diff --git a/.cron.yml b/.cron.yml index 3c709be4a98f..6e9b753f67f0 100644 --- a/.cron.yml +++ b/.cron.yml @@ -115,3 +115,6 @@ jobs: mozilla-central: - {weekday: 'Monday', hour: 10, minute: 0} - {weekday: 'Thursday', hour: 10, minute: 0} + mozilla-esr60: + - {weekday: 'Monday', hour: 10, minute: 0} + - {weekday: 'Thursday', hour: 10, minute: 0} diff --git a/accessible/interfaces/msaa/ISimpleDOMNode.idl b/accessible/interfaces/msaa/ISimpleDOMNode.idl index 0e9671a90fbc..fbf104adca69 100644 --- a/accessible/interfaces/msaa/ISimpleDOMNode.idl +++ b/accessible/interfaces/msaa/ISimpleDOMNode.idl @@ -42,7 +42,7 @@ cpp_quote("//") cpp_quote("// computedStyle( ") cpp_quote("// /* [in] */ unsigned short maxStyleProperties,") cpp_quote("// /* [out] */ unsigned short *numStyleProperties, ") -cpp_quote("// /* [in] */ boolean useAlternateView, // If TRUE, returns properites for media as set in nsIDOMDocument::set_alternateViewMediaTypes") +cpp_quote("// /* [in] */ boolean useAlternateView, // If TRUE, returns properites for media as set in Document's set_alternateViewMediaTypes") cpp_quote("// /* [out] */ BSTR *styleProperties, ") cpp_quote("// /* [out] */ BSTR *styleValues);") cpp_quote("// ---------------------------------------------------------------------------------------------------=") @@ -52,7 +52,7 @@ cpp_quote("// useAlternateView=TRUE: properties for media types set w/ nsIDOMSi cpp_quote("//") cpp_quote("// computedStyleForProperties( ") cpp_quote("// /* [in] */ unsigned short numStyleProperties, ") -cpp_quote("// /* [in] */ boolean useAlternateView, // If TRUE, returns properites for media as set in nsIDOMDocument::set_alternateViewMediaTypes") +cpp_quote("// /* [in] */ boolean useAlternateView, // If TRUE, returns properites for media as set in Document's set_alternateViewMediaTypes") cpp_quote("// /* [in] */ BSTR *styleProperties, ") cpp_quote("// /* [out] */ BSTR *styleValues);") cpp_quote("// ---------------------------------------------------------------------------------------------------=") @@ -141,7 +141,7 @@ interface ISimpleDOMNode : IUnknown [propget] HRESULT computedStyle( [in] unsigned short maxStyleProperties, - [in] boolean useAlternateView, // If TRUE, returns properites for media as set in nsIDOMDocument::set_alternateViewMediaTypes + [in] boolean useAlternateView, // If TRUE, returns properites for media as set in Document's set_alternateViewMediaTypes [out, size_is(maxStyleProperties), length_is(*numStyleProperties)] BSTR *styleProperties, [out, size_is(maxStyleProperties), length_is(*numStyleProperties)] BSTR *styleValues, [out, retval] unsigned short *numStyleProperties @@ -149,7 +149,7 @@ interface ISimpleDOMNode : IUnknown [propget] HRESULT computedStyleForProperties( [in] unsigned short numStyleProperties, - [in] boolean useAlternateView, // If TRUE, returns properites for media as set in nsIDOMDocument::set_alternateViewMediaTypes + [in] boolean useAlternateView, // If TRUE, returns properites for media as set in Document's set_alternateViewMediaTypes [in, size_is(numStyleProperties), length_is(numStyleProperties)] BSTR *styleProperties, [out, retval, size_is(numStyleProperties), length_is(numStyleProperties)] BSTR *styleValues ); diff --git a/accessible/tests/mochitest/common.js b/accessible/tests/mochitest/common.js index 5fdf629e8cfd..2714cf82c5c5 100644 --- a/accessible/tests/mochitest/common.js +++ b/accessible/tests/mochitest/common.js @@ -44,7 +44,6 @@ const nsIAccessibleValue = Ci.nsIAccessibleValue; const nsIObserverService = Ci.nsIObserverService; -const nsIDOMDocument = Ci.nsIDOMDocument; const nsIDOMNode = Ci.nsIDOMNode; const nsIDOMWindow = Ci.nsIDOMWindow; diff --git a/accessible/tests/mochitest/events.js b/accessible/tests/mochitest/events.js index ca20d33d262a..83d4fd166bf5 100644 --- a/accessible/tests/mochitest/events.js +++ b/accessible/tests/mochitest/events.js @@ -1062,7 +1062,7 @@ function synthClick(aNodeOrID, aCheckerOrEventSeq, aArgs) { this.invoke = function synthClick_invoke() { var targetNode = this.DOMNode; - if (targetNode instanceof nsIDOMDocument) { + if (targetNode.nodeType == targetNode.DOCUMENT_NODE) { targetNode = this.DOMNode.body ? this.DOMNode.body : this.DOMNode.documentElement; } diff --git a/accessible/tests/mochitest/test_nsIAccessibleDocument.html b/accessible/tests/mochitest/test_nsIAccessibleDocument.html index 32cb3dbc0f16..e90c5dab0fe6 100644 --- a/accessible/tests/mochitest/test_nsIAccessibleDocument.html +++ b/accessible/tests/mochitest/test_nsIAccessibleDocument.html @@ -56,12 +56,12 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=441737 // is(docAcc.docType, "HTML", // "Wrong type of document!"); - // Test for correct nsIDOMDocument retrieval. + // Test for correct Document retrieval. var domDoc = null; try { - domDoc = docAcc.DOMDocument.QueryInterface(nsIDOMDocument); + domDoc = docAcc.DOMDocument; } catch (e) {} - ok(domDoc, "no nsIDOMDocument for this doc accessible!"); + ok(domDoc, "no Document for this doc accessible!"); is(domDoc, document, "Document nodes do not match!"); // Test for correct nsIDOMWindow retrieval. diff --git a/browser/base/content/content.js b/browser/base/content/content.js index c838977a5348..63c9323f52b1 100644 --- a/browser/base/content/content.js +++ b/browser/base/content/content.js @@ -588,12 +588,8 @@ var AboutNetAndCertErrorListener = { }, handleEvent(aEvent) { - let doc; - if (aEvent.originalTarget instanceof Ci.nsIDOMDocument) { - doc = aEvent.originalTarget; - } else { - doc = aEvent.originalTarget.ownerDocument; - } + // Documents have a null ownerDocument. + let doc = aEvent.originalTarget.ownerDocument || aEvent.originalTarget; if (!this.isAboutNetError(doc) && !this.isAboutCertError(doc)) { return; diff --git a/browser/base/content/test/general/browser_tabfocus.js b/browser/base/content/test/general/browser_tabfocus.js index a70778c48a87..0719b12d6b9d 100644 --- a/browser/base/content/test/general/browser_tabfocus.js +++ b/browser/base/content/test/general/browser_tabfocus.js @@ -74,7 +74,7 @@ function focusInChild() { var id; if (event.target instanceof Ci.nsIDOMWindow) id = getWindowDocId(event.originalTarget) + "-window"; - else if (event.target instanceof Ci.nsIDOMDocument) + else if (event.target.nodeType == event.target.DOCUMENT_NODE) id = getWindowDocId(event.originalTarget) + "-document"; else id = event.originalTarget.id; diff --git a/browser/components/extensions/parent/ext-tabs.js b/browser/components/extensions/parent/ext-tabs.js index 3b8597921ada..edb980c70b8c 100644 --- a/browser/components/extensions/parent/ext-tabs.js +++ b/browser/components/extensions/parent/ext-tabs.js @@ -966,8 +966,8 @@ this.tabs = class extends ExtensionAPI { let browser = event.originalTarget; // For non-remote browsers, this event is dispatched on the document - // rather than on the . - if (browser instanceof Ci.nsIDOMDocument) { + // rather than on the . But either way we have a node here. + if (browser.nodeType == browser.DOCUMENT_NODE) { browser = browser.docShell.chromeEventHandler; } diff --git a/browser/extensions/pdfjs/README.mozilla b/browser/extensions/pdfjs/README.mozilla index 9a94b248e5f1..dd279756dbc2 100644 --- a/browser/extensions/pdfjs/README.mozilla +++ b/browser/extensions/pdfjs/README.mozilla @@ -1,5 +1,5 @@ This is the PDF.js project output, https://github.com/mozilla/pdf.js -Current extension version is: 2.0.506 +Current extension version is: 2.0.517 -Taken from upstream commit: b7a3a5e7 +Taken from upstream commit: 7cd6c0fb diff --git a/browser/extensions/pdfjs/content/build/pdf.js b/browser/extensions/pdfjs/content/build/pdf.js index bce26136246c..a79293eb2337 100644 --- a/browser/extensions/pdfjs/content/build/pdf.js +++ b/browser/extensions/pdfjs/content/build/pdf.js @@ -1650,8 +1650,8 @@ exports.GlobalWorkerOptions = GlobalWorkerOptions; "use strict"; -var pdfjsVersion = '2.0.506'; -var pdfjsBuild = 'b7a3a5e7'; +var pdfjsVersion = '2.0.517'; +var pdfjsBuild = '7cd6c0fb'; var pdfjsSharedUtil = __w_pdfjs_require__(0); var pdfjsDisplayAPI = __w_pdfjs_require__(9); var pdfjsDisplayTextLayer = __w_pdfjs_require__(17); @@ -4929,7 +4929,7 @@ function _fetchDocument(worker, source, pdfDataRangeTransport, docId) { } return worker.messageHandler.sendWithPromise('GetDocRequest', { docId, - apiVersion: '2.0.506', + apiVersion: '2.0.517', source: { data: source.data, url: source.url, @@ -6252,8 +6252,8 @@ var InternalRenderTask = function InternalRenderTaskClosure() { }(); var version, build; { - exports.version = version = '2.0.506'; - exports.build = build = 'b7a3a5e7'; + exports.version = version = '2.0.517'; + exports.build = build = '7cd6c0fb'; } exports.getDocument = getDocument; exports.LoopbackPort = LoopbackPort; diff --git a/browser/extensions/pdfjs/content/build/pdf.worker.js b/browser/extensions/pdfjs/content/build/pdf.worker.js index 949bb48449a4..f441089e327a 100644 --- a/browser/extensions/pdfjs/content/build/pdf.worker.js +++ b/browser/extensions/pdfjs/content/build/pdf.worker.js @@ -21103,8 +21103,8 @@ exports.PostScriptCompiler = PostScriptCompiler; "use strict"; -var pdfjsVersion = '2.0.506'; -var pdfjsBuild = 'b7a3a5e7'; +var pdfjsVersion = '2.0.517'; +var pdfjsBuild = '7cd6c0fb'; var pdfjsCoreWorker = __w_pdfjs_require__(20); exports.WorkerMessageHandler = pdfjsCoreWorker.WorkerMessageHandler; @@ -21305,7 +21305,7 @@ var WorkerMessageHandler = { var cancelXHRs = null; var WorkerTasks = []; let apiVersion = docParams.apiVersion; - let workerVersion = '2.0.506'; + let workerVersion = '2.0.517'; if (apiVersion !== null && apiVersion !== workerVersion) { throw new Error(`The API version "${apiVersion}" does not match ` + `the Worker version "${workerVersion}".`); } @@ -36238,10 +36238,9 @@ var Type1Parser = function Type1ParserClosure() { var glyph = this.getToken(); length = this.readInt(); this.getToken(); - data = stream.makeSubStream(stream.pos, length); + data = length > 0 ? stream.getBytes(length) : new Uint8Array(0); lenIV = program.properties.privateData['lenIV']; - encoded = this.readCharStrings(data.getBytes(), lenIV); - stream.skip(length); + encoded = this.readCharStrings(data, lenIV); this.nextChar(); token = this.getToken(); if (token === 'noaccess') { @@ -36260,10 +36259,9 @@ var Type1Parser = function Type1ParserClosure() { var index = this.readInt(); length = this.readInt(); this.getToken(); - data = stream.makeSubStream(stream.pos, length); + data = length > 0 ? stream.getBytes(length) : new Uint8Array(0); lenIV = program.properties.privateData['lenIV']; - encoded = this.readCharStrings(data.getBytes(), lenIV); - stream.skip(length); + encoded = this.readCharStrings(data, lenIV); this.nextChar(); token = this.getToken(); if (token === 'noaccess') { diff --git a/browser/extensions/pdfjs/content/web/viewer.js b/browser/extensions/pdfjs/content/web/viewer.js index f885a68e513a..de046b7ce93e 100644 --- a/browser/extensions/pdfjs/content/web/viewer.js +++ b/browser/extensions/pdfjs/content/web/viewer.js @@ -95,7 +95,7 @@ Object.defineProperty(exports, "__esModule", { value: true }); -exports.moveToEndOfArray = exports.waitOnEventOrTimeout = exports.WaitOnType = exports.animationStarted = exports.normalizeWheelEventDelta = exports.binarySearchFirstItem = exports.watchScroll = exports.scrollIntoView = exports.getOutputScale = exports.approximateFraction = exports.getPageSizeInches = exports.roundToDivide = exports.getVisibleElements = exports.backtrackBeforeAllVisibleElements = exports.parseQueryString = exports.noContextMenuHandler = exports.getPDFFileNameFromURL = exports.ProgressBar = exports.EventBus = exports.NullL10n = exports.TextLayerMode = exports.RendererType = exports.PresentationModeState = exports.cloneObj = exports.isFileSchema = exports.isPortraitOrientation = exports.isValidRotation = exports.VERTICAL_PADDING = exports.SCROLLBAR_PADDING = exports.MAX_AUTO_SCALE = exports.UNKNOWN_SCALE = exports.MAX_SCALE = exports.MIN_SCALE = exports.DEFAULT_SCALE = exports.DEFAULT_SCALE_VALUE = exports.CSS_UNITS = undefined; +exports.moveToEndOfArray = exports.waitOnEventOrTimeout = exports.WaitOnType = exports.animationStarted = exports.normalizeWheelEventDelta = exports.binarySearchFirstItem = exports.watchScroll = exports.scrollIntoView = exports.getOutputScale = exports.approximateFraction = exports.getPageSizeInches = exports.roundToDivide = exports.getVisibleElements = exports.backtrackBeforeAllVisibleElements = exports.parseQueryString = exports.noContextMenuHandler = exports.getPDFFileNameFromURL = exports.ProgressBar = exports.EventBus = exports.NullL10n = exports.TextLayerMode = exports.RendererType = exports.PresentationModeState = exports.cloneObj = exports.isPortraitOrientation = exports.isValidRotation = exports.VERTICAL_PADDING = exports.SCROLLBAR_PADDING = exports.MAX_AUTO_SCALE = exports.UNKNOWN_SCALE = exports.MAX_SCALE = exports.MIN_SCALE = exports.DEFAULT_SCALE = exports.DEFAULT_SCALE_VALUE = exports.CSS_UNITS = undefined; var _pdfjsLib = __webpack_require__(1); @@ -397,14 +397,6 @@ function getVisibleElements(scrollEl, views, sortByVisibility = false, horizonta function noContextMenuHandler(evt) { evt.preventDefault(); } -function isFileSchema(url) { - let i = 0, - ii = url.length; - while (i < ii && url[i].trim() === '') { - i++; - } - return url.substr(i, 7).toLowerCase() === 'file://'; -} function isDataSchema(url) { let i = 0, ii = url.length; @@ -614,7 +606,6 @@ exports.SCROLLBAR_PADDING = SCROLLBAR_PADDING; exports.VERTICAL_PADDING = VERTICAL_PADDING; exports.isValidRotation = isValidRotation; exports.isPortraitOrientation = isPortraitOrientation; -exports.isFileSchema = isFileSchema; exports.cloneObj = cloneObj; exports.PresentationModeState = PresentationModeState; exports.RendererType = RendererType; @@ -1438,11 +1429,6 @@ let PDFViewerApplication = { parameters[prop] = args[prop]; } } - if (this.url && (0, _ui_utils.isFileSchema)(this.url)) { - let appConfig = this.appConfig; - appConfig.toolbar.download.setAttribute('hidden', 'true'); - appConfig.secondaryToolbar.downloadButton.setAttribute('hidden', 'true'); - } let loadingTask = (0, _pdfjsLib.getDocument)(parameters); this.pdfLoadingTask = loadingTask; loadingTask.onPassword = (updateCallback, reason) => { diff --git a/browser/modules/Sanitizer.jsm b/browser/modules/Sanitizer.jsm index 303a5e1ca513..6fd30f708835 100644 --- a/browser/modules/Sanitizer.jsm +++ b/browser/modules/Sanitizer.jsm @@ -17,6 +17,7 @@ XPCOMUtils.defineLazyModuleGetters(this, { setTimeout: "resource://gre/modules/Timer.jsm", ServiceWorkerCleanUp: "resource://gre/modules/ServiceWorkerCleanUp.jsm", OfflineAppCacheHelper: "resource://gre/modules/offlineAppCache.jsm", + ContextualIdentityService: "resource://gre/modules/ContextualIdentityService.jsm", }); XPCOMUtils.defineLazyServiceGetter(this, "sas", @@ -71,6 +72,12 @@ var Sanitizer = { */ PREF_TIMESPAN: "privacy.sanitize.timeSpan", + /** + * Pref to newTab segregation. If true, on shutdown, the private container + * used in about:newtab is cleaned up. Exposed because used in tests. + */ + PREF_NEWTAB_SEGREGATION: "privacy.usercontext.about_newtab_segregation.enabled", + /** * Time span constants corresponding to values of the privacy.sanitize.timeSpan * pref. Used to determine how much history to clear, for various items @@ -91,6 +98,11 @@ var Sanitizer = { */ shouldSanitizeOnShutdown: false, + /** + * Whether we should sanitize the private container for about:newtab. + */ + shouldSanitizeNewTabContainer: false, + /** * Shows a sanitization dialog to the user. * @@ -145,6 +157,17 @@ var Sanitizer = { {fetchState: () => ({ progress })} ); + this.shouldSanitizeNewTabContainer = Services.prefs.getBoolPref(this.PREF_NEWTAB_SEGREGATION, false); + if (this.shouldSanitizeNewTabContainer) { + addPendingSanitization("newtab-container", [], {}); + } + + let i = pendingSanitizations.findIndex(s => s.id == "newtab-container"); + if (i != -1) { + pendingSanitizations.splice(i, 1); + sanitizeNewTabSegregation(); + } + // Finally, run the sanitizations that were left pending, because we crashed // before completing them. for (let {itemsToClear, options} of pendingSanitizations) { @@ -272,6 +295,12 @@ var Sanitizer = { let itemsToClear = getItemsToClearFromPrefBranch(Sanitizer.PREF_SHUTDOWN_BRANCH); addPendingSanitization("shutdown", itemsToClear, {}); } + } else if (data == this.PREF_NEWTAB_SEGREGATION) { + this.shouldSanitizeNewTabContainer = Services.prefs.getBoolPref(this.PREF_NEWTAB_SEGREGATION, false); + removePendingSanitization("newtab-container"); + if (this.shouldSanitizeNewTabContainer) { + addPendingSanitization("newtab-container", [], {}); + } } } }, @@ -990,6 +1019,11 @@ async function sanitizeOnShutdown(progress) { } } + if (Sanitizer.shouldSanitizeNewTabContainer) { + sanitizeNewTabSegregation(); + removePendingSanitization("newtab-container"); + } + if (Sanitizer.shouldSanitizeOnShutdown) { // We didn't crash during shutdown sanitization, so annotate it to avoid // sanitizing again on startup. @@ -1061,6 +1095,14 @@ async function sanitizeSessionPrincipal(principal) { ]); } +function sanitizeNewTabSegregation() { + let identity = ContextualIdentityService.getPrivateIdentity("userContextIdInternal.thumbnail"); + if (identity) { + Services.obs.notifyObservers(null, "clear-origin-attributes-data", + JSON.stringify({ userContextId: identity.userContextId })); + } +} + /** * Gets an array of items to clear from the given pref branch. * @param branch The pref branch to fetch. diff --git a/browser/modules/test/unit/test_Sanitizer_interrupted.js b/browser/modules/test/unit/test_Sanitizer_interrupted.js index 707b8b6431d6..575f113921be 100644 --- a/browser/modules/test/unit/test_Sanitizer_interrupted.js +++ b/browser/modules/test/unit/test_Sanitizer_interrupted.js @@ -11,9 +11,13 @@ do_get_profile(); add_task(async function() { ChromeUtils.import("resource:///modules/Sanitizer.jsm"); + + Services.prefs.setBoolPref(Sanitizer.PREF_NEWTAB_SEGREGATION, false); + registerCleanupFunction(() => { Services.prefs.clearUserPref(Sanitizer.PREF_SANITIZE_ON_SHUTDOWN); Services.prefs.clearUserPref(Sanitizer.PREF_SHUTDOWN_BRANCH + "formdata"); + Services.prefs.clearUserPref(Sanitizer.PREF_NEWTAB_SEGREGATION); }); Services.prefs.setBoolPref(Sanitizer.PREF_SANITIZE_ON_SHUTDOWN, true); Services.prefs.setBoolPref(Sanitizer.PREF_SHUTDOWN_BRANCH + "formdata", true); diff --git a/devtools/client/debugger/new/README.mozilla b/devtools/client/debugger/new/README.mozilla index 3b4f93efac95..9b4cdb6d34f1 100644 --- a/devtools/client/debugger/new/README.mozilla +++ b/devtools/client/debugger/new/README.mozilla @@ -1,13 +1,13 @@ This is the debugger.html project output. See https://github.com/devtools-html/debugger.html -Version 58 +Version 60 -Comparison: https://github.com/devtools-html/debugger.html/compare/release-57...release-58 +Comparison: https://github.com/devtools-html/debugger.html/compare/release-59...release-60 Packages: - babel-plugin-transform-es2015-modules-commonjs @6.26.2 - babel-preset-react @6.24.1 - react @16.2.0 - react-dom @16.2.0 -- webpack @3.12.0 +- webpack @3.11.0 diff --git a/devtools/client/debugger/new/dist/debugger.css b/devtools/client/debugger/new/dist/debugger.css index d0c926e50cfe..0017087554ab 100644 --- a/devtools/client/debugger/new/dist/debugger.css +++ b/devtools/client/debugger/new/dist/debugger.css @@ -1108,7 +1108,10 @@ html .toggle-button.end.vertical svg { .search-field i.magnifying-glass, .search-field i.sad-face { - padding: 6px; + padding-top: 5px; + padding-bottom: 5px; + padding-inline-end: 10px; + padding-inline-start: 5px; width: 24px; } @@ -1118,6 +1121,11 @@ html .toggle-button.end.vertical svg { width: 40px; } +.search-field.big i.sad-face { + padding-top: 4px; + padding-inline-start: 4px; +} + .search-field .magnifying-glass path, .search-field .magnifying-glass ellipse { stroke: var(--theme-comment); @@ -1134,18 +1142,13 @@ html .toggle-button.end.vertical svg { .search-field .summary { line-height: 27px; text-align: center; - padding-right: 10px; + padding-inline-end: 10px; color: var(--theme-body-color-inactive); align-self: center; padding-top: 1px; white-space: nowrap; } -.search-field.big .summary { - padding: 5px 0 5px 0; - line-height: 2rem; -} - .search-field .search-nav-buttons { display: flex; user-select: none; @@ -1261,7 +1264,7 @@ html .toggle-button.end.vertical svg { } .project-text-search .search-field .close-btn.big { - margin-top: 6px; + margin-top: 2px; } .project-text-search .managed-tree { @@ -3077,7 +3080,7 @@ html[dir="rtl"] .breakpoints-list .breakpoint .breakpoint-line { max-width: calc(100% - var(--breakpoint-expression-right-clear-space)); display: inline-block; padding-inline-end: 8px; - cursor: default; + cursor: pointer; flex-grow: 1; text-overflow: ellipsis; overflow: hidden; @@ -3261,7 +3264,7 @@ html[dir="rtl"] .breakpoints-list .breakpoint .breakpoint-line { .expression-container__close-btn { position: absolute; offset-inline-end: 0px; - top: 0px; + top: 1px; } .expression-content { @@ -4049,6 +4052,7 @@ html .welcomebox .toggle-button-end.collapsed { position: relative; transition: all 0.15s ease; min-width: 40px; + max-width: 100%; overflow: hidden; padding: 5px; margin-inline-start: 3px; diff --git a/devtools/client/debugger/new/dist/parser-worker.js b/devtools/client/debugger/new/dist/parser-worker.js index fead7a6b9d59..f3a93442fdd2 100644 --- a/devtools/client/debugger/new/dist/parser-worker.js +++ b/devtools/client/debugger/new/dist/parser-worker.js @@ -22811,7 +22811,7 @@ function toParsedScopes(children, sourceId) { return { start: scope.loc.start, end: scope.loc.end, - type: scope.type === "module" ? "block" : scope.type, + type: scope.type === "module" || scope.type === "function-body" ? "block" : scope.type, displayName: scope.displayName, bindings: scope.bindings, children: toParsedScopes(scope.children, sourceId) @@ -22906,9 +22906,18 @@ function isLetOrConst(node) { } function hasLexicalDeclaration(node, parent) { + const nodes = []; + if (t.isSwitchStatement(node)) { + for (const caseNode of node.cases) { + nodes.push(...caseNode.consequent); + } + } else { + nodes.push(...node.body); + } + const isFunctionBody = t.isFunction(parent, { body: node }); - return node.body.some(child => isLexicalVariable(child) || !isFunctionBody && child.type === "FunctionDeclaration" || child.type === "ClassDeclaration"); + return nodes.some(child => isLexicalVariable(child) || t.isClassDeclaration(child) || !isFunctionBody && t.isFunctionDeclaration(child)); } function isLexicalVariable(node) { return isNode(node, "VariableDeclaration") && isLetOrConst(node); @@ -22973,19 +22982,27 @@ const scopeCollectionVisitor = { // This ignores Annex B function declaration hoisting, which // is probably a fine assumption. state.declarationBindingIds.add(node.id); - const fnScope = getVarScope(scope); - scope.bindings[node.id.name] = { - type: fnScope === scope ? "var" : "let", - refs: [{ - type: "fn-decl", - start: fromBabelLocation(node.id.loc.start, state.sourceId), - end: fromBabelLocation(node.id.loc.end, state.sourceId), - declaration: { - start: fromBabelLocation(node.loc.start, state.sourceId), - end: fromBabelLocation(node.loc.end, state.sourceId) - } - }] - }; + const refs = [{ + type: "fn-decl", + start: fromBabelLocation(node.id.loc.start, state.sourceId), + end: fromBabelLocation(node.id.loc.end, state.sourceId), + declaration: { + start: fromBabelLocation(node.loc.start, state.sourceId), + end: fromBabelLocation(node.loc.end, state.sourceId) + } + }]; + + if (scope.type === "block") { + scope.bindings[node.id.name] = { + type: "let", + refs + }; + } else { + getVarScope(scope).bindings[node.id.name] = { + type: "var", + refs + }; + } } scope = pushTempScope(state, "function", (0, _getFunctionName2.default)(node, parentNode), { @@ -23007,6 +23024,13 @@ const scopeCollectionVisitor = { refs: [] }; } + + if (t.isBlockStatement(node.body) && hasLexicalDeclaration(node.body, node)) { + scope = pushTempScope(state, "function-body", "Function Body", { + start: fromBabelLocation(node.body.loc.start, state.sourceId), + end: fromBabelLocation(node.body.loc.end, state.sourceId) + }); + } } else if (t.isClass(node)) { if (t.isIdentifier(node.id)) { // For decorated classes, the AST considers the first the decorator @@ -23075,7 +23099,9 @@ const scopeCollectionVisitor = { end: fromBabelLocation(node.loc.end, state.sourceId) }); parseDeclarator(node.param, scope, "var", "catch", node, state); - } else if (t.isBlockStatement(node) && hasLexicalDeclaration(node, parentNode)) { + } else if (t.isBlockStatement(node) && + // Function body's are handled in the function logic above. + !t.isFunction(parentNode) && hasLexicalDeclaration(node, parentNode)) { // Debugger will create new lexical environment for the block. pushTempScope(state, "block", "Block", { start: fromBabelLocation(node.loc.start, state.sourceId), @@ -23199,7 +23225,7 @@ const scopeCollectionVisitor = { type: "implicit", refs: [] }; - } else if (t.isSwitchStatement(node) && node.cases.some(caseNode => caseNode.consequent.some(child => isLexicalVariable(child)))) { + } else if (t.isSwitchStatement(node) && hasLexicalDeclaration(node, parentNode)) { pushTempScope(state, "block", "Switch", { start: fromBabelLocation(node.loc.start, state.sourceId), end: fromBabelLocation(node.loc.end, state.sourceId) @@ -25012,6 +25038,7 @@ const { const dispatcher = new WorkerDispatcher(); const getOriginalURLs = dispatcher.task("getOriginalURLs"); +const getOriginalRanges = dispatcher.task("getOriginalRanges"); const getGeneratedRanges = dispatcher.task("getGeneratedRanges", { queue: true }); @@ -25035,6 +25062,7 @@ module.exports = { isOriginalId, hasMappedSource, getOriginalURLs, + getOriginalRanges, getGeneratedRanges, getGeneratedLocation, getAllGeneratedLocations, diff --git a/devtools/client/debugger/new/src/actions/breakpoints.js b/devtools/client/debugger/new/src/actions/breakpoints.js index 8b85ac66a0e4..d341384b536d 100644 --- a/devtools/client/debugger/new/src/actions/breakpoints.js +++ b/devtools/client/debugger/new/src/actions/breakpoints.js @@ -417,7 +417,7 @@ function toggleBreakpoint(line, column) { line, column }); - const isEmptyLine = (0, _ast.isEmptyLineInSource)(state, line, selectedSource); + const isEmptyLine = (0, _ast.isEmptyLineInSource)(state, line, selectedSource.id); if (!bp && isEmptyLine || bp && bp.loading) { return; @@ -434,8 +434,8 @@ function toggleBreakpoint(line, column) { } return dispatch(addBreakpoint({ - sourceId: selectedSource.get("id"), - sourceUrl: selectedSource.get("url"), + sourceId: selectedSource.id, + sourceUrl: selectedSource.url, line: line, column: column })); diff --git a/devtools/client/debugger/new/src/actions/navigation.js b/devtools/client/debugger/new/src/actions/navigation.js index f3f873d2c895..de9c04519850 100644 --- a/devtools/client/debugger/new/src/actions/navigation.js +++ b/devtools/client/debugger/new/src/actions/navigation.js @@ -51,7 +51,6 @@ function willNavigate(event) { await sourceMaps.clearSourceMaps(); (0, _wasm.clearWasmStates)(); (0, _editor.clearDocuments)(); - (0, _editor.removeEditor)(); (0, _parser.clearSymbols)(); (0, _parser.clearASTs)(); (0, _parser.clearScopes)(); diff --git a/devtools/client/debugger/new/src/actions/sources/loadSourceText.js b/devtools/client/debugger/new/src/actions/sources/loadSourceText.js index 2da070f11f81..4228e67f4b55 100644 --- a/devtools/client/debugger/new/src/actions/sources/loadSourceText.js +++ b/devtools/client/debugger/new/src/actions/sources/loadSourceText.js @@ -41,7 +41,7 @@ async function loadSource(source, { const id = source.get("id"); if ((0, _devtoolsSourceMap.isOriginalId)(id)) { - return await sourceMaps.getOriginalSourceText(source.toJS()); + return sourceMaps.getOriginalSourceText(source.toJS()); } const response = await client.sourceContents(id); diff --git a/devtools/client/debugger/new/src/components/Editor/EditorMenu.js b/devtools/client/debugger/new/src/components/Editor/EditorMenu.js index b237383db7b4..08bd9b34fb97 100644 --- a/devtools/client/debugger/new/src/components/Editor/EditorMenu.js +++ b/devtools/client/debugger/new/src/components/Editor/EditorMenu.js @@ -211,9 +211,9 @@ const mapStateToProps = state => { return { selectedLocation: (0, _selectors.getSelectedLocation)(state), selectedSource, - hasPrettyPrint: !!(0, _selectors.getPrettySource)(state, selectedSource.get("id")), + hasPrettyPrint: !!(0, _selectors.getPrettySource)(state, selectedSource.id), contextMenu: (0, _selectors.getContextMenu)(state), - getFunctionText: line => (0, _function.findFunctionText)(line, selectedSource.toJS(), symbols), + getFunctionText: line => (0, _function.findFunctionText)(line, selectedSource, symbols), getFunctionLocation: line => (0, _ast.findClosestFunction)(symbols, { line, column: Infinity diff --git a/devtools/client/debugger/new/src/components/Editor/EmptyLines.js b/devtools/client/debugger/new/src/components/Editor/EmptyLines.js index 0a71012633ee..3423790d33a1 100644 --- a/devtools/client/debugger/new/src/components/Editor/EmptyLines.js +++ b/devtools/client/debugger/new/src/components/Editor/EmptyLines.js @@ -70,7 +70,7 @@ class EmptyLines extends _react.Component { const mapStateToProps = state => { const selectedSource = (0, _selectors.getSelectedSource)(state); - const foundEmptyLines = (0, _selectors.getEmptyLines)(state, selectedSource.toJS()); + const foundEmptyLines = (0, _selectors.getEmptyLines)(state, selectedSource.id); return { selectedSource, emptyLines: selectedSource ? foundEmptyLines : [] diff --git a/devtools/client/debugger/new/src/components/Editor/GutterMenu.js b/devtools/client/debugger/new/src/components/Editor/GutterMenu.js index 15b75300a7cf..4a953b8a35b5 100644 --- a/devtools/client/debugger/new/src/components/Editor/GutterMenu.js +++ b/devtools/client/debugger/new/src/components/Editor/GutterMenu.js @@ -169,7 +169,7 @@ const mapStateToProps = state => { breakpoints: (0, _selectors.getVisibleBreakpoints)(state), isPaused: (0, _selectors.isPaused)(state), contextMenu: (0, _selectors.getContextMenu)(state), - emptyLines: (0, _selectors.getEmptyLines)(state, selectedSource.toJS()) + emptyLines: (0, _selectors.getEmptyLines)(state, selectedSource.id) }; }; diff --git a/devtools/client/debugger/new/src/components/Editor/Tab.js b/devtools/client/debugger/new/src/components/Editor/Tab.js index 9fcc91ce23b3..7b1028752203 100644 --- a/devtools/client/debugger/new/src/components/Editor/Tab.js +++ b/devtools/client/debugger/new/src/components/Editor/Tab.js @@ -18,6 +18,8 @@ var _SourceIcon2 = _interopRequireDefault(_SourceIcon); var _Button = require("../shared/Button/index"); +var _text = require("../../utils/text"); + var _actions = require("../../actions/index"); var _actions2 = _interopRequireDefault(_actions); @@ -175,7 +177,7 @@ class Tab extends _react.PureComponent { shouldHide: icon => ["file", "javascript"].includes(icon) }), _react2.default.createElement("div", { className: "filename" - }, (0, _devtoolsModules.getUnicodeUrlPath)(filename)), _react2.default.createElement(_Button.CloseButton, { + }, (0, _text.truncateMiddleText)((0, _devtoolsModules.getUnicodeUrlPath)(filename), 30)), _react2.default.createElement(_Button.CloseButton, { handleClick: onClickClose, tooltip: L10N.getStr("sourceTabs.closeTabButtonTooltip") })); diff --git a/devtools/client/debugger/new/src/components/SecondaryPanes/Breakpoint.js b/devtools/client/debugger/new/src/components/SecondaryPanes/Breakpoint.js deleted file mode 100644 index cafe4b0cdf30..000000000000 --- a/devtools/client/debugger/new/src/components/SecondaryPanes/Breakpoint.js +++ /dev/null @@ -1,198 +0,0 @@ -"use strict"; - -Object.defineProperty(exports, "__esModule", { - value: true -}); - -var _react = require("devtools/client/shared/vendor/react"); - -var _react2 = _interopRequireDefault(_react); - -var _reactDom = require("devtools/client/shared/vendor/react-dom"); - -var _reactDom2 = _interopRequireDefault(_reactDom); - -var _classnames = require("devtools/client/debugger/new/dist/vendors").vendored["classnames"]; - -var _classnames2 = _interopRequireDefault(_classnames); - -var _devtoolsSourceMap = require("devtools/client/shared/source-map/index.js"); - -var _Button = require("../shared/Button/index"); - -var _breakpoint = require("../../utils/breakpoint/index"); - -var _prefs = require("../../utils/prefs"); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at . */ -function getBreakpointLocation(source, line, column) { - const isWasm = source && source.isWasm; - const columnVal = _prefs.features.columnBreakpoints && column ? `:${column}` : ""; - const bpLocation = isWasm ? `0x${line.toString(16).toUpperCase()}` : `${line}${columnVal}`; - return bpLocation; -} - -function getBreakpointText(selectedSource, breakpoint) { - const { - condition, - text, - originalText - } = breakpoint; - - if (condition) { - return condition; - } - - if (!selectedSource || (0, _devtoolsSourceMap.isGeneratedId)(selectedSource.id) || originalText.length == 0) { - return text; - } - - return originalText; -} - -class Breakpoint extends _react.Component { - componentDidMount() { - this.setupEditor(); - } - - componentDidUpdate(prevProps) { - if (getBreakpointText(this.props.selectedSource, this.props.breakpoint) != getBreakpointText(prevProps.selectedSource, prevProps.breakpoint)) { - this.destroyEditor(); - } - - this.setupEditor(); - } - - componentWillUnmount() { - this.destroyEditor(); - } - - shouldComponentUpdate(nextProps) { - const prevBreakpoint = this.props.breakpoint; - const nextBreakpoint = nextProps.breakpoint; - return !prevBreakpoint || this.props.selectedSource != nextProps.selectedSource || prevBreakpoint.text != nextBreakpoint.text || prevBreakpoint.disabled != nextBreakpoint.disabled || prevBreakpoint.condition != nextBreakpoint.condition || prevBreakpoint.hidden != nextBreakpoint.hidden || prevBreakpoint.isCurrentlyPaused != nextBreakpoint.isCurrentlyPaused; - } - - destroyEditor() { - if (this.editor) { - this.editor.destroy(); - this.editor = null; - } - } - - setupEditor() { - if (this.editor) { - return; - } - - const { - selectedSource, - breakpoint - } = this.props; - this.editor = (0, _breakpoint.createEditor)(getBreakpointText(selectedSource, breakpoint)); // disables the default search shortcuts - // $FlowIgnore - - this.editor._initShortcuts = () => {}; - - const node = _reactDom2.default.findDOMNode(this); - - if (node instanceof HTMLElement) { - const mountNode = node.querySelector(".breakpoint-label"); - - if (node instanceof HTMLElement) { - // $FlowIgnore - mountNode.innerHTML = ""; - this.editor.appendToLocalElement(mountNode); - this.editor.codeMirror.on("mousedown", (_, e) => e.preventDefault()); - } - } - } - - renderCheckbox() { - const { - onChange, - breakpoint - } = this.props; - const { - disabled - } = breakpoint; - return _react2.default.createElement("input", { - type: "checkbox", - className: "breakpoint-checkbox", - checked: !disabled, - onChange: onChange, - onClick: ev => ev.stopPropagation() - }); - } - - renderText() { - const { - selectedSource, - breakpoint - } = this.props; - const text = getBreakpointText(selectedSource, breakpoint); - return _react2.default.createElement("label", { - className: "breakpoint-label", - title: text - }, text); - } - - renderLineClose() { - const { - breakpoint, - onCloseClick, - selectedSource - } = this.props; - const { - location - } = breakpoint; - let { - line, - column - } = location; - - if (selectedSource && (0, _devtoolsSourceMap.isGeneratedId)(selectedSource.id) && breakpoint.generatedLocation) { - line = breakpoint.generatedLocation.line; - column = breakpoint.generatedLocation.column; - } - - return _react2.default.createElement("div", { - className: "breakpoint-line-close" - }, _react2.default.createElement("div", { - className: "breakpoint-line" - }, getBreakpointLocation(breakpoint.source, line, column)), _react2.default.createElement(_Button.CloseButton, { - handleClick: onCloseClick, - tooltip: L10N.getStr("breakpoints.removeBreakpointTooltip") - })); - } - - render() { - const { - breakpoint, - onClick, - onContextMenu - } = this.props; - const locationId = breakpoint.locationId; - const isCurrentlyPaused = breakpoint.isCurrentlyPaused; - const isDisabled = breakpoint.disabled; - const isConditional = !!breakpoint.condition; - return _react2.default.createElement("div", { - className: (0, _classnames2.default)({ - breakpoint, - paused: isCurrentlyPaused, - disabled: isDisabled, - "is-conditional": isConditional - }), - key: locationId, - onClick: onClick, - onContextMenu: onContextMenu - }, this.renderCheckbox(), this.renderText(), this.renderLineClose()); - } - -} - -exports.default = Breakpoint; \ No newline at end of file diff --git a/devtools/client/debugger/new/src/components/SecondaryPanes/Breakpoints.js b/devtools/client/debugger/new/src/components/SecondaryPanes/Breakpoints.js deleted file mode 100644 index 644d1c126b0a..000000000000 --- a/devtools/client/debugger/new/src/components/SecondaryPanes/Breakpoints.js +++ /dev/null @@ -1,212 +0,0 @@ -"use strict"; - -Object.defineProperty(exports, "__esModule", { - value: true -}); - -var _react = require("devtools/client/shared/vendor/react"); - -var _react2 = _interopRequireDefault(_react); - -var _classnames = require("devtools/client/debugger/new/dist/vendors").vendored["classnames"]; - -var _classnames2 = _interopRequireDefault(_classnames); - -var _reactRedux = require("devtools/client/shared/vendor/react-redux"); - -var _immutable = require("devtools/client/shared/vendor/immutable"); - -var I = _interopRequireWildcard(_immutable); - -var _reselect = require("devtools/client/debugger/new/dist/vendors").vendored["reselect"]; - -var _lodash = require("devtools/client/shared/vendor/lodash"); - -var _Breakpoint = require("./Breakpoint"); - -var _Breakpoint2 = _interopRequireDefault(_Breakpoint); - -var _SourceIcon = require("../shared/SourceIcon"); - -var _SourceIcon2 = _interopRequireDefault(_SourceIcon); - -var _actions = require("../../actions/index"); - -var _actions2 = _interopRequireDefault(_actions); - -var _source = require("../../utils/source"); - -var _selectors = require("../../selectors/index"); - -var _pause = require("../../utils/pause/index"); - -var _breakpoint = require("../../utils/breakpoint/index"); - -var _BreakpointsContextMenu = require("./BreakpointsContextMenu"); - -var _BreakpointsContextMenu2 = _interopRequireDefault(_BreakpointsContextMenu); - -function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = Object.defineProperty && Object.getOwnPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : {}; if (desc.get || desc.set) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } } newObj.default = obj; return newObj; } } - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; var ownKeys = Object.keys(source); if (typeof Object.getOwnPropertySymbols === 'function') { ownKeys = ownKeys.concat(Object.getOwnPropertySymbols(source).filter(function (sym) { return Object.getOwnPropertyDescriptor(source, sym).enumerable; })); } ownKeys.forEach(function (key) { _defineProperty(target, key, source[key]); }); } return target; } - -function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } - -function isCurrentlyPausedAtBreakpoint(frame, why, breakpoint) { - if (!frame || !(0, _pause.isInterrupted)(why)) { - return false; - } - - const bpId = (0, _breakpoint.makeLocationId)(breakpoint.location); - const pausedId = (0, _breakpoint.makeLocationId)(frame.location); - return bpId === pausedId; -} - -function createExceptionOption(label, value, onChange, className) { - return _react2.default.createElement("div", { - className: className, - onClick: onChange - }, _react2.default.createElement("input", { - type: "checkbox", - checked: value ? "checked" : "", - onChange: e => e.stopPropagation() && onChange() - }), _react2.default.createElement("div", { - className: "breakpoint-exceptions-label" - }, label)); -} - -function sortFilenames(urlA, urlB) { - const filenameA = (0, _source.getFilenameFromURL)(urlA); - const filenameB = (0, _source.getFilenameFromURL)(urlB); - - if (filenameA > filenameB) { - return 1; - } - - if (filenameA < filenameB) { - return -1; - } - - return 0; -} - -class Breakpoints extends _react.Component { - handleBreakpointCheckbox(breakpoint) { - if (breakpoint.loading) { - return; - } - - if (breakpoint.disabled) { - this.props.enableBreakpoint(breakpoint.location); - } else { - this.props.disableBreakpoint(breakpoint.location); - } - } - - selectBreakpoint(breakpoint) { - this.props.selectLocation(breakpoint.location); - } - - removeBreakpoint(event, breakpoint) { - event.stopPropagation(); - this.props.removeBreakpoint(breakpoint.location); - } - - renderBreakpoint(breakpoint) { - const { - selectedSource - } = this.props; - return _react2.default.createElement(_Breakpoint2.default, { - key: breakpoint.locationId, - breakpoint: breakpoint, - selectedSource: selectedSource, - onClick: () => this.selectBreakpoint(breakpoint), - onContextMenu: e => (0, _BreakpointsContextMenu2.default)(_objectSpread({}, this.props, { - breakpoint, - contextMenuEvent: e - })), - onChange: () => this.handleBreakpointCheckbox(breakpoint), - onCloseClick: ev => this.removeBreakpoint(ev, breakpoint) - }); - } - - renderExceptionsOptions() { - const { - breakpoints, - shouldPauseOnExceptions, - shouldPauseOnCaughtExceptions, - pauseOnExceptions - } = this.props; - const isEmpty = breakpoints.size == 0; - const exceptionsBox = createExceptionOption(L10N.getStr("pauseOnExceptionsItem2"), shouldPauseOnExceptions, () => pauseOnExceptions(!shouldPauseOnExceptions, false), "breakpoints-exceptions"); - const ignoreCaughtBox = createExceptionOption(L10N.getStr("pauseOnCaughtExceptionsItem"), shouldPauseOnCaughtExceptions, () => pauseOnExceptions(true, !shouldPauseOnCaughtExceptions), "breakpoints-exceptions-caught"); - return _react2.default.createElement("div", { - className: (0, _classnames2.default)("breakpoints-exceptions-options", { - empty: isEmpty - }) - }, exceptionsBox, shouldPauseOnExceptions ? ignoreCaughtBox : null); - } - - renderBreakpoints() { - const { - breakpoints - } = this.props; - - if (breakpoints.size == 0) { - return; - } - - const groupedBreakpoints = (0, _lodash.groupBy)((0, _lodash.sortBy)([...breakpoints.valueSeq()], bp => bp.location.line), bp => (0, _source.getRawSourceURL)(bp.source.url)); - return [...Object.keys(groupedBreakpoints).sort(sortFilenames).map(url => { - const groupBreakpoints = groupedBreakpoints[url].filter(bp => !bp.hidden && (bp.text || bp.originalText)); - - if (!groupBreakpoints.length) { - return null; - } - - const { - source - } = groupBreakpoints[0]; - return [_react2.default.createElement("div", { - className: "breakpoint-heading", - title: url, - key: url, - onClick: () => this.props.selectSource(source.id) - }, _react2.default.createElement(_SourceIcon2.default, { - source: source - }), (0, _source.getFilename)(source)), ...groupBreakpoints.map(bp => this.renderBreakpoint(bp))]; - })]; - } - - render() { - return _react2.default.createElement("div", { - className: "pane breakpoints-list" - }, this.renderExceptionsOptions(), this.renderBreakpoints()); - } - -} - -function updateLocation(sources, frame, why, bp) { - const source = (0, _selectors.getSourceInSources)(sources, bp.location.sourceId); - const isCurrentlyPaused = isCurrentlyPausedAtBreakpoint(frame, why, bp); - const locationId = (0, _breakpoint.makeLocationId)(bp.location); - - const localBP = _objectSpread({}, bp, { - locationId, - isCurrentlyPaused, - source - }); - - return localBP; -} - -const _getBreakpoints = (0, _reselect.createSelector)(_selectors.getBreakpoints, _selectors.getSources, _selectors.getTopFrame, _selectors.getPauseReason, (breakpoints, sources, frame, why) => breakpoints.map(bp => updateLocation(sources, frame, why, bp)).filter(bp => bp.source && !bp.source.isBlackBoxed)); - -const mapStateToProps = state => ({ - breakpoints: _getBreakpoints(state), - selectedSource: (0, _selectors.getSelectedSource)(state) -}); - -exports.default = (0, _reactRedux.connect)(mapStateToProps, _actions2.default)(Breakpoints); \ No newline at end of file diff --git a/devtools/client/debugger/new/src/components/SecondaryPanes/Breakpoints/Breakpoint.js b/devtools/client/debugger/new/src/components/SecondaryPanes/Breakpoints/Breakpoint.js new file mode 100644 index 000000000000..db64e290beff --- /dev/null +++ b/devtools/client/debugger/new/src/components/SecondaryPanes/Breakpoints/Breakpoint.js @@ -0,0 +1,196 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +var _react = require("devtools/client/shared/vendor/react"); + +var _react2 = _interopRequireDefault(_react); + +var _reactRedux = require("devtools/client/shared/vendor/react-redux"); + +var _devtoolsSourceMap = require("devtools/client/shared/source-map/index.js"); + +var _classnames = require("devtools/client/debugger/new/dist/vendors").vendored["classnames"]; + +var _classnames2 = _interopRequireDefault(_classnames); + +var _actions = require("../../../actions/index"); + +var _actions2 = _interopRequireDefault(_actions); + +var _BreakpointsContextMenu = require("./BreakpointsContextMenu"); + +var _BreakpointsContextMenu2 = _interopRequireDefault(_BreakpointsContextMenu); + +var _Button = require("../../shared/Button/index"); + +var _breakpoint = require("../../../utils/breakpoint/index"); + +var _prefs = require("../../../utils/prefs"); + +var _editor = require("../../../utils/editor/index"); + +var _selectors = require("../../../selectors/index"); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; var ownKeys = Object.keys(source); if (typeof Object.getOwnPropertySymbols === 'function') { ownKeys = ownKeys.concat(Object.getOwnPropertySymbols(source).filter(function (sym) { return Object.getOwnPropertyDescriptor(source, sym).enumerable; })); } ownKeys.forEach(function (key) { _defineProperty(target, key, source[key]); }); } return target; } + +function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } + +function getMappedLocation(mappedLocation, selectedSource) { + return selectedSource && (0, _devtoolsSourceMap.isGeneratedId)(selectedSource.id) ? mappedLocation.generatedLocation : mappedLocation.location; +} + +class Breakpoint extends _react.PureComponent { + constructor(...args) { + var _temp; + + return _temp = super(...args), this.onContextMenu = e => { + (0, _BreakpointsContextMenu2.default)(_objectSpread({}, this.props, { + contextMenuEvent: e + })); + }, this.selectBreakpoint = () => { + const { + breakpoint, + selectSpecificLocation + } = this.props; + selectSpecificLocation(breakpoint.location); + }, this.removeBreakpoint = event => { + const { + breakpoint, + removeBreakpoint + } = this.props; + event.stopPropagation(); + removeBreakpoint(breakpoint.location); + }, this.handleBreakpointCheckbox = () => { + const { + breakpoint, + enableBreakpoint, + disableBreakpoint + } = this.props; + + if (breakpoint.loading) { + return; + } + + if (breakpoint.disabled) { + enableBreakpoint(breakpoint.location); + } else { + disableBreakpoint(breakpoint.location); + } + }, _temp; + } + + isCurrentlyPausedAtBreakpoint() { + const { + frame, + breakpoint, + selectedSource + } = this.props; + + if (!frame) { + return false; + } + + const bpId = (0, _breakpoint.getLocationWithoutColumn)(getMappedLocation(breakpoint, selectedSource)); + const frameId = (0, _breakpoint.getLocationWithoutColumn)(getMappedLocation(frame, selectedSource)); + return bpId == frameId; + } + + getBreakpointLocation() { + const { + breakpoint, + source, + selectedSource + } = this.props; + const { + column, + line + } = getMappedLocation(breakpoint, selectedSource); + const isWasm = source && source.isWasm; + const columnVal = _prefs.features.columnBreakpoints && column ? `:${column}` : ""; + const bpLocation = isWasm ? `0x${line.toString(16).toUpperCase()}` : `${line}${columnVal}`; + return bpLocation; + } + + getBreakpointText() { + const { + selectedSource, + breakpoint + } = this.props; + const { + condition + } = breakpoint; + + if (condition) { + return condition; + } + + if (selectedSource && (0, _devtoolsSourceMap.isGeneratedId)(selectedSource.id)) { + return breakpoint.text; + } + + return breakpoint.originalText; + } + + highlightText() { + const text = this.getBreakpointText(); + const codeMirror = (0, _editor.getCodeMirror)(); + + if (!text || !codeMirror) { + return { + __html: "" + }; + } + + const node = document.createElement("div"); + codeMirror.constructor.runMode(text, "application/javascript", node); + return { + __html: node.innerHTML + }; + } + + render() { + const { + breakpoint + } = this.props; + return _react2.default.createElement("div", { + className: (0, _classnames2.default)({ + breakpoint, + paused: this.isCurrentlyPausedAtBreakpoint(), + disabled: breakpoint.disabled, + "is-conditional": !!breakpoint.condition + }), + onClick: this.selectBreakpoint, + onContextMenu: this.onContextMenu + }, _react2.default.createElement("input", { + type: "checkbox", + className: "breakpoint-checkbox", + checked: !breakpoint.disabled, + onChange: this.handleBreakpointCheckbox, + onClick: ev => ev.stopPropagation() + }), _react2.default.createElement("label", { + className: "breakpoint-label cm-s-mozilla", + title: this.getBreakpointText(), + dangerouslySetInnerHTML: this.highlightText() + }), _react2.default.createElement("div", { + className: "breakpoint-line-close" + }, _react2.default.createElement("div", { + className: "breakpoint-line" + }, this.getBreakpointLocation()), _react2.default.createElement(_Button.CloseButton, { + handleClick: e => this.removeBreakpoint(e), + tooltip: L10N.getStr("breakpoints.removeBreakpointTooltip") + }))); + } + +} + +const mapStateToProps = state => ({ + frame: (0, _selectors.getTopFrame)(state), + selectedSource: (0, _selectors.getSelectedSource)(state) +}); + +exports.default = (0, _reactRedux.connect)(mapStateToProps, _actions2.default)(Breakpoint); \ No newline at end of file diff --git a/devtools/client/debugger/new/src/components/SecondaryPanes/BreakpointsContextMenu.js b/devtools/client/debugger/new/src/components/SecondaryPanes/Breakpoints/BreakpointsContextMenu.js similarity index 100% rename from devtools/client/debugger/new/src/components/SecondaryPanes/BreakpointsContextMenu.js rename to devtools/client/debugger/new/src/components/SecondaryPanes/Breakpoints/BreakpointsContextMenu.js diff --git a/devtools/client/debugger/new/src/components/SecondaryPanes/Breakpoints/index.js b/devtools/client/debugger/new/src/components/SecondaryPanes/Breakpoints/index.js new file mode 100644 index 000000000000..3a4019fd3d23 --- /dev/null +++ b/devtools/client/debugger/new/src/components/SecondaryPanes/Breakpoints/index.js @@ -0,0 +1,105 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +var _react = require("devtools/client/shared/vendor/react"); + +var _react2 = _interopRequireDefault(_react); + +var _classnames = require("devtools/client/debugger/new/dist/vendors").vendored["classnames"]; + +var _classnames2 = _interopRequireDefault(_classnames); + +var _reactRedux = require("devtools/client/shared/vendor/react-redux"); + +var _Breakpoint = require("./Breakpoint"); + +var _Breakpoint2 = _interopRequireDefault(_Breakpoint); + +var _SourceIcon = require("../../shared/SourceIcon"); + +var _SourceIcon2 = _interopRequireDefault(_SourceIcon); + +var _actions = require("../../../actions/index"); + +var _actions2 = _interopRequireDefault(_actions); + +var _source = require("../../../utils/source"); + +var _breakpoint = require("../../../utils/breakpoint/index"); + +var _selectors = require("../../../selectors/index"); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at . */ +function createExceptionOption(label, value, onChange, className) { + return _react2.default.createElement("div", { + className: className, + onClick: onChange + }, _react2.default.createElement("input", { + type: "checkbox", + checked: value ? "checked" : "", + onChange: e => e.stopPropagation() && onChange() + }), _react2.default.createElement("div", { + className: "breakpoint-exceptions-label" + }, label)); +} + +class Breakpoints extends _react.Component { + renderExceptionsOptions() { + const { + breakpointSources, + shouldPauseOnExceptions, + shouldPauseOnCaughtExceptions, + pauseOnExceptions + } = this.props; + const isEmpty = breakpointSources.length == 0; + const exceptionsBox = createExceptionOption(L10N.getStr("pauseOnExceptionsItem2"), shouldPauseOnExceptions, () => pauseOnExceptions(!shouldPauseOnExceptions, false), "breakpoints-exceptions"); + const ignoreCaughtBox = createExceptionOption(L10N.getStr("pauseOnCaughtExceptionsItem"), shouldPauseOnCaughtExceptions, () => pauseOnExceptions(true, !shouldPauseOnCaughtExceptions), "breakpoints-exceptions-caught"); + return _react2.default.createElement("div", { + className: (0, _classnames2.default)("breakpoints-exceptions-options", { + empty: isEmpty + }) + }, exceptionsBox, shouldPauseOnExceptions ? ignoreCaughtBox : null); + } + + renderBreakpoints() { + const { + breakpointSources + } = this.props; + return [...breakpointSources.map(({ + source, + breakpoints + }) => [_react2.default.createElement("div", { + className: "breakpoint-heading", + title: source.url, + key: source.url, + onClick: () => this.props.selectSource(source.id) + }, _react2.default.createElement(_SourceIcon2.default, { + source: source + }), (0, _source.getFilename)(source)), ...breakpoints.map(breakpoint => _react2.default.createElement(_Breakpoint2.default, { + breakpoint: breakpoint, + source: source, + key: (0, _breakpoint.makeLocationId)(breakpoint.location) + }))])]; + } + + render() { + return _react2.default.createElement("div", { + className: "pane breakpoints-list" + }, this.renderExceptionsOptions(), this.renderBreakpoints()); + } + +} + +const mapStateToProps = state => ({ + breakpointSources: (0, _selectors.getBreakpointSources)(state), + selectedSource: (0, _selectors.getSelectedSource)(state) +}); + +exports.default = (0, _reactRedux.connect)(mapStateToProps, _actions2.default)(Breakpoints); \ No newline at end of file diff --git a/servo/etc/ci/clean_build_artifacts.sh b/devtools/client/debugger/new/src/components/SecondaryPanes/Breakpoints/moz.build old mode 100755 new mode 100644 similarity index 61% rename from servo/etc/ci/clean_build_artifacts.sh rename to devtools/client/debugger/new/src/components/SecondaryPanes/Breakpoints/moz.build index f3d7d7250609..ee02a5734a20 --- a/servo/etc/ci/clean_build_artifacts.sh +++ b/devtools/client/debugger/new/src/components/SecondaryPanes/Breakpoints/moz.build @@ -1,11 +1,14 @@ -#!/usr/bin/env bash - +# vim: set filetype=python: # This Source Code Form is subject to the terms of the Mozilla Public # License, v. 2.0. If a copy of the MPL was not distributed with this # file, You can obtain one at http://mozilla.org/MPL/2.0/. -set -o errexit -set -o nounset -set -o pipefail +DIRS += [ -rm -rf target/{debug,release,doc,geckolib} +] + +DevToolsModules( + 'Breakpoint.js', + 'BreakpointsContextMenu.js', + 'index.js', +) diff --git a/devtools/client/debugger/new/src/components/SecondaryPanes/index.js b/devtools/client/debugger/new/src/components/SecondaryPanes/index.js index 22eddae2ce3c..9ec027ad3dbf 100644 --- a/devtools/client/debugger/new/src/components/SecondaryPanes/index.js +++ b/devtools/client/debugger/new/src/components/SecondaryPanes/index.js @@ -28,7 +28,7 @@ var _Svg2 = _interopRequireDefault(_Svg); var _prefs = require("../../utils/prefs"); -var _Breakpoints = require("./Breakpoints"); +var _Breakpoints = require("./Breakpoints/index"); var _Breakpoints2 = _interopRequireDefault(_Breakpoints); diff --git a/devtools/client/debugger/new/src/components/SecondaryPanes/moz.build b/devtools/client/debugger/new/src/components/SecondaryPanes/moz.build index 7d1d54afab6b..49d4991446d9 100644 --- a/devtools/client/debugger/new/src/components/SecondaryPanes/moz.build +++ b/devtools/client/debugger/new/src/components/SecondaryPanes/moz.build @@ -4,13 +4,11 @@ # file, You can obtain one at http://mozilla.org/MPL/2.0/. DIRS += [ + 'Breakpoints', 'Frames', ] DevToolsModules( - 'Breakpoint.js', - 'Breakpoints.js', - 'BreakpointsContextMenu.js', 'CommandBar.js', 'EventListeners.js', 'Expressions.js', diff --git a/devtools/client/debugger/new/src/components/shared/Button/Close.js b/devtools/client/debugger/new/src/components/shared/Button/Close.js deleted file mode 100644 index a64c4c084541..000000000000 --- a/devtools/client/debugger/new/src/components/shared/Button/Close.js +++ /dev/null @@ -1,30 +0,0 @@ -"use strict"; - -Object.defineProperty(exports, "__esModule", { - value: true -}); - -var _react = require("devtools/client/shared/vendor/react"); - -var _react2 = _interopRequireDefault(_react); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at . */ -function CloseButton({ - handleClick, - buttonClass, - tooltip -}) { - return _react2.default.createElement("button", { - className: buttonClass ? `close-btn ${buttonClass}` : "close-btn", - onClick: handleClick, - title: tooltip - }, _react2.default.createElement("img", { - className: "close" - })); -} - -exports.default = CloseButton; \ No newline at end of file diff --git a/devtools/client/debugger/new/src/components/shared/Button/PaneToggle.js b/devtools/client/debugger/new/src/components/shared/Button/PaneToggle.js deleted file mode 100644 index efabc748e6dd..000000000000 --- a/devtools/client/debugger/new/src/components/shared/Button/PaneToggle.js +++ /dev/null @@ -1,54 +0,0 @@ -"use strict"; - -Object.defineProperty(exports, "__esModule", { - value: true -}); - -var _react = require("devtools/client/shared/vendor/react"); - -var _react2 = _interopRequireDefault(_react); - -var _classnames = require("devtools/client/debugger/new/dist/vendors").vendored["classnames"]; - -var _classnames2 = _interopRequireDefault(_classnames); - -var _Svg = require("devtools/client/debugger/new/dist/vendors").vendored["Svg"]; - -var _Svg2 = _interopRequireDefault(_Svg); - -var _CommandBarButton = require("./CommandBarButton"); - -var _CommandBarButton2 = _interopRequireDefault(_CommandBarButton); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at . */ -class PaneToggleButton extends _react.PureComponent { - render() { - const { - position, - collapsed, - horizontal, - handleClick - } = this.props; - const title = !collapsed ? L10N.getStr("expandPanes") : L10N.getStr("collapsePanes"); - return _react2.default.createElement(_CommandBarButton2.default, { - className: (0, _classnames2.default)("toggle-button", position, { - collapsed, - vertical: !horizontal - }), - onClick: () => handleClick(position, collapsed), - title: title - }, _react2.default.createElement(_Svg2.default, { - name: "togglePanes" - })); - } - -} - -PaneToggleButton.defaultProps = { - horizontal: false -}; -exports.default = PaneToggleButton; \ No newline at end of file diff --git a/devtools/client/debugger/new/src/reducers/ast.js b/devtools/client/debugger/new/src/reducers/ast.js index 1e089db735ae..9bf70204dfb7 100644 --- a/devtools/client/debugger/new/src/reducers/ast.js +++ b/devtools/client/debugger/new/src/reducers/ast.js @@ -162,17 +162,17 @@ function isSymbolsLoading(state, source) { return symbols.hasOwnProperty("loading"); } -function isEmptyLineInSource(state, line, selectedSource) { - const emptyLines = getEmptyLines(state, selectedSource); +function isEmptyLineInSource(state, line, selectedSourceId) { + const emptyLines = getEmptyLines(state, selectedSourceId); return emptyLines && emptyLines.includes(line); } -function getEmptyLines(state, source) { - if (!source) { +function getEmptyLines(state, sourceId) { + if (!sourceId) { return null; } - return state.ast.emptyLines.get(source.id); + return state.ast.emptyLines.get(sourceId); } function getPausePoints(state, sourceId) { diff --git a/devtools/client/debugger/new/src/reducers/sources.js b/devtools/client/debugger/new/src/reducers/sources.js index 81f439cf63e1..546cf302476d 100644 --- a/devtools/client/debugger/new/src/reducers/sources.js +++ b/devtools/client/debugger/new/src/reducers/sources.js @@ -5,6 +5,7 @@ Object.defineProperty(exports, "__esModule", { }); exports.getSelectedSourceText = exports.getSelectedSource = exports.getSelectedLocation = exports.getSourcesForTabs = exports.getSourceTabs = exports.getTabs = exports.getSources = exports.RelativeSourceRecordClass = exports.SourceRecordClass = undefined; exports.initialSourcesState = initialSourcesState; +exports.createSourceRecord = createSourceRecord; exports.removeSourceFromTabList = removeSourceFromTabList; exports.removeSourcesFromTabList = removeSourcesFromTabList; exports.getBlackBoxList = getBlackBoxList; @@ -68,6 +69,10 @@ const RelativeSourceRecordClass = exports.RelativeSourceRecordClass = new I.Reco relativeUrl: undefined })); +function createSourceRecord(source) { + return new SourceRecordClass(source); +} + function update(state = initialSourcesState(), action) { let location = null; @@ -222,7 +227,7 @@ function updateSource(state, source) { return state.setIn(["sources", source.id], updatedSource); } - return state.setIn(["sources", source.id], new SourceRecordClass(source)); + return state.setIn(["sources", source.id], createSourceRecord(source)); } function removeSourceFromTabList(tabs, url) { diff --git a/devtools/client/debugger/new/src/selectors/breakpointSources.js b/devtools/client/debugger/new/src/selectors/breakpointSources.js new file mode 100644 index 000000000000..272c0d01191b --- /dev/null +++ b/devtools/client/debugger/new/src/selectors/breakpointSources.js @@ -0,0 +1,37 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.getBreakpointSources = undefined; + +var _lodash = require("devtools/client/shared/vendor/lodash"); + +var _reselect = require("devtools/client/debugger/new/dist/vendors").vendored["reselect"]; + +var _selectors = require("../selectors/index"); + +var _source = require("../utils/source"); + +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at . */ +function getBreakpointsForSource(source, breakpoints) { + return breakpoints.valueSeq().filter(bp => bp.location.sourceId == source.id && !bp.hidden && (bp.text || bp.condition)).sortBy(bp => bp.location.line).toJS(); +} + +function findBreakpointSources(sources, breakpoints) { + const sourceIds = (0, _lodash.uniq)(breakpoints.valueSeq().filter(bp => !bp.hidden).map(bp => bp.location.sourceId).toJS()); + const breakpointSources = sourceIds.map(id => (0, _selectors.getSourceInSources)(sources, id)).filter(source => source && !source.isBlackBoxed); + return (0, _lodash.sortBy)(breakpointSources, source => (0, _source.getFilenameFromURL)(source.url)); +} + +function _getBreakpointSources(breakpoints, sources, selectedSource) { + const breakpointSources = findBreakpointSources(sources, breakpoints); + return breakpointSources.map(source => ({ + source, + breakpoints: getBreakpointsForSource(source, breakpoints) + })); +} + +const getBreakpointSources = exports.getBreakpointSources = (0, _reselect.createSelector)(_selectors.getBreakpoints, _selectors.getSources, _getBreakpointSources); \ No newline at end of file diff --git a/devtools/client/debugger/new/src/selectors/index.js b/devtools/client/debugger/new/src/selectors/index.js index 307922fe036e..b4c7d1704b99 100644 --- a/devtools/client/debugger/new/src/selectors/index.js +++ b/devtools/client/debugger/new/src/selectors/index.js @@ -251,4 +251,13 @@ Object.defineProperty(exports, "getRelativeSources", { get: function () { return _getRelativeSources.getRelativeSources; } +}); + +var _breakpointSources = require("./breakpointSources"); + +Object.defineProperty(exports, "getBreakpointSources", { + enumerable: true, + get: function () { + return _breakpointSources.getBreakpointSources; + } }); \ No newline at end of file diff --git a/devtools/client/debugger/new/src/selectors/moz.build b/devtools/client/debugger/new/src/selectors/moz.build index 05c9e2b43c2b..4d7cdd4cf91e 100644 --- a/devtools/client/debugger/new/src/selectors/moz.build +++ b/devtools/client/debugger/new/src/selectors/moz.build @@ -9,6 +9,7 @@ DIRS += [ DevToolsModules( 'breakpointAtLocation.js', + 'breakpointSources.js', 'getCallStackFrames.js', 'getRelativeSources.js', 'inComponent.js', diff --git a/devtools/client/debugger/new/src/utils/breakpoint/create-editor.js b/devtools/client/debugger/new/src/utils/breakpoint/create-editor.js deleted file mode 100644 index 9b29b1bd1f86..000000000000 --- a/devtools/client/debugger/new/src/utils/breakpoint/create-editor.js +++ /dev/null @@ -1,33 +0,0 @@ -"use strict"; - -Object.defineProperty(exports, "__esModule", { - value: true -}); -exports.createEditor = createEditor; - -var _sourceEditor = require("devtools/client/sourceeditor/editor"); - -var _sourceEditor2 = _interopRequireDefault(_sourceEditor); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at . */ -function createEditor(value) { - return new _sourceEditor2.default({ - mode: "javascript", - foldGutter: false, - enableCodeFolding: false, - readOnly: "nocursor", - lineNumbers: false, - theme: "mozilla mozilla-breakpoint", - styleActiveLine: false, - lineWrapping: false, - matchBrackets: false, - showAnnotationRuler: false, - gutters: false, - value: value || "", - scrollbarStyle: null - }); -} \ No newline at end of file diff --git a/devtools/client/debugger/new/src/utils/breakpoint/index.js b/devtools/client/debugger/new/src/utils/breakpoint/index.js index 2e0345f2a29a..ef1a819d04b4 100644 --- a/devtools/client/debugger/new/src/utils/breakpoint/index.js +++ b/devtools/client/debugger/new/src/utils/breakpoint/index.js @@ -3,16 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true }); -exports.findScopeByName = exports.getASTLocation = exports.createEditor = undefined; - -var _createEditor = require("./create-editor"); - -Object.defineProperty(exports, "createEditor", { - enumerable: true, - get: function () { - return _createEditor.createEditor; - } -}); +exports.findScopeByName = exports.getASTLocation = undefined; var _astBreakpointLocation = require("./astBreakpointLocation"); @@ -31,6 +22,7 @@ Object.defineProperty(exports, "findScopeByName", { exports.firstString = firstString; exports.locationMoved = locationMoved; exports.makeLocationId = makeLocationId; +exports.getLocationWithoutColumn = getLocationWithoutColumn; exports.makePendingLocationId = makePendingLocationId; exports.assertBreakpoint = assertBreakpoint; exports.assertPendingBreakpoint = assertPendingBreakpoint; @@ -77,6 +69,14 @@ function makeLocationId(location) { return `${sourceId}:${line}:${columnString}`; } +function getLocationWithoutColumn(location) { + const { + sourceId, + line + } = location; + return `${sourceId}:${line}`; +} + function makePendingLocationId(location) { assertPendingLocation(location); const { diff --git a/devtools/client/debugger/new/src/utils/breakpoint/moz.build b/devtools/client/debugger/new/src/utils/breakpoint/moz.build index 06b7115e91b5..2beb971c99b3 100644 --- a/devtools/client/debugger/new/src/utils/breakpoint/moz.build +++ b/devtools/client/debugger/new/src/utils/breakpoint/moz.build @@ -9,6 +9,5 @@ DIRS += [ DevToolsModules( 'astBreakpointLocation.js', - 'create-editor.js', 'index.js', ) diff --git a/devtools/client/debugger/new/src/utils/editor/index.js b/devtools/client/debugger/new/src/utils/editor/index.js index 3d8260770f36..c0faf5e5f5c3 100644 --- a/devtools/client/debugger/new/src/utils/editor/index.js +++ b/devtools/client/debugger/new/src/utils/editor/index.js @@ -65,6 +65,7 @@ Object.keys(_createEditor).forEach(function (key) { }); exports.setEditor = setEditor; exports.getEditor = getEditor; +exports.getCodeMirror = getCodeMirror; exports.removeEditor = removeEditor; exports.shouldShowPrettyPrint = shouldShowPrettyPrint; exports.shouldShowFooter = shouldShowFooter; @@ -103,6 +104,10 @@ function getEditor() { return editor; } +function getCodeMirror() { + return editor && editor.codeMirror; +} + function removeEditor() { editor = null; } diff --git a/devtools/client/debugger/new/src/utils/editor/source-editor.js b/devtools/client/debugger/new/src/utils/editor/source-editor.js index f4d9c3aab86c..4dcd04a5aa90 100644 --- a/devtools/client/debugger/new/src/utils/editor/source-editor.js +++ b/devtools/client/debugger/new/src/utils/editor/source-editor.js @@ -38,6 +38,8 @@ require("codemirror/addon/fold/indent-fold/index"); require("codemirror/addon/fold/foldgutter/index"); +require("codemirror/addon/runmode/runmode/index"); + require("codemirror/addon/selection/active-line/index"); require("codemirror/addon/edit/matchbrackets/index"); diff --git a/devtools/client/debugger/new/src/utils/pause/mapScopes/index.js b/devtools/client/debugger/new/src/utils/pause/mapScopes/index.js index 596756ca7d51..ac60390c5f65 100644 --- a/devtools/client/debugger/new/src/utils/pause/mapScopes/index.js +++ b/devtools/client/debugger/new/src/utils/pause/mapScopes/index.js @@ -9,6 +9,8 @@ var _parser = require("../../../workers/parser/index"); var _locColumn = require("./locColumn"); +var _rangeMetadata = require("./rangeMetadata"); + var _findGeneratedBindingFromPosition = require("./findGeneratedBindingFromPosition"); var _buildGeneratedBindingList = require("./buildGeneratedBindingList"); @@ -30,10 +32,11 @@ async function buildMappedScopes(source, frame, scopes, sourceMaps, client) { } const generatedAstBindings = (0, _buildGeneratedBindingList.buildGeneratedBindingList)(scopes, generatedAstScopes, frame.this); + const originalRanges = await (0, _rangeMetadata.loadRangeMetadata)(source, frame, originalAstScopes, sourceMaps); const { mappedOriginalScopes, expressionLookup - } = await mapOriginalBindingsToGenerated(source, originalAstScopes, generatedAstBindings, client, sourceMaps); + } = await mapOriginalBindingsToGenerated(source, originalRanges, originalAstScopes, generatedAstBindings, client, sourceMaps); const mappedGeneratedScopes = generateClientScope(scopes, mappedOriginalScopes); return isReliableScope(mappedGeneratedScopes) ? { mappings: expressionLookup, @@ -41,7 +44,7 @@ async function buildMappedScopes(source, frame, scopes, sourceMaps, client) { } : null; } -async function mapOriginalBindingsToGenerated(source, originalAstScopes, generatedAstBindings, client, sourceMaps) { +async function mapOriginalBindingsToGenerated(source, originalRanges, originalAstScopes, generatedAstBindings, client, sourceMaps) { const expressionLookup = {}; const mappedOriginalScopes = []; const cachedSourceMaps = batchScopeMappings(originalAstScopes, source, sourceMaps); @@ -51,7 +54,7 @@ async function mapOriginalBindingsToGenerated(source, originalAstScopes, generat for (const name of Object.keys(item.bindings)) { const binding = item.bindings[name]; - const result = await findGeneratedBinding(cachedSourceMaps, client, source, name, binding, generatedAstBindings); + const result = await findGeneratedBinding(cachedSourceMaps, client, source, name, binding, originalRanges, generatedAstBindings); if (result) { generatedBindings[name] = result.grip; @@ -213,7 +216,14 @@ function generateClientScope(scopes, originalScopes) { return result; } -async function findGeneratedBinding(sourceMaps, client, source, name, originalBinding, generatedAstBindings) { +function hasValidIdent(range, pos) { + return range.type === "match" || // For declarations, we allow the range on the identifier to be a + // more general "contains" to increase the chances of a match. + pos.type !== "ref" && range.type === "contains"; +} // eslint-disable-next-line complexity + + +async function findGeneratedBinding(sourceMaps, client, source, name, originalBinding, originalRanges, generatedAstBindings) { // If there are no references to the implicits, then we have no way to // even attempt to map it back to the original since there is no location // data to use. Bail out instead of just showing it as unmapped. @@ -227,27 +237,43 @@ async function findGeneratedBinding(sourceMaps, client, source, name, originalBi let genContent = null; for (const pos of refs) { - if (originalBinding.type === "import") { - genContent = await (0, _findGeneratedBindingFromPosition.findGeneratedBindingForImportBinding)(sourceMaps, client, source, pos, name, originalBinding.type, generatedAstBindings); - } else { - genContent = await (0, _findGeneratedBindingFromPosition.findGeneratedBindingForStandardBinding)(sourceMaps, client, source, pos, name, originalBinding.type, generatedAstBindings); + const range = (0, _rangeMetadata.findMatchingRange)(originalRanges, pos); + + if (range && hasValidIdent(range, pos)) { + if (originalBinding.type === "import") { + genContent = await (0, _findGeneratedBindingFromPosition.findGeneratedBindingForImportBinding)(sourceMaps, client, source, pos, name, originalBinding.type, generatedAstBindings); + } else { + genContent = await (0, _findGeneratedBindingFromPosition.findGeneratedBindingForStandardBinding)(sourceMaps, client, source, pos, name, originalBinding.type, generatedAstBindings); + } } if ((pos.type === "class-decl" || pos.type === "class-inner") && source.contentType && source.contentType.match(/\/typescript/)) { - // Resolve to first binding in the range - const declContent = await (0, _findGeneratedBindingFromPosition.findGeneratedBindingForNormalDeclaration)(sourceMaps, client, source, pos, name, originalBinding.type, generatedAstBindings); + const declRange = (0, _rangeMetadata.findMatchingRange)(originalRanges, pos.declaration); - if (declContent) { - // Prefer the declaration mapping in this case because TS sometimes - // maps class declaration names to "export.Foo = Foo;" or to - // the decorator logic itself - genContent = declContent; + if (declRange && declRange.type !== "multiple") { + // Resolve to first binding in the range + const declContent = await (0, _findGeneratedBindingFromPosition.findGeneratedBindingForNormalDeclaration)(sourceMaps, client, source, pos, name, originalBinding.type, generatedAstBindings); + + if (declContent) { + // Prefer the declaration mapping in this case because TS sometimes + // maps class declaration names to "export.Foo = Foo;" or to + // the decorator logic itself + genContent = declContent; + } } } if (!genContent && (pos.type === "import-decl" || pos.type === "import-ns-decl")) { - // match the import declaration location - genContent = await (0, _findGeneratedBindingFromPosition.findGeneratedBindingForImportDeclaration)(sourceMaps, client, source, pos, name, originalBinding.type, generatedAstBindings); + const declRange = (0, _rangeMetadata.findMatchingRange)(originalRanges, pos.declaration); // The import declaration should have an original position mapping, + // but otherwise we don't really have preferences on the range type + // because it can have multiple bindings, but we do want to make sure + // that all of the bindings that match the range are part of the same + // import declaration. + + if (declRange && declRange.singleDeclaration) { + // match the import declaration location + genContent = await (0, _findGeneratedBindingFromPosition.findGeneratedBindingForImportDeclaration)(sourceMaps, client, source, pos, name, originalBinding.type, generatedAstBindings); + } } if (genContent) { diff --git a/devtools/client/debugger/new/src/utils/pause/mapScopes/moz.build b/devtools/client/debugger/new/src/utils/pause/mapScopes/moz.build index b8c2b558d199..ac03adebea4e 100644 --- a/devtools/client/debugger/new/src/utils/pause/mapScopes/moz.build +++ b/devtools/client/debugger/new/src/utils/pause/mapScopes/moz.build @@ -16,4 +16,5 @@ DevToolsModules( 'locColumn.js', 'mappingContains.js', 'positionCmp.js', + 'rangeMetadata.js', ) diff --git a/devtools/client/debugger/new/src/utils/pause/mapScopes/rangeMetadata.js b/devtools/client/debugger/new/src/utils/pause/mapScopes/rangeMetadata.js new file mode 100644 index 000000000000..a7539cd804f8 --- /dev/null +++ b/devtools/client/debugger/new/src/utils/pause/mapScopes/rangeMetadata.js @@ -0,0 +1,92 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.loadRangeMetadata = loadRangeMetadata; +exports.findMatchingRange = findMatchingRange; + +var _locColumn = require("./locColumn"); + +var _positionCmp = require("./positionCmp"); + +var _filtering = require("./filtering"); + +function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; var ownKeys = Object.keys(source); if (typeof Object.getOwnPropertySymbols === 'function') { ownKeys = ownKeys.concat(Object.getOwnPropertySymbols(source).filter(function (sym) { return Object.getOwnPropertyDescriptor(source, sym).enumerable; })); } ownKeys.forEach(function (key) { _defineProperty(target, key, source[key]); }); } return target; } + +function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } + +async function loadRangeMetadata(source, frame, originalAstScopes, sourceMaps) { + const originalRanges = await sourceMaps.getOriginalRanges(frame.location.sourceId, source.url); + const sortedOriginalAstBindings = []; + + for (const item of originalAstScopes) { + for (const name of Object.keys(item.bindings)) { + for (const ref of item.bindings[name].refs) { + sortedOriginalAstBindings.push(ref); + } + } + } + + sortedOriginalAstBindings.sort((a, b) => (0, _positionCmp.positionCmp)(a.start, b.start)); + let i = 0; + return originalRanges.map(range => { + const bindings = []; + + while (i < sortedOriginalAstBindings.length && (sortedOriginalAstBindings[i].start.line < range.line || sortedOriginalAstBindings[i].start.line === range.line && (0, _locColumn.locColumn)(sortedOriginalAstBindings[i].start) < range.columnStart)) { + i++; + } + + while (i < sortedOriginalAstBindings.length && sortedOriginalAstBindings[i].start.line === range.line && (0, _locColumn.locColumn)(sortedOriginalAstBindings[i].start) >= range.columnStart && (0, _locColumn.locColumn)(sortedOriginalAstBindings[i].start) < range.columnEnd) { + bindings.push(sortedOriginalAstBindings[i]); + i++; + } + + let type = "empty"; + let singleDeclaration = true; + + if (bindings.length === 1) { + const binding = bindings[0]; + + if (binding.start.line === range.line && binding.start.column === range.columnStart) { + type = "match"; + } else { + type = "contains"; + } + } else if (bindings.length > 1) { + type = "multiple"; + const binding = bindings[0]; + const declStart = binding.type !== "ref" ? binding.declaration.start : null; + singleDeclaration = bindings.every(b => { + return declStart && b.type !== "ref" && (0, _positionCmp.positionCmp)(declStart, b.declaration.start) === 0; + }); + } + + return _objectSpread({ + type, + singleDeclaration + }, range); + }); +} + +function findMatchingRange(sortedOriginalRanges, bindingRange) { + return (0, _filtering.filterSortedArray)(sortedOriginalRanges, range => { + if (range.line < bindingRange.start.line) { + return -1; + } + + if (range.line > bindingRange.start.line) { + return 1; + } + + if (range.columnEnd <= (0, _locColumn.locColumn)(bindingRange.start)) { + return -1; + } + + if (range.columnStart > (0, _locColumn.locColumn)(bindingRange.start)) { + return 1; + } + + return 0; + }).pop(); +} \ No newline at end of file diff --git a/devtools/client/debugger/new/src/utils/source.js b/devtools/client/debugger/new/src/utils/source.js index 3591525e8a23..d10f261d306e 100644 --- a/devtools/client/debugger/new/src/utils/source.js +++ b/devtools/client/debugger/new/src/utils/source.js @@ -466,5 +466,5 @@ function getSourceClassnames(source, sourceMetaData) { return "blackBox"; } - return sourceTypes[(0, _sourcesTree.getExtension)(source)] || defaultClassName; + return sourceTypes[(0, _sourcesTree.getExtension)(source.url)] || defaultClassName; } \ No newline at end of file diff --git a/devtools/client/debugger/new/src/utils/sources-tree/utils.js b/devtools/client/debugger/new/src/utils/sources-tree/utils.js index aee48530cf75..a3d7e1ba80ed 100644 --- a/devtools/client/debugger/new/src/utils/sources-tree/utils.js +++ b/devtools/client/debugger/new/src/utils/sources-tree/utils.js @@ -47,8 +47,7 @@ function isDirectory(url) { return (parts.length === 0 || url.path.slice(-1) === "/" || nodeHasChildren(url)) && url.name != "(index)"; } -function getExtension(source) { - const url = source.get ? source.get("url") : source.url; +function getExtension(url = "") { const parsedUrl = (0, _url.parse)(url).pathname; if (!parsedUrl) { @@ -59,7 +58,7 @@ function getExtension(source) { } function isNotJavaScript(source) { - return ["css", "svg", "png"].includes(getExtension(source)); + return ["css", "svg", "png"].includes(getExtension(source.url)); } function isInvalidUrl(url, source) { diff --git a/devtools/client/debugger/new/src/utils/test-head.js b/devtools/client/debugger/new/src/utils/test-head.js deleted file mode 100644 index ae492308299b..000000000000 --- a/devtools/client/debugger/new/src/utils/test-head.js +++ /dev/null @@ -1,167 +0,0 @@ -"use strict"; - -Object.defineProperty(exports, "__esModule", { - value: true -}); -exports.getHistory = exports.waitForState = exports.makeSymbolDeclaration = exports.makeSourceRecord = exports.makeOriginalSource = exports.makeSource = exports.makeFrame = exports.commonLog = exports.createStore = exports.reducers = exports.selectors = exports.actions = undefined; - -var _redux = require("devtools/client/shared/vendor/redux"); - -var _devtoolsSourceMap = require("devtools/client/shared/source-map/index.js"); - -var _devtoolsSourceMap2 = _interopRequireDefault(_devtoolsSourceMap); - -var _reducers = require("../reducers/index"); - -var _reducers2 = _interopRequireDefault(_reducers); - -var _actions = require("../actions/index"); - -var _actions2 = _interopRequireDefault(_actions); - -var _selectors = require("../selectors/index"); - -var selectors = _interopRequireWildcard(_selectors); - -var _history = require("../test/utils/history"); - -var _createStore = require("../actions/utils/create-store"); - -var _createStore2 = _interopRequireDefault(_createStore); - -var _immutable = require("devtools/client/shared/vendor/immutable"); - -var I = _interopRequireWildcard(_immutable); - -function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = Object.defineProperty && Object.getOwnPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : {}; if (desc.get || desc.set) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } } newObj.default = obj; return newObj; } } - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; var ownKeys = Object.keys(source); if (typeof Object.getOwnPropertySymbols === 'function') { ownKeys = ownKeys.concat(Object.getOwnPropertySymbols(source).filter(function (sym) { return Object.getOwnPropertyDescriptor(source, sym).enumerable; })); } ownKeys.forEach(function (key) { _defineProperty(target, key, source[key]); }); } return target; } - -function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } - -/** - * @memberof utils/test-head - * @static - */ -function createStore(client, initialState = {}, sourceMapsMock) { - return (0, _createStore2.default)({ - log: false, - history: (0, _history.getHistory)(), - makeThunkArgs: args => { - return _objectSpread({}, args, { - client, - sourceMaps: sourceMapsMock !== undefined ? sourceMapsMock : _devtoolsSourceMap2.default - }); - } - })((0, _redux.combineReducers)(_reducers2.default), initialState); -} -/** - * @memberof utils/test-head - * @static - */ - - -function commonLog(msg, data = {}) { - console.log(`[INFO] ${msg} ${JSON.stringify(data)}`); -} - -function makeFrame({ - id, - sourceId -}, opts = {}) { - return _objectSpread({ - id, - scope: [], - location: { - sourceId, - line: 4 - } - }, opts); -} -/** - * @memberof utils/test-head - * @static - */ - - -function makeSource(name, props = {}) { - return _objectSpread({ - id: name, - loadedState: "unloaded", - url: `http://localhost:8000/examples/${name}` - }, props); -} - -function makeOriginalSource(name, props) { - const source = makeSource(name, props); - return _objectSpread({}, source, { - id: `${name}-original` - }); -} - -function makeSourceRecord(name, props = {}) { - return I.Map(makeSource(name, props)); -} - -function makeFuncLocation(startLine, endLine) { - if (!endLine) { - endLine = startLine + 1; - } - - return { - start: { - line: startLine - }, - end: { - line: endLine - } - }; -} - -function makeSymbolDeclaration(name, start, end, klass) { - return { - id: `${name}:${start}`, - name, - location: makeFuncLocation(start, end), - klass - }; -} -/** - * @memberof utils/test-head - * @static - */ - - -function waitForState(store, predicate) { - return new Promise(resolve => { - let ret = predicate(store.getState()); - - if (ret) { - resolve(ret); - } - - const unsubscribe = store.subscribe(() => { - ret = predicate(store.getState()); - - if (ret) { - unsubscribe(); - resolve(ret); - } - }); - }); -} - -exports.actions = _actions2.default; -exports.selectors = selectors; -exports.reducers = _reducers2.default; -exports.createStore = createStore; -exports.commonLog = commonLog; -exports.makeFrame = makeFrame; -exports.makeSource = makeSource; -exports.makeOriginalSource = makeOriginalSource; -exports.makeSourceRecord = makeSourceRecord; -exports.makeSymbolDeclaration = makeSymbolDeclaration; -exports.waitForState = waitForState; -exports.getHistory = _history.getHistory; \ No newline at end of file diff --git a/devtools/client/debugger/new/src/utils/text.js b/devtools/client/debugger/new/src/utils/text.js index aa5f7afe824c..23165c648fe3 100644 --- a/devtools/client/debugger/new/src/utils/text.js +++ b/devtools/client/debugger/new/src/utils/text.js @@ -3,7 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true }); -exports.formatKeyShortcut = undefined; +exports.truncateMiddleText = exports.formatKeyShortcut = undefined; var _devtoolsModules = require("devtools/client/debugger/new/dist/vendors").vendored["devtools-modules"]; @@ -40,5 +40,26 @@ function formatKeyShortcut(shortcut) { return shortcut.replace(/CommandOrControl\+|CmdOrCtrl\+/g, `${L10N.getStr("ctrl")} `).replace(/Shift\+/g, "Shift "); } +/** + * Truncates the received text to the maxLength in the format: + * Original: 'this is a very long text and ends here' + * Truncated: 'this is a ver...and ends here' + * @param {String} sourceText - Source text + * @param {Number} maxLength - Max allowed length + * @memberof utils/text + * @static + */ -exports.formatKeyShortcut = formatKeyShortcut; \ No newline at end of file + +function truncateMiddleText(sourceText, maxLength) { + let truncatedText = sourceText; + + if (sourceText.length > maxLength) { + truncatedText = `${sourceText.substring(0, Math.round(maxLength / 2) - 2)}...${sourceText.substring(sourceText.length - Math.round(maxLength / 2 - 1))}`; + } + + return truncatedText; +} + +exports.formatKeyShortcut = formatKeyShortcut; +exports.truncateMiddleText = truncateMiddleText; \ No newline at end of file diff --git a/devtools/client/debugger/new/src/workers/parser/getScopes/visitor.js b/devtools/client/debugger/new/src/workers/parser/getScopes/visitor.js index 92b0fa50296c..e500ff710931 100644 --- a/devtools/client/debugger/new/src/workers/parser/getScopes/visitor.js +++ b/devtools/client/debugger/new/src/workers/parser/getScopes/visitor.js @@ -89,7 +89,7 @@ function toParsedScopes(children, sourceId) { return { start: scope.loc.start, end: scope.loc.end, - type: scope.type === "module" ? "block" : scope.type, + type: scope.type === "module" || scope.type === "function-body" ? "block" : scope.type, displayName: scope.displayName, bindings: scope.bindings, children: toParsedScopes(scope.children, sourceId) @@ -190,10 +190,20 @@ function isLetOrConst(node) { } function hasLexicalDeclaration(node, parent) { + const nodes = []; + + if (t.isSwitchStatement(node)) { + for (const caseNode of node.cases) { + nodes.push(...caseNode.consequent); + } + } else { + nodes.push(...node.body); + } + const isFunctionBody = t.isFunction(parent, { body: node }); - return node.body.some(child => isLexicalVariable(child) || !isFunctionBody && child.type === "FunctionDeclaration" || child.type === "ClassDeclaration"); + return nodes.some(child => isLexicalVariable(child) || t.isClassDeclaration(child) || !isFunctionBody && t.isFunctionDeclaration(child)); } function isLexicalVariable(node) { @@ -257,19 +267,27 @@ const scopeCollectionVisitor = { // This ignores Annex B function declaration hoisting, which // is probably a fine assumption. state.declarationBindingIds.add(node.id); - const fnScope = getVarScope(scope); - scope.bindings[node.id.name] = { - type: fnScope === scope ? "var" : "let", - refs: [{ - type: "fn-decl", - start: fromBabelLocation(node.id.loc.start, state.sourceId), - end: fromBabelLocation(node.id.loc.end, state.sourceId), - declaration: { - start: fromBabelLocation(node.loc.start, state.sourceId), - end: fromBabelLocation(node.loc.end, state.sourceId) - } - }] - }; + const refs = [{ + type: "fn-decl", + start: fromBabelLocation(node.id.loc.start, state.sourceId), + end: fromBabelLocation(node.id.loc.end, state.sourceId), + declaration: { + start: fromBabelLocation(node.loc.start, state.sourceId), + end: fromBabelLocation(node.loc.end, state.sourceId) + } + }]; + + if (scope.type === "block") { + scope.bindings[node.id.name] = { + type: "let", + refs + }; + } else { + getVarScope(scope).bindings[node.id.name] = { + type: "var", + refs + }; + } } scope = pushTempScope(state, "function", (0, _getFunctionName2.default)(node, parentNode), { @@ -290,6 +308,13 @@ const scopeCollectionVisitor = { refs: [] }; } + + if (t.isBlockStatement(node.body) && hasLexicalDeclaration(node.body, node)) { + scope = pushTempScope(state, "function-body", "Function Body", { + start: fromBabelLocation(node.body.loc.start, state.sourceId), + end: fromBabelLocation(node.body.loc.end, state.sourceId) + }); + } } else if (t.isClass(node)) { if (t.isIdentifier(node.id)) { // For decorated classes, the AST considers the first the decorator @@ -359,7 +384,8 @@ const scopeCollectionVisitor = { end: fromBabelLocation(node.loc.end, state.sourceId) }); parseDeclarator(node.param, scope, "var", "catch", node, state); - } else if (t.isBlockStatement(node) && hasLexicalDeclaration(node, parentNode)) { + } else if (t.isBlockStatement(node) && // Function body's are handled in the function logic above. + !t.isFunction(parentNode) && hasLexicalDeclaration(node, parentNode)) { // Debugger will create new lexical environment for the block. pushTempScope(state, "block", "Block", { start: fromBabelLocation(node.loc.start, state.sourceId), @@ -489,7 +515,7 @@ const scopeCollectionVisitor = { type: "implicit", refs: [] }; - } else if (t.isSwitchStatement(node) && node.cases.some(caseNode => caseNode.consequent.some(child => isLexicalVariable(child)))) { + } else if (t.isSwitchStatement(node) && hasLexicalDeclaration(node, parentNode)) { pushTempScope(state, "block", "Switch", { start: fromBabelLocation(node.loc.start, state.sourceId), end: fromBabelLocation(node.loc.end, state.sourceId) diff --git a/devtools/client/debugger/new/test/mochitest/browser.ini b/devtools/client/debugger/new/test/mochitest/browser.ini index 5eeb81513049..e81239fb1096 100644 --- a/devtools/client/debugger/new/test/mochitest/browser.ini +++ b/devtools/client/debugger/new/test/mochitest/browser.ini @@ -31,6 +31,8 @@ support-files = examples/sourcemapped/fixtures/babel-for-loops/output.js.map examples/sourcemapped/fixtures/babel-functions/output.js examples/sourcemapped/fixtures/babel-functions/output.js.map + examples/sourcemapped/fixtures/babel-lex-and-nonlex/output.js + examples/sourcemapped/fixtures/babel-lex-and-nonlex/output.js.map examples/sourcemapped/fixtures/babel-type-module/output.js examples/sourcemapped/fixtures/babel-type-module/output.js.map examples/sourcemapped/fixtures/babel-type-script/output.js diff --git a/devtools/client/debugger/new/test/mochitest/browser_dbg-scopes-mutations.js b/devtools/client/debugger/new/test/mochitest/browser_dbg-scopes-mutations.js index 9b64e80b10b5..22902a31f43c 100644 --- a/devtools/client/debugger/new/test/mochitest/browser_dbg-scopes-mutations.js +++ b/devtools/client/debugger/new/test/mochitest/browser_dbg-scopes-mutations.js @@ -25,7 +25,7 @@ add_task(async function() { let onPaused = waitForPaused(dbg); invokeInTab("mutate"); await onPaused; - await waitForLoadedSource(dbg, "script-mutate"); + await waitForSelectedSource(dbg, "script-mutate"); is( getScopeNodeLabel(dbg, 2), diff --git a/devtools/client/debugger/new/test/mochitest/browser_dbg-sourcemapped-scopes.js b/devtools/client/debugger/new/test/mochitest/browser_dbg-sourcemapped-scopes.js index 9ffaea369eeb..8f54112e4bc6 100644 --- a/devtools/client/debugger/new/test/mochitest/browser_dbg-sourcemapped-scopes.js +++ b/devtools/client/debugger/new/test/mochitest/browser_dbg-sourcemapped-scopes.js @@ -46,7 +46,7 @@ add_task(async function() { "Block", ["three", "5"], ["two", "4"], - "Block", + "Function Body", ["three", "3"], ["two", "2"], "root", @@ -73,7 +73,7 @@ add_task(async function() { ["aConst", '"const2"'], ["aLet", '"let2"'], "Outer:_Outer()", - "Block", + "Function Body", ["aConst", '"const1"'], ["aLet", '"let1"'], "Outer()", @@ -86,7 +86,7 @@ add_task(async function() { "babel-line-start-bindings-es6", { line: 19, column: 4 }, [ - "Block", + "Function Body", ["", "{\u2026}"], ["one", "1"], ["two", "2"], @@ -102,7 +102,7 @@ add_task(async function() { "babel-this-arguments-bindings", { line: 4, column: 4 }, [ - "Block", + "Function Body", ["", '"this-value"'], ["arrow", "undefined"], "fn", @@ -123,7 +123,7 @@ add_task(async function() { "arrow", ["", '"this-value"'], ["argArrow", '"arrow-arg"'], - "Block", + "Function Body", "arrow()", "fn", ["arg", '"arg-value"'], @@ -158,12 +158,12 @@ add_task(async function() { ]); await breakpointScopes(dbg, "babel-classes", { line: 12, column: 6 }, [ - "Block", + "Function Body", ["three", "3"], ["two", "2"], "Class", "Another()", - "Block", + "Function Body", "Another()", ["one", "1"], "Thing()", @@ -174,7 +174,7 @@ add_task(async function() { await breakpointScopes(dbg, "babel-for-loops", { line: 5, column: 4 }, [ "For", ["i", "1"], - "Block", + "Function Body", ["i", "0"], "Module", "root()" @@ -183,7 +183,7 @@ add_task(async function() { await breakpointScopes(dbg, "babel-for-loops", { line: 9, column: 4 }, [ "For", ["i", '"2"'], - "Block", + "Function Body", ["i", "0"], "Module", "root()" @@ -192,7 +192,7 @@ add_task(async function() { await breakpointScopes(dbg, "babel-for-loops", { line: 13, column: 4 }, [ "For", ["i", "3"], - "Block", + "Function Body", ["i", "0"], "Module", "root()" @@ -201,13 +201,13 @@ add_task(async function() { await breakpointScopes(dbg, "babel-functions", { line: 6, column: 8 }, [ "arrow", ["p3", "undefined"], - "Block", + "Function Body", "arrow()", "inner", ["p2", "undefined"], "Function Expression", "inner()", - "Block", + "Function Body", "inner()", "decl", ["p1", "undefined"], @@ -268,7 +268,7 @@ add_task(async function() { await breakpointScopes(dbg, "babel-switches", { line: 7, column: 6 }, [ "Switch", ["val", "2"], - "Block", + "Function Body", ["val", "1"], "Module", "root()" @@ -279,7 +279,7 @@ add_task(async function() { ["val", "3"], "Switch", ["val", "2"], - "Block", + "Function Body", ["val", "1"], "Module", "root()" @@ -290,12 +290,21 @@ add_task(async function() { ["two", "2"], "Catch", ["err", '"AnError"'], - "Block", + "Function Body", ["one", "1"], "Module", "root()" ]); + await breakpointScopes(dbg, "babel-lex-and-nonlex", { line: 3, column: 4 }, [ + "Function Body", + "Thing()", + "root", + "someHelper()", + "Module", + "root()" + ]); + await breakpointScopes( dbg, "babel-modules-webpack", diff --git a/devtools/client/debugger/new/test/mochitest/browser_dbg-sourcemaps3.js b/devtools/client/debugger/new/test/mochitest/browser_dbg-sourcemaps3.js index 725dab3cbdda..4998590a8b26 100644 --- a/devtools/client/debugger/new/test/mochitest/browser_dbg-sourcemaps3.js +++ b/devtools/client/debugger/new/test/mochitest/browser_dbg-sourcemaps3.js @@ -40,7 +40,7 @@ add_task(async function() { is(getScopeLabel(dbg, 2), "na"); is(getScopeLabel(dbg, 3), "nb"); - is(getScopeLabel(dbg, 4), "Block"); + is(getScopeLabel(dbg, 4), "Function Body"); await toggleScopeNode(dbg, 4); diff --git a/devtools/client/debugger/new/test/mochitest/examples/doc-sourcemapped.html b/devtools/client/debugger/new/test/mochitest/examples/doc-sourcemapped.html index 27c85734fddd..7674d43f9765 100644 --- a/devtools/client/debugger/new/test/mochitest/examples/doc-sourcemapped.html +++ b/devtools/client/debugger/new/test/mochitest/examples/doc-sourcemapped.html @@ -27,6 +27,8 @@ + + diff --git a/devtools/client/debugger/new/test/mochitest/examples/sourcemapped/fixtures/babel-lex-and-nonlex/input.js b/devtools/client/debugger/new/test/mochitest/examples/sourcemapped/fixtures/babel-lex-and-nonlex/input.js new file mode 100644 index 000000000000..5704081677d6 --- /dev/null +++ b/devtools/client/debugger/new/test/mochitest/examples/sourcemapped/fixtures/babel-lex-and-nonlex/input.js @@ -0,0 +1,9 @@ +export default function root() { + function someHelper(){ + console.log("pause here", root, Thing); + } + + class Thing {} + + someHelper(); +} diff --git a/devtools/client/debugger/new/test/mochitest/examples/sourcemapped/fixtures/babel-lex-and-nonlex/output.js b/devtools/client/debugger/new/test/mochitest/examples/sourcemapped/fixtures/babel-lex-and-nonlex/output.js new file mode 100644 index 000000000000..5946da6f9cf7 --- /dev/null +++ b/devtools/client/debugger/new/test/mochitest/examples/sourcemapped/fixtures/babel-lex-and-nonlex/output.js @@ -0,0 +1,90 @@ +var babelLexAndNonlex = +/******/ (function(modules) { // webpackBootstrap +/******/ // The module cache +/******/ var installedModules = {}; +/******/ +/******/ // The require function +/******/ function __webpack_require__(moduleId) { +/******/ +/******/ // Check if module is in cache +/******/ if(installedModules[moduleId]) { +/******/ return installedModules[moduleId].exports; +/******/ } +/******/ // Create a new module (and put it into the cache) +/******/ var module = installedModules[moduleId] = { +/******/ i: moduleId, +/******/ l: false, +/******/ exports: {} +/******/ }; +/******/ +/******/ // Execute the module function +/******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__); +/******/ +/******/ // Flag the module as loaded +/******/ module.l = true; +/******/ +/******/ // Return the exports of the module +/******/ return module.exports; +/******/ } +/******/ +/******/ +/******/ // expose the modules object (__webpack_modules__) +/******/ __webpack_require__.m = modules; +/******/ +/******/ // expose the module cache +/******/ __webpack_require__.c = installedModules; +/******/ +/******/ // define getter function for harmony exports +/******/ __webpack_require__.d = function(exports, name, getter) { +/******/ if(!__webpack_require__.o(exports, name)) { +/******/ Object.defineProperty(exports, name, { +/******/ configurable: false, +/******/ enumerable: true, +/******/ get: getter +/******/ }); +/******/ } +/******/ }; +/******/ +/******/ // getDefaultExport function for compatibility with non-harmony modules +/******/ __webpack_require__.n = function(module) { +/******/ var getter = module && module.__esModule ? +/******/ function getDefault() { return module['default']; } : +/******/ function getModuleExports() { return module; }; +/******/ __webpack_require__.d(getter, 'a', getter); +/******/ return getter; +/******/ }; +/******/ +/******/ // Object.prototype.hasOwnProperty.call +/******/ __webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); }; +/******/ +/******/ // __webpack_public_path__ +/******/ __webpack_require__.p = ""; +/******/ +/******/ // Load entry module and return exports +/******/ return __webpack_require__(__webpack_require__.s = 0); +/******/ }) +/************************************************************************/ +/******/ ([ +/* 0 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +Object.defineProperty(__webpack_exports__, "__esModule", { value: true }); +/* harmony export (immutable) */ __webpack_exports__["default"] = root; +function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } + +function root() { + function someHelper() { + console.log("pause here", root, Thing); + } + + var Thing = function Thing() { + _classCallCheck(this, Thing); + }; + + someHelper(); +} + +/***/ }) +/******/ ])["default"]; +//# sourceMappingURL=output.js.map \ No newline at end of file diff --git a/devtools/client/debugger/new/test/mochitest/examples/sourcemapped/fixtures/babel-lex-and-nonlex/output.js.map b/devtools/client/debugger/new/test/mochitest/examples/sourcemapped/fixtures/babel-lex-and-nonlex/output.js.map new file mode 100644 index 000000000000..2685157d69ee --- /dev/null +++ b/devtools/client/debugger/new/test/mochitest/examples/sourcemapped/fixtures/babel-lex-and-nonlex/output.js.map @@ -0,0 +1 @@ +{"version":3,"sources":["webpack:///webpack/bootstrap 683415abc3361bb5ff85","webpack:///./fixtures/babel-lex-and-nonlex/input.js"],"names":["root","someHelper","console","log","Thing"],"mappings":";;AAAA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;;;AAGA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,aAAK;AACL;AACA;;AAEA;AACA;AACA;AACA,mCAA2B,0BAA0B,EAAE;AACvD,yCAAiC,eAAe;AAChD;AACA;AACA;;AAEA;AACA,8DAAsD,+DAA+D;;AAErH;AACA;;AAEA;AACA;;;;;;;;;;;;AC7De,SAASA,IAAT,GAAgB;AAC7B,WAASC,UAAT,GAAqB;AACnBC,YAAQC,GAAR,CAAY,YAAZ,EAA0BH,IAA1B,EAAgCI,KAAhC;AACD;;AAH4B,MAKvBA,KALuB;AAAA;AAAA;;AAO7BH;AACD,C","file":"fixtures/babel-lex-and-nonlex/output.js","sourcesContent":[" \t// The module cache\n \tvar installedModules = {};\n\n \t// The require function\n \tfunction __webpack_require__(moduleId) {\n\n \t\t// Check if module is in cache\n \t\tif(installedModules[moduleId]) {\n \t\t\treturn installedModules[moduleId].exports;\n \t\t}\n \t\t// Create a new module (and put it into the cache)\n \t\tvar module = installedModules[moduleId] = {\n \t\t\ti: moduleId,\n \t\t\tl: false,\n \t\t\texports: {}\n \t\t};\n\n \t\t// Execute the module function\n \t\tmodules[moduleId].call(module.exports, module, module.exports, __webpack_require__);\n\n \t\t// Flag the module as loaded\n \t\tmodule.l = true;\n\n \t\t// Return the exports of the module\n \t\treturn module.exports;\n \t}\n\n\n \t// expose the modules object (__webpack_modules__)\n \t__webpack_require__.m = modules;\n\n \t// expose the module cache\n \t__webpack_require__.c = installedModules;\n\n \t// define getter function for harmony exports\n \t__webpack_require__.d = function(exports, name, getter) {\n \t\tif(!__webpack_require__.o(exports, name)) {\n \t\t\tObject.defineProperty(exports, name, {\n \t\t\t\tconfigurable: false,\n \t\t\t\tenumerable: true,\n \t\t\t\tget: getter\n \t\t\t});\n \t\t}\n \t};\n\n \t// getDefaultExport function for compatibility with non-harmony modules\n \t__webpack_require__.n = function(module) {\n \t\tvar getter = module && module.__esModule ?\n \t\t\tfunction getDefault() { return module['default']; } :\n \t\t\tfunction getModuleExports() { return module; };\n \t\t__webpack_require__.d(getter, 'a', getter);\n \t\treturn getter;\n \t};\n\n \t// Object.prototype.hasOwnProperty.call\n \t__webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };\n\n \t// __webpack_public_path__\n \t__webpack_require__.p = \"\";\n\n \t// Load entry module and return exports\n \treturn __webpack_require__(__webpack_require__.s = 0);\n\n\n\n// WEBPACK FOOTER //\n// webpack/bootstrap 683415abc3361bb5ff85","export default function root() {\n function someHelper(){\n console.log(\"pause here\", root, Thing);\n }\n\n class Thing {}\n\n someHelper();\n}\n\n\n\n// WEBPACK FOOTER //\n// ./fixtures/babel-lex-and-nonlex/input.js"],"sourceRoot":""} \ No newline at end of file diff --git a/devtools/client/shared/source-map/index.js b/devtools/client/shared/source-map/index.js index 45519e8a15ce..5c25d5953d12 100644 --- a/devtools/client/shared/source-map/index.js +++ b/devtools/client/shared/source-map/index.js @@ -437,6 +437,7 @@ const { const dispatcher = new WorkerDispatcher(); const getOriginalURLs = dispatcher.task("getOriginalURLs"); +const getOriginalRanges = dispatcher.task("getOriginalRanges"); const getGeneratedRanges = dispatcher.task("getGeneratedRanges", { queue: true }); @@ -460,6 +461,7 @@ module.exports = { isOriginalId, hasMappedSource, getOriginalURLs, + getOriginalRanges, getGeneratedRanges, getGeneratedLocation, getAllGeneratedLocations, diff --git a/devtools/client/shared/source-map/worker.js b/devtools/client/shared/source-map/worker.js index 4526735b6402..a47f7e44c8e2 100644 --- a/devtools/client/shared/source-map/worker.js +++ b/devtools/client/shared/source-map/worker.js @@ -1973,6 +1973,7 @@ exports.ArraySet = ArraySet; const { getOriginalURLs, + getOriginalRanges, getGeneratedRanges, getGeneratedLocation, getAllGeneratedLocations, @@ -1993,6 +1994,7 @@ const { // easier to unit test. self.onmessage = workerHandler({ getOriginalURLs, + getOriginalRanges, getGeneratedRanges, getGeneratedLocation, getAllGeneratedLocations, @@ -2046,6 +2048,57 @@ async function getOriginalURLs(generatedSource) { const COMPUTED_SPANS = new WeakSet(); +const SOURCE_MAPPINGS = new WeakMap(); +async function getOriginalRanges(sourceId, url) { + if (!isOriginalId(sourceId)) { + return []; + } + + const generatedSourceId = originalToGeneratedId(sourceId); + const map = await getSourceMap(generatedSourceId); + if (!map) { + return []; + } + + let mappings = SOURCE_MAPPINGS.get(map); + if (!mappings) { + mappings = new Map(); + SOURCE_MAPPINGS.set(map, mappings); + } + + let fileMappings = mappings.get(url); + if (!fileMappings) { + fileMappings = []; + mappings.set(url, fileMappings); + + const originalMappings = fileMappings; + map.eachMapping(mapping => { + if (mapping.source !== url) { + return; + } + + const last = originalMappings[originalMappings.length - 1]; + + if (last && last.line === mapping.originalLine) { + if (last.columnStart < mapping.originalColumn) { + last.columnEnd = mapping.originalColumn; + } else { + // Skip this duplicate original location, + return; + } + } + + originalMappings.push({ + line: mapping.originalLine, + columnStart: mapping.originalColumn, + columnEnd: Infinity + }); + }, null, SourceMapConsumer.ORIGINAL_ORDER); + } + + return fileMappings; +} + /** * Given an original location, find the ranges on the generated file that * are mapped from the original range containing the location. @@ -2234,6 +2287,7 @@ function applySourceMap(generatedId, url, code, mappings) { module.exports = { getOriginalURLs, + getOriginalRanges, getGeneratedRanges, getGeneratedLocation, getAllGeneratedLocations, diff --git a/devtools/client/shared/vendor/WasmDis.js b/devtools/client/shared/vendor/WasmDis.js index 0a73193e1cea..e84b2b975769 100644 --- a/devtools/client/shared/vendor/WasmDis.js +++ b/devtools/client/shared/vendor/WasmDis.js @@ -956,7 +956,9 @@ var WasmDisassembler = /** @class */ (function () { case 30 /* CODE_OPERATOR */: var operator = reader.result; if (operator.code == 11 /* end */ && this._indentLevel == 0) { - // reached of the function, skipping the operator + // reached of the function, closing function body + this.appendBuffer(" )"); + this.newLine(); break; } switch (operator.code) { @@ -980,8 +982,7 @@ var WasmDisassembler = /** @class */ (function () { case 31 /* END_FUNCTION_BODY */: this._funcIndex++; this._backrefLabels = null; - this.appendBuffer(" )"); - this.newLine(); + // See case BinaryReaderState.CODE_OPERATOR for closing of body break; default: throw new Error("Expectected state: " + reader.state); diff --git a/devtools/client/sourceeditor/codemirror/addon/runmode/runmode.js b/devtools/client/sourceeditor/codemirror/addon/runmode/runmode.js new file mode 100644 index 000000000000..5540a2531fc7 --- /dev/null +++ b/devtools/client/sourceeditor/codemirror/addon/runmode/runmode.js @@ -0,0 +1,72 @@ +// CodeMirror, copyright (c) by Marijn Haverbeke and others +// Distributed under an MIT license: http://codemirror.net/LICENSE + +(function(mod) { + if (typeof exports == "object" && typeof module == "object") // CommonJS + mod(require("../../lib/codemirror")); + else if (typeof define == "function" && define.amd) // AMD + define(["../../lib/codemirror"], mod); + else // Plain browser env + mod(CodeMirror); +})(function(CodeMirror) { +"use strict"; + +CodeMirror.runMode = function(string, modespec, callback, options) { + var mode = CodeMirror.getMode(CodeMirror.defaults, modespec); + var ie = /MSIE \d/.test(navigator.userAgent); + var ie_lt9 = ie && (document.documentMode == null || document.documentMode < 9); + + if (callback.appendChild) { + var tabSize = (options && options.tabSize) || CodeMirror.defaults.tabSize; + var node = callback, col = 0; + node.innerHTML = ""; + callback = function(text, style) { + if (text == "\n") { + // Emitting LF or CRLF on IE8 or earlier results in an incorrect display. + // Emitting a carriage return makes everything ok. + node.appendChild(document.createTextNode(ie_lt9 ? '\r' : text)); + col = 0; + return; + } + var content = ""; + // replace tabs + for (var pos = 0;;) { + var idx = text.indexOf("\t", pos); + if (idx == -1) { + content += text.slice(pos); + col += text.length - pos; + break; + } else { + col += idx - pos; + content += text.slice(pos, idx); + var size = tabSize - col % tabSize; + col += size; + for (var i = 0; i < size; ++i) content += " "; + pos = idx + 1; + } + } + + if (style) { + var sp = node.appendChild(document.createElement("span")); + sp.className = "cm-" + style.replace(/ +/g, " cm-"); + sp.appendChild(document.createTextNode(content)); + } else { + node.appendChild(document.createTextNode(content)); + } + }; + } + + var lines = CodeMirror.splitLines(string), state = (options && options.state) || CodeMirror.startState(mode); + for (var i = 0, e = lines.length; i < e; ++i) { + if (i) callback("\n"); + var stream = new CodeMirror.StringStream(lines[i]); + if (!stream.string && mode.blankLine) mode.blankLine(state); + while (!stream.eol()) { + var style = mode.token(stream, state); + callback(stream.current(), style, i, stream.start, state); + stream.start = stream.pos; + } + } +}; + +}); \ No newline at end of file diff --git a/devtools/client/sourceeditor/codemirror/codemirror.bundle.js b/devtools/client/sourceeditor/codemirror/codemirror.bundle.js index f5a9c22cc809..f327afebda71 100644 --- a/devtools/client/sourceeditor/codemirror/codemirror.bundle.js +++ b/devtools/client/sourceeditor/codemirror/codemirror.bundle.js @@ -1 +1,22554 @@ -var CodeMirror=function(e){var t={};function n(r){if(t[r])return t[r].exports;var i=t[r]={i:r,l:!1,exports:{}};return e[r].call(i.exports,i,i.exports,n),i.l=!0,i.exports}return n.m=e,n.c=t,n.d=function(e,t,r){n.o(e,t)||Object.defineProperty(e,t,{configurable:!1,enumerable:!0,get:r})},n.r=function(e){Object.defineProperty(e,"__esModule",{value:!0})},n.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return n.d(t,"a",t),t},n.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},n.p="",n(n.s=26)}([function(e,t,n){e.exports=function(){"use strict";var e=navigator.userAgent,t=navigator.platform,n=/gecko\/\d/i.test(e),r=/MSIE \d/.test(e),i=/Trident\/(?:[7-9]|\d{2,})\..*rv:(\d+)/.exec(e),o=/Edge\/(\d+)/.exec(e),a=r||i||o,l=a&&(r?document.documentMode||6:+(o||i)[1]),s=!o&&/WebKit\//.test(e),c=s&&/Qt\/\d+\.\d+/.test(e),u=!o&&/Chrome\//.test(e),f=/Opera\//.test(e),d=/Apple Computer/.test(navigator.vendor),h=/Mac OS X 1\d\D([8-9]|\d\d)\D/.test(e),p=/PhantomJS/.test(e),m=!o&&/AppleWebKit/.test(e)&&/Mobile\/\w+/.test(e),g=/Android/.test(e),v=m||g||/webOS|BlackBerry|Opera Mini|Opera Mobi|IEMobile/i.test(e),y=m||/Mac/.test(t),b=/\bCrOS\b/.test(e),w=/win/i.test(t),x=f&&e.match(/Version\/(\d*\.\d*)/);x&&(x=Number(x[1])),x&&x>=15&&(f=!1,s=!0);var k=y&&(c||f&&(null==x||x<12.11)),C=n||a&&l>=9;function S(e){return new RegExp("(^|\\s)"+e+"(?:$|\\s)\\s*")}var L,M=function(e,t){var n=e.className,r=S(t).exec(n);if(r){var i=n.slice(r.index+r[0].length);e.className=n.slice(0,r.index)+(i?r[1]+i:"")}};function T(e){for(var t=e.childNodes.length;t>0;--t)e.removeChild(e.firstChild);return e}function A(e,t){return T(e).appendChild(t)}function O(e,t,n,r){var i=document.createElement(e);if(n&&(i.className=n),r&&(i.style.cssText=r),"string"==typeof t)i.appendChild(document.createTextNode(t));else if(t)for(var o=0;o=t)return a+(t-o);a+=l-o,a+=n-a%n,o=l+1}}m?B=function(e){e.selectionStart=0,e.selectionEnd=e.value.length}:a&&(B=function(e){try{e.select()}catch(e){}});var z=function(){this.id=null};function _(e,t){for(var n=0;n=t)return r+Math.min(a,t-i);if(i+=o-r,r=o+1,(i+=n-i%n)>=t)return r}}var $=[""];function G(e){for(;$.length<=e;)$.push(X($)+" ");return $[e]}function X(e){return e[e.length-1]}function Y(e,t){for(var n=[],r=0;r"€"&&(e.toUpperCase()!=e.toLowerCase()||Z.test(e))}function te(e,t){return t?!!(t.source.indexOf("\\w")>-1&&ee(e))||t.test(e):ee(e)}function ne(e){for(var t in e)if(e.hasOwnProperty(t)&&e[t])return!1;return!0}var re=/[\u0300-\u036f\u0483-\u0489\u0591-\u05bd\u05bf\u05c1\u05c2\u05c4\u05c5\u05c7\u0610-\u061a\u064b-\u065e\u0670\u06d6-\u06dc\u06de-\u06e4\u06e7\u06e8\u06ea-\u06ed\u0711\u0730-\u074a\u07a6-\u07b0\u07eb-\u07f3\u0816-\u0819\u081b-\u0823\u0825-\u0827\u0829-\u082d\u0900-\u0902\u093c\u0941-\u0948\u094d\u0951-\u0955\u0962\u0963\u0981\u09bc\u09be\u09c1-\u09c4\u09cd\u09d7\u09e2\u09e3\u0a01\u0a02\u0a3c\u0a41\u0a42\u0a47\u0a48\u0a4b-\u0a4d\u0a51\u0a70\u0a71\u0a75\u0a81\u0a82\u0abc\u0ac1-\u0ac5\u0ac7\u0ac8\u0acd\u0ae2\u0ae3\u0b01\u0b3c\u0b3e\u0b3f\u0b41-\u0b44\u0b4d\u0b56\u0b57\u0b62\u0b63\u0b82\u0bbe\u0bc0\u0bcd\u0bd7\u0c3e-\u0c40\u0c46-\u0c48\u0c4a-\u0c4d\u0c55\u0c56\u0c62\u0c63\u0cbc\u0cbf\u0cc2\u0cc6\u0ccc\u0ccd\u0cd5\u0cd6\u0ce2\u0ce3\u0d3e\u0d41-\u0d44\u0d4d\u0d57\u0d62\u0d63\u0dca\u0dcf\u0dd2-\u0dd4\u0dd6\u0ddf\u0e31\u0e34-\u0e3a\u0e47-\u0e4e\u0eb1\u0eb4-\u0eb9\u0ebb\u0ebc\u0ec8-\u0ecd\u0f18\u0f19\u0f35\u0f37\u0f39\u0f71-\u0f7e\u0f80-\u0f84\u0f86\u0f87\u0f90-\u0f97\u0f99-\u0fbc\u0fc6\u102d-\u1030\u1032-\u1037\u1039\u103a\u103d\u103e\u1058\u1059\u105e-\u1060\u1071-\u1074\u1082\u1085\u1086\u108d\u109d\u135f\u1712-\u1714\u1732-\u1734\u1752\u1753\u1772\u1773\u17b7-\u17bd\u17c6\u17c9-\u17d3\u17dd\u180b-\u180d\u18a9\u1920-\u1922\u1927\u1928\u1932\u1939-\u193b\u1a17\u1a18\u1a56\u1a58-\u1a5e\u1a60\u1a62\u1a65-\u1a6c\u1a73-\u1a7c\u1a7f\u1b00-\u1b03\u1b34\u1b36-\u1b3a\u1b3c\u1b42\u1b6b-\u1b73\u1b80\u1b81\u1ba2-\u1ba5\u1ba8\u1ba9\u1c2c-\u1c33\u1c36\u1c37\u1cd0-\u1cd2\u1cd4-\u1ce0\u1ce2-\u1ce8\u1ced\u1dc0-\u1de6\u1dfd-\u1dff\u200c\u200d\u20d0-\u20f0\u2cef-\u2cf1\u2de0-\u2dff\u302a-\u302f\u3099\u309a\ua66f-\ua672\ua67c\ua67d\ua6f0\ua6f1\ua802\ua806\ua80b\ua825\ua826\ua8c4\ua8e0-\ua8f1\ua926-\ua92d\ua947-\ua951\ua980-\ua982\ua9b3\ua9b6-\ua9b9\ua9bc\uaa29-\uaa2e\uaa31\uaa32\uaa35\uaa36\uaa43\uaa4c\uaab0\uaab2-\uaab4\uaab7\uaab8\uaabe\uaabf\uaac1\uabe5\uabe8\uabed\udc00-\udfff\ufb1e\ufe00-\ufe0f\ufe20-\ufe26\uff9e\uff9f]/;function ie(e){return e.charCodeAt(0)>=768&&re.test(e)}function oe(e,t,n){for(;(n<0?t>0:tn?-1:1;;){if(t==n)return t;var i=(t+n)/2,o=r<0?Math.ceil(i):Math.floor(i);if(o==t)return e(o)?t:n;e(o)?n=o:t=o+r}}function le(e,t){if((t-=e.first)<0||t>=e.size)throw new Error("There is no line "+(t+e.first)+" in the document.");for(var n=e;!n.lines;)for(var r=0;;++r){var i=n.children[r],o=i.chunkSize();if(t=e.first&&tn?me(n,le(e,n).text.length):function(e,t){var n=e.ch;return null==n||n>t?me(e.line,t):n<0?me(e.line,0):e}(t,le(e,t.line).text.length)}function Ce(e,t){for(var n=[],r=0;r=t:o.to>t);(r||(r=[])).push(new Me(a,o.from,s?null:o.to))}}return r}(n,i,a),s=function(e,t,n){var r;if(e)for(var i=0;i=t:o.to>t);if(l||o.from==t&&"bookmark"==a.type&&(!n||o.marker.insertLeft)){var s=null==o.from||(a.inclusiveLeft?o.from<=t:o.from0&&l)for(var w=0;w=0&&f<=0||u<=0&&f>=0)&&(u<=0&&(s.marker.inclusiveRight&&i.inclusiveLeft?ge(c.to,n)>=0:ge(c.to,n)>0)||u>=0&&(s.marker.inclusiveRight&&i.inclusiveLeft?ge(c.from,r)<=0:ge(c.from,r)<0)))return!0}}}function _e(e){for(var t;t=Fe(e);)e=t.find(-1,!0).line;return e}function He(e,t){var n=le(e,t),r=_e(n);return n==r?t:fe(r)}function Ke(e,t){if(t>e.lastLine())return t;var n,r=le(e,t);if(!je(e,r))return t;for(;n=We(r);)r=n.find(1,!0).line;return fe(r)+1}function je(e,t){var n=Le&&t.markedSpans;if(n)for(var r=void 0,i=0;it.maxLineLength&&(t.maxLineLength=n,t.maxLine=e)})}var Ge=null;function Xe(e,t,n){var r;Ge=null;for(var i=0;it)return i;o.to==t&&(o.from!=o.to&&"before"==n?r=i:Ge=i),o.from==t&&(o.from!=o.to&&"before"!=n?r=i:Ge=i)}return null!=r?r:Ge}var Ye=function(){var e="bbbbbbbbbtstwsbbbbbbbbbbbbbbssstwNN%%%NNNNNN,N,N1111111111NNNNNNNLLLLLLLLLLLLLLLLLLLLLLLLLLNNNNNNLLLLLLLLLLLLLLLLLLLLLLLLLLNNNNbbbbbbsbbbbbbbbbbbbbbbbbbbbbbbbbb,N%%%%NNNNLNNNNN%%11NLNNN1LNNNNNLLLLLLLLLLLLLLLLLLLLLLLNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLN",t="nnnnnnNNr%%r,rNNmmmmmmmmmmmrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrmmmmmmmmmmmmmmmmmmmmmnnnnnnnnnn%nnrrrmrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrmmmmmmmnNmmmmmmrrmmNmmmmrr1111111111";var n=/[\u0590-\u05f4\u0600-\u06ff\u0700-\u08ac]/,r=/[stwN]/,i=/[LRr]/,o=/[Lb1n]/,a=/[1n]/;function l(e,t,n){this.level=e,this.from=t,this.to=n}return function(s,c){var u,f="ltr"==c?"L":"R";if(0==s.length||"ltr"==c&&!n.test(s))return!1;for(var d=s.length,h=[],p=0;p-1&&(r[t]=i.slice(0,o).concat(i.slice(o+1)))}}}function nt(e,t){var n=et(e,t);if(n.length)for(var r=Array.prototype.slice.call(arguments,2),i=0;i0}function at(e){e.prototype.on=function(e,t){Ze(this,e,t)},e.prototype.off=function(e,t){tt(this,e,t)}}function lt(e){e.preventDefault?e.preventDefault():e.returnValue=!1}function st(e){e.stopPropagation?e.stopPropagation():e.cancelBubble=!0}function ct(e){return null!=e.defaultPrevented?e.defaultPrevented:0==e.returnValue}function ut(e){lt(e),st(e)}function ft(e){return e.target||e.srcElement}function dt(e){var t=e.which;return null==t&&(1&e.button?t=1:2&e.button?t=3:4&e.button&&(t=2)),y&&e.ctrlKey&&1==t&&(t=3),t}var ht,pt,mt=function(){if(a&&l<9)return!1;var e=O("div");return"draggable"in e||"dragDrop"in e}();function gt(e){if(null==ht){var t=O("span","​");A(e,O("span",[t,document.createTextNode("x")])),0!=e.firstChild.offsetHeight&&(ht=t.offsetWidth<=1&&t.offsetHeight>2&&!(a&&l<8))}var n=ht?O("span","​"):O("span"," ",null,"display: inline-block; width: 1px; margin-right: -1px");return n.setAttribute("cm-text",""),n}function vt(e){if(null!=pt)return pt;var t=A(e,document.createTextNode("AخA")),n=L(t,0,1).getBoundingClientRect(),r=L(t,1,2).getBoundingClientRect();return T(e),!(!n||n.left==n.right)&&(pt=r.right-n.right<3)}var yt,bt=3!="\n\nb".split(/\n/).length?function(e){for(var t=0,n=[],r=e.length;t<=r;){var i=e.indexOf("\n",t);-1==i&&(i=e.length);var o=e.slice(t,"\r"==e.charAt(i-1)?i-1:i),a=o.indexOf("\r");-1!=a?(n.push(o.slice(0,a)),t+=a+1):(n.push(o),t=i+1)}return n}:function(e){return e.split(/\r\n?|\n/)},wt=window.getSelection?function(e){try{return e.selectionStart!=e.selectionEnd}catch(e){return!1}}:function(e){var t;try{t=e.ownerDocument.selection.createRange()}catch(e){}return!(!t||t.parentElement()!=e)&&0!=t.compareEndPoints("StartToEnd",t)},xt="oncopy"in(yt=O("div"))||(yt.setAttribute("oncopy","return;"),"function"==typeof yt.oncopy),kt=null,Ct={},St={};function Lt(e){if("string"==typeof e&&St.hasOwnProperty(e))e=St[e];else if(e&&"string"==typeof e.name&&St.hasOwnProperty(e.name)){var t=St[e.name];"string"==typeof t&&(t={name:t}),(e=Q(t,e)).name=t.name}else{if("string"==typeof e&&/^[\w\-]+\/[\w\-]+\+xml$/.test(e))return Lt("application/xml");if("string"==typeof e&&/^[\w\-]+\/[\w\-]+\+json$/.test(e))return Lt("application/json")}return"string"==typeof e?{name:e}:e||{name:"null"}}function Mt(e,t){t=Lt(t);var n=Ct[t.name];if(!n)return Mt(e,"text/plain");var r=n(e,t);if(Tt.hasOwnProperty(t.name)){var i=Tt[t.name];for(var o in i)i.hasOwnProperty(o)&&(r.hasOwnProperty(o)&&(r["_"+o]=r[o]),r[o]=i[o])}if(r.name=t.name,t.helperType&&(r.helperType=t.helperType),t.modeProps)for(var a in t.modeProps)r[a]=t.modeProps[a];return r}var Tt={};function At(e,t){var n=Tt.hasOwnProperty(e)?Tt[e]:Tt[e]={};F(t,n)}function Ot(e,t){if(!0===t)return t;if(e.copyState)return e.copyState(t);var n={};for(var r in t){var i=t[r];i instanceof Array&&(i=i.concat([])),n[r]=i}return n}function Et(e,t){for(var n;e.innerMode&&(n=e.innerMode(t))&&n.mode!=e;)t=n.state,e=n.mode;return n||{mode:e,state:t}}function Pt(e,t,n){return!e.startState||e.startState(t,n)}var Nt=function(e,t,n){this.pos=this.start=0,this.string=e,this.tabSize=t||8,this.lastColumnPos=this.lastColumnValue=0,this.lineStart=0,this.lineOracle=n};Nt.prototype.eol=function(){return this.pos>=this.string.length},Nt.prototype.sol=function(){return this.pos==this.lineStart},Nt.prototype.peek=function(){return this.string.charAt(this.pos)||void 0},Nt.prototype.next=function(){if(this.post},Nt.prototype.eatSpace=function(){for(var e=this.pos;/[\s\u00a0]/.test(this.string.charAt(this.pos));)++this.pos;return this.pos>e},Nt.prototype.skipToEnd=function(){this.pos=this.string.length},Nt.prototype.skipTo=function(e){var t=this.string.indexOf(e,this.pos);if(t>-1)return this.pos=t,!0},Nt.prototype.backUp=function(e){this.pos-=e},Nt.prototype.column=function(){return this.lastColumnPos0?null:(r&&!1!==t&&(this.pos+=r[0].length),r)}var i=function(e){return n?e.toLowerCase():e},o=this.string.substr(this.pos,e.length);if(i(o)==i(e))return!1!==t&&(this.pos+=e.length),!0},Nt.prototype.current=function(){return this.string.slice(this.start,this.pos)},Nt.prototype.hideFirstChars=function(e,t){this.lineStart+=e;try{return t()}finally{this.lineStart-=e}},Nt.prototype.lookAhead=function(e){var t=this.lineOracle;return t&&t.lookAhead(e)},Nt.prototype.baseToken=function(){var e=this.lineOracle;return e&&e.baseToken(this.pos)};var It=function(e,t){this.state=e,this.lookAhead=t},Rt=function(e,t,n,r){this.state=t,this.doc=e,this.line=n,this.maxLookAhead=r||0,this.baseTokens=null,this.baseTokenPos=1};function Bt(e,t,n,r){var i=[e.state.modeGen],o={};Ut(e,t.text,e.doc.mode,n,function(e,t){return i.push(e,t)},o,r);for(var a=n.state,l=function(r){n.baseTokens=i;var l=e.state.overlays[r],s=1,c=0;n.state=!0,Ut(e,t.text,l.mode,n,function(e,t){for(var n=s;ce&&i.splice(s,1,e,i[s+1],r),s+=2,c=Math.min(e,r)}if(t)if(l.opaque)i.splice(n,s-n,e,"overlay "+t),s=n+2;else for(;ne.options.maxHighlightLength&&Ot(e.doc.mode,r.state),o=Bt(e,t,r);i&&(r.state=i),t.stateAfter=r.save(!i),t.styles=o.styles,o.classes?t.styleClasses=o.classes:t.styleClasses&&(t.styleClasses=null),n===e.doc.highlightFrontier&&(e.doc.modeFrontier=Math.max(e.doc.modeFrontier,++e.doc.highlightFrontier))}return t.styles}function Ft(e,t,n){var r=e.doc,i=e.display;if(!r.mode.startState)return new Rt(r,!0,t);var o=function(e,t,n){for(var r,i,o=e.doc,a=n?-1:t-(e.doc.mode.innerMode?1e3:100),l=t;l>a;--l){if(l<=o.first)return o.first;var s=le(o,l-1),c=s.stateAfter;if(c&&(!n||l+(c instanceof It?c.lookAhead:0)<=o.modeFrontier))return l;var u=W(s.text,null,e.options.tabSize);(null==i||r>u)&&(i=l-1,r=u)}return i}(e,t,n),a=o>r.first&&le(r,o-1).stateAfter,l=a?Rt.fromSaved(r,a,o):new Rt(r,Pt(r.mode),o);return r.iter(o,t,function(n){Wt(e,n.text,l);var r=l.line;n.stateAfter=r==t-1||r%5==0||r>=i.viewFrom&&rt.start)return o}throw new Error("Mode "+e.name+" failed to advance stream.")}Rt.prototype.lookAhead=function(e){var t=this.doc.getLine(this.line+e);return null!=t&&e>this.maxLookAhead&&(this.maxLookAhead=e),t},Rt.prototype.baseToken=function(e){if(!this.baseTokens)return null;for(;this.baseTokens[this.baseTokenPos]<=e;)this.baseTokenPos+=2;var t=this.baseTokens[this.baseTokenPos+1];return{type:t&&t.replace(/( |^)overlay .*/,""),size:this.baseTokens[this.baseTokenPos]-e}},Rt.prototype.nextLine=function(){this.line++,this.maxLookAhead>0&&this.maxLookAhead--},Rt.fromSaved=function(e,t,n){return t instanceof It?new Rt(e,Ot(e.mode,t.state),n,t.lookAhead):new Rt(e,Ot(e.mode,t),n)},Rt.prototype.save=function(e){var t=!1!==e?Ot(this.doc.mode,this.state):this.state;return this.maxLookAhead>0?new It(t,this.maxLookAhead):t};var Ht=function(e,t,n){this.start=e.start,this.end=e.pos,this.string=e.current(),this.type=t||null,this.state=n};function Kt(e,t,n,r){var i,o=e.doc,a=o.mode;t=ke(o,t);var l,s=le(o,t.line),c=Ft(e,t.line,n),u=new Nt(s.text,e.options.tabSize,c);for(r&&(l=[]);(r||u.pose.options.maxHighlightLength?(l=!1,a&&Wt(e,t,r,f.pos),f.pos=t.length,s=null):s=jt(_t(n,f,r.state,d),o),d){var h=d[0].name;h&&(s="m-"+(s?h+" "+s:h))}if(!l||u!=s){for(;c1&&!/ /.test(e))return e;for(var n=t,r="",i=0;ic&&f.from<=c);d++);if(f.to>=u)return e(n,r,i,o,a,l,s);e(n,r.slice(0,f.to-c),i,o,null,l,s),o=null,r=r.slice(f.to-c),c=f.to}}}function en(e,t,n,r){var i=!r&&n.widgetNode;i&&e.map.push(e.pos,e.pos+t,i),!r&&e.cm.display.input.needsContentAttribute&&(i||(i=e.content.appendChild(document.createElement("span"))),i.setAttribute("cm-marker",n.id)),i&&(e.cm.display.input.setUneditable(i),e.content.appendChild(i)),e.pos+=t,e.trailingSpace=!1}function tn(e,t,n){var r=e.markedSpans,i=e.text,o=0;if(r)for(var a,l,s,c,u,f,d,h=i.length,p=0,m=1,g="",v=0;;){if(v==p){s=c=u=f=l="",d=null,v=1/0;for(var y=[],b=void 0,w=0;wp||k.collapsed&&x.to==p&&x.from==p)?(null!=x.to&&x.to!=p&&v>x.to&&(v=x.to,c=""),k.className&&(s+=" "+k.className),k.css&&(l=(l?l+";":"")+k.css),k.startStyle&&x.from==p&&(u+=" "+k.startStyle),k.endStyle&&x.to==v&&(b||(b=[])).push(k.endStyle,x.to),k.title&&!f&&(f=k.title),k.collapsed&&(!d||Be(d.marker,k)<0)&&(d=x)):x.from>p&&v>x.from&&(v=x.from)}if(b)for(var C=0;C=h)break;for(var L=Math.min(h,v);;){if(g){var M=p+g.length;if(!d){var T=M>L?g.slice(0,L-p):g;t.addToken(t,T,a?a+s:s,u,p+T.length==v?c:"",f,l)}if(M>=L){g=g.slice(L-p),p=L;break}p=M,u=""}g=i.slice(o,o=n[m++]),a=Xt(n[m++],t.cm.options)}}else for(var A=1;An)return{map:e.measure.maps[i],cache:e.measure.caches[i],before:!0}}function On(e,t,n,r){return Nn(e,Pn(e,t),n,r)}function En(e,t){if(t>=e.display.viewFrom&&t=n.lineN&&t2&&o.push((s.bottom+c.top)/2-n.top)}}o.push(n.bottom-n.top)}}(e,t.view,t.rect),t.hasHeights=!0),(o=function(e,t,n,r){var i,o=Bn(t.map,n,r),s=o.node,c=o.start,u=o.end,f=o.collapse;if(3==s.nodeType){for(var d=0;d<4;d++){for(;c&&ie(t.line.text.charAt(o.coverStart+c));)--c;for(;o.coverStart+u1}(e))return t;var n=screen.logicalXDPI/screen.deviceXDPI,r=screen.logicalYDPI/screen.deviceYDPI;return{left:t.left*n,right:t.right*n,top:t.top*r,bottom:t.bottom*r}}(e.display.measure,i))}else{var h;c>0&&(f=r="right"),i=e.options.lineWrapping&&(h=s.getClientRects()).length>1?h["right"==r?h.length-1:0]:s.getBoundingClientRect()}if(a&&l<9&&!c&&(!i||!i.left&&!i.right)){var p=s.parentNode.getClientRects()[0];i=p?{left:p.left,right:p.left+tr(e.display),top:p.top,bottom:p.bottom}:Rn}for(var m=i.top-t.rect.top,g=i.bottom-t.rect.top,v=(m+g)/2,y=t.view.measure.heights,b=0;bt)&&(i=(o=s-l)-1,t>=s&&(a="right")),null!=i){if(r=e[c+2],l==s&&n==(r.insertLeft?"left":"right")&&(a=n),"left"==n&&0==i)for(;c&&e[c-2]==e[c-3]&&e[c-1].insertLeft;)r=e[2+(c-=3)],a="left";if("right"==n&&i==s-l)for(;c=0&&(n=e[i]).left==n.right;i--);return n}function Fn(e){if(e.measure&&(e.measure.cache={},e.measure.heights=null,e.rest))for(var t=0;t=r.text.length?(s=r.text.length,c="before"):s<=0&&(s=0,c="after"),!l)return a("before"==c?s-1:s,"before"==c);function u(e,t,n){var r=l[t],i=1==r.level;return a(n?e-1:e,i!=n)}var f=Xe(l,s,c),d=Ge,h=u(s,f,"before"==c);return null!=d&&(h.other=u(s,d,"before"!=c)),h}function $n(e,t){var n=0;t=ke(e.doc,t),e.options.lineWrapping||(n=tr(e.display)*t.ch);var r=le(e.doc,t.line),i=Ve(r)+kn(e.display);return{left:n,right:n,top:i,bottom:i+r.height}}function Gn(e,t,n,r,i){var o=me(e,t,n);return o.xRel=i,r&&(o.outside=!0),o}function Xn(e,t,n){var r=e.doc;if((n+=e.display.viewOffset)<0)return Gn(r.first,0,null,!0,-1);var i=de(r,n),o=r.first+r.size-1;if(i>o)return Gn(r.first+r.size-1,le(r,o).text.length,null,!0,1);t<0&&(t=0);for(var a=le(r,i);;){var l=Zn(e,a,i,t,n),s=We(a),c=s&&s.find(0,!0);if(!s||!(l.ch>c.from.ch||l.ch==c.from.ch&&l.xRel>0))return l;i=fe(a=c.to.line)}}function Yn(e,t,n,r){r-=Kn(t);var i=t.text.length,o=ae(function(t){return Nn(e,n,t-1).bottom<=r},i,0);return i=ae(function(t){return Nn(e,n,t).top>r},o,i),{begin:o,end:i}}function Jn(e,t,n,r){n||(n=Pn(e,t));var i=jn(e,t,Nn(e,n,r),"line").top;return Yn(e,t,n,i)}function Qn(e,t,n,r){return!(e.bottom<=n)&&(e.top>n||(r?e.left:e.right)>t)}function Zn(e,t,n,r,i){i-=Ve(t);var o=Pn(e,t),a=Kn(t),l=0,s=t.text.length,c=!0,u=Je(t,e.doc.direction);if(u){var f=(e.options.lineWrapping?function(e,t,n,r,i,o,a){var l=Yn(e,t,r,a),s=l.begin,c=l.end;/\s/.test(t.text.charAt(c-1))&&c--;for(var u=null,f=null,d=0;d=c||h.to<=s)){var p=1!=h.level,m=Nn(e,r,p?Math.min(c,h.to)-1:Math.max(s,h.from)).right,g=mg)&&(u=h,f=g)}}return u||(u=i[i.length-1]),u.fromc&&(u={from:u.from,to:c,level:u.level}),u}:function(e,t,n,r,i,o,a){var l=ae(function(l){var s=i[l],c=1!=s.level;return Qn(qn(e,me(n,c?s.to:s.from,c?"before":"after"),"line",t,r),o,a,!0)},0,i.length-1),s=i[l];if(l>0){var c=1!=s.level,u=qn(e,me(n,c?s.from:s.to,c?"after":"before"),"line",t,r);Qn(u,o,a,!0)&&u.top>a&&(s=i[l-1])}return s})(e,t,n,o,u,r,i);c=1!=f.level,l=c?f.from:f.to-1,s=c?f.to:f.from-1}var d,h,p=null,m=null,g=ae(function(t){var n=Nn(e,o,t);return n.top+=a,n.bottom+=a,!!Qn(n,r,i,!1)&&(n.top<=i&&n.left<=r&&(p=t,m=n),!0)},l,s),v=!1;if(m){var y=r-m.left=w.bottom}return g=oe(t.text,g,1),Gn(n,g,h,v,r-d)}function er(e){if(null!=e.cachedTextHeight)return e.cachedTextHeight;if(null==In){In=O("pre");for(var t=0;t<49;++t)In.appendChild(document.createTextNode("x")),In.appendChild(O("br"));In.appendChild(document.createTextNode("x"))}A(e.measure,In);var n=In.offsetHeight/50;return n>3&&(e.cachedTextHeight=n),T(e.measure),n||1}function tr(e){if(null!=e.cachedCharWidth)return e.cachedCharWidth;var t=O("span","xxxxxxxxxx"),n=O("pre",[t]);A(e.measure,n);var r=t.getBoundingClientRect(),i=(r.right-r.left)/10;return i>2&&(e.cachedCharWidth=i),i||10}function nr(e){for(var t=e.display,n={},r={},i=t.gutters.clientLeft,o=t.gutters.firstChild,a=0;o;o=o.nextSibling,++a)n[e.options.gutters[a]]=o.offsetLeft+o.clientLeft+i,r[e.options.gutters[a]]=o.clientWidth;return{fixedPos:rr(t),gutterTotalWidth:t.gutters.offsetWidth,gutterLeft:n,gutterWidth:r,wrapperWidth:t.wrapper.clientWidth}}function rr(e){return e.scroller.getBoundingClientRect().left-e.sizer.getBoundingClientRect().left}function ir(e){var t=er(e.display),n=e.options.lineWrapping,r=n&&Math.max(5,e.display.scroller.clientWidth/tr(e.display)-3);return function(i){if(je(e.doc,i))return 0;var o=0;if(i.widgets)for(var a=0;a=e.display.viewTo)return null;if((t-=e.display.viewFrom)<0)return null;for(var n=e.display.view,r=0;r=e.display.viewTo||l.to().linet||t==n&&a.to==t)&&(r(Math.max(a.from,t),Math.min(a.to,n),1==a.level?"rtl":"ltr",o),i=!0)}i||r(t,n,"ltr")}(m,n||0,null==r?d:r,function(e,t,i,f){var g="ltr"==i,v=h(e,g?"left":"right"),y=h(t-1,g?"right":"left"),b=null==n&&0==e,w=null==r&&t==d,x=0==f,k=!m||f==m.length-1;if(y.top-v.top<=3){var C=(c?b:w)&&x,S=(c?w:b)&&k,L=C?l:(g?v:y).left,M=S?s:(g?y:v).right;u(L,v.top,M-L,v.bottom)}else{var T,A,O,E;g?(T=c&&b&&x?l:v.left,A=c?s:p(e,i,"before"),O=c?l:p(t,i,"after"),E=c&&w&&k?s:y.right):(T=c?p(e,i,"before"):l,A=!c&&b&&x?s:v.right,O=!c&&w&&k?l:y.left,E=c?p(t,i,"after"):s),u(T,v.top,A-T,v.bottom),v.bottom0?t.blinker=setInterval(function(){return t.cursorDiv.style.visibility=(n=!n)?"":"hidden"},e.options.cursorBlinkRate):e.options.cursorBlinkRate<0&&(t.cursorDiv.style.visibility="hidden")}}function pr(e){e.state.focused||(e.display.input.focus(),gr(e))}function mr(e){e.state.delayingBlurEvent=!0,setTimeout(function(){e.state.delayingBlurEvent&&(e.state.delayingBlurEvent=!1,vr(e))},100)}function gr(e,t){e.state.delayingBlurEvent&&(e.state.delayingBlurEvent=!1),"nocursor"!=e.options.readOnly&&(e.state.focused||(nt(e,"focus",e,t),e.state.focused=!0,I(e.display.wrapper,"CodeMirror-focused"),e.curOp||e.display.selForContextMenu==e.doc.sel||(e.display.input.reset(),s&&setTimeout(function(){return e.display.input.reset(!0)},20)),e.display.input.receivedFocus()),hr(e))}function vr(e,t){e.state.delayingBlurEvent||(e.state.focused&&(nt(e,"blur",e,t),e.state.focused=!1,M(e.display.wrapper,"CodeMirror-focused")),clearInterval(e.display.blinker),setTimeout(function(){e.state.focused||(e.display.shift=!1)},150))}function yr(e){for(var t=e.display,n=t.lineDiv.offsetTop,r=0;r.005||u<-.005)&&(ue(i.line,o),br(i.line),i.rest))for(var f=0;f=a&&(o=de(t,Ve(le(t,s))-e.wrapper.clientHeight),a=s)}return{from:o,to:Math.max(a,o+1)}}function xr(e){var t=e.display,n=t.view;if(t.alignWidgets||t.gutters.firstChild&&e.options.fixedGutter){for(var r=rr(t)-t.scroller.scrollLeft+e.doc.scrollLeft,i=t.gutters.offsetWidth,o=r+"px",a=0;ao&&(t.bottom=t.top+o);var l=e.doc.height+Cn(n),s=t.topl-r;if(t.topi+o){var u=Math.min(t.top,(c?l:t.bottom)-o);u!=i&&(a.scrollTop=u)}var f=e.curOp&&null!=e.curOp.scrollLeft?e.curOp.scrollLeft:n.scroller.scrollLeft,d=Mn(e)-(e.options.fixedGutter?n.gutters.offsetWidth:0),h=t.right-t.left>d;return h&&(t.right=t.left+d),t.left<10?a.scrollLeft=0:t.leftd+f-3&&(a.scrollLeft=t.right+(h?0:10)-d),a}function Sr(e,t){null!=t&&(Tr(e),e.curOp.scrollTop=(null==e.curOp.scrollTop?e.doc.scrollTop:e.curOp.scrollTop)+t)}function Lr(e){Tr(e);var t=e.getCursor();e.curOp.scrollToPos={from:t,to:t,margin:e.options.cursorScrollMargin}}function Mr(e,t,n){null==t&&null==n||Tr(e),null!=t&&(e.curOp.scrollLeft=t),null!=n&&(e.curOp.scrollTop=n)}function Tr(e){var t=e.curOp.scrollToPos;if(t){e.curOp.scrollToPos=null;var n=$n(e,t.from),r=$n(e,t.to);Ar(e,n,r,t.margin)}}function Ar(e,t,n,r){var i=Cr(e,{left:Math.min(t.left,n.left),top:Math.min(t.top,n.top)-r,right:Math.max(t.right,n.right),bottom:Math.max(t.bottom,n.bottom)+r});Mr(e,i.scrollLeft,i.scrollTop)}function Or(e,t){Math.abs(e.doc.scrollTop-t)<2||(n||ai(e,{top:t}),Er(e,t,!0),n&&ai(e),ti(e,100))}function Er(e,t,n){t=Math.min(e.display.scroller.scrollHeight-e.display.scroller.clientHeight,t),(e.display.scroller.scrollTop!=t||n)&&(e.doc.scrollTop=t,e.display.scrollbars.setScrollTop(t),e.display.scroller.scrollTop!=t&&(e.display.scroller.scrollTop=t))}function Pr(e,t,n,r){t=Math.min(t,e.display.scroller.scrollWidth-e.display.scroller.clientWidth),(n?t==e.doc.scrollLeft:Math.abs(e.doc.scrollLeft-t)<2)&&!r||(e.doc.scrollLeft=t,xr(e),e.display.scroller.scrollLeft!=t&&(e.display.scroller.scrollLeft=t),e.display.scrollbars.setScrollLeft(t))}function Nr(e){var t=e.display,n=t.gutters.offsetWidth,r=Math.round(e.doc.height+Cn(e.display));return{clientHeight:t.scroller.clientHeight,viewHeight:t.wrapper.clientHeight,scrollWidth:t.scroller.scrollWidth,clientWidth:t.scroller.clientWidth,viewWidth:t.wrapper.clientWidth,barLeft:e.options.fixedGutter?n:0,docHeight:r,scrollHeight:r+Ln(e)+t.barHeight,nativeBarWidth:t.nativeBarWidth,gutterWidth:n}}var Ir=function(e,t,n){this.cm=n;var r=this.vert=O("div",[O("div",null,null,"min-width: 1px")],"CodeMirror-vscrollbar"),i=this.horiz=O("div",[O("div",null,null,"height: 100%; min-height: 1px")],"CodeMirror-hscrollbar");e(r),e(i),Ze(r,"scroll",function(){r.clientHeight&&t(r.scrollTop,"vertical")}),Ze(i,"scroll",function(){i.clientWidth&&t(i.scrollLeft,"horizontal")}),this.checkedZeroWidth=!1,a&&l<8&&(this.horiz.style.minHeight=this.vert.style.minWidth="18px")};Ir.prototype.update=function(e){var t=e.scrollWidth>e.clientWidth+1,n=e.scrollHeight>e.clientHeight+1,r=e.nativeBarWidth;if(n){this.vert.style.display="block",this.vert.style.bottom=t?r+"px":"0";var i=e.viewHeight-(t?r:0);this.vert.firstChild.style.height=Math.max(0,e.scrollHeight-e.clientHeight+i)+"px"}else this.vert.style.display="",this.vert.firstChild.style.height="0";if(t){this.horiz.style.display="block",this.horiz.style.right=n?r+"px":"0",this.horiz.style.left=e.barLeft+"px";var o=e.viewWidth-e.barLeft-(n?r:0);this.horiz.firstChild.style.width=Math.max(0,e.scrollWidth-e.clientWidth+o)+"px"}else this.horiz.style.display="",this.horiz.firstChild.style.width="0";return!this.checkedZeroWidth&&e.clientHeight>0&&(0==r&&this.zeroWidthHack(),this.checkedZeroWidth=!0),{right:n?r:0,bottom:t?r:0}},Ir.prototype.setScrollLeft=function(e){this.horiz.scrollLeft!=e&&(this.horiz.scrollLeft=e),this.disableHoriz&&this.enableZeroWidthBar(this.horiz,this.disableHoriz,"horiz")},Ir.prototype.setScrollTop=function(e){this.vert.scrollTop!=e&&(this.vert.scrollTop=e),this.disableVert&&this.enableZeroWidthBar(this.vert,this.disableVert,"vert")},Ir.prototype.zeroWidthHack=function(){var e=y&&!h?"12px":"18px";this.horiz.style.height=this.vert.style.width=e,this.horiz.style.pointerEvents=this.vert.style.pointerEvents="none",this.disableHoriz=new z,this.disableVert=new z},Ir.prototype.enableZeroWidthBar=function(e,t,n){e.style.pointerEvents="auto",t.set(1e3,function r(){var i=e.getBoundingClientRect(),o="vert"==n?document.elementFromPoint(i.right-1,(i.top+i.bottom)/2):document.elementFromPoint((i.right+i.left)/2,i.bottom-1);o!=e?e.style.pointerEvents="none":t.set(1e3,r)})},Ir.prototype.clear=function(){var e=this.horiz.parentNode;e.removeChild(this.horiz),e.removeChild(this.vert)};var Rr=function(){};function Br(e,t){t||(t=Nr(e));var n=e.display.barWidth,r=e.display.barHeight;Dr(e,t);for(var i=0;i<4&&n!=e.display.barWidth||r!=e.display.barHeight;i++)n!=e.display.barWidth&&e.options.lineWrapping&&yr(e),Dr(e,Nr(e)),n=e.display.barWidth,r=e.display.barHeight}function Dr(e,t){var n=e.display,r=n.scrollbars.update(t);n.sizer.style.paddingRight=(n.barWidth=r.right)+"px",n.sizer.style.paddingBottom=(n.barHeight=r.bottom)+"px",n.heightForcer.style.borderBottom=r.bottom+"px solid transparent",r.right&&r.bottom?(n.scrollbarFiller.style.display="block",n.scrollbarFiller.style.height=r.bottom+"px",n.scrollbarFiller.style.width=r.right+"px"):n.scrollbarFiller.style.display="",r.bottom&&e.options.coverGutterNextToScrollbar&&e.options.fixedGutter?(n.gutterFiller.style.display="block",n.gutterFiller.style.height=r.bottom+"px",n.gutterFiller.style.width=t.gutterWidth+"px"):n.gutterFiller.style.display=""}Rr.prototype.update=function(){return{bottom:0,right:0}},Rr.prototype.setScrollLeft=function(){},Rr.prototype.setScrollTop=function(){},Rr.prototype.clear=function(){};var Fr={native:Ir,null:Rr};function Wr(e){e.display.scrollbars&&(e.display.scrollbars.clear(),e.display.scrollbars.addClass&&M(e.display.wrapper,e.display.scrollbars.addClass)),e.display.scrollbars=new Fr[e.options.scrollbarStyle](function(t){e.display.wrapper.insertBefore(t,e.display.scrollbarFiller),Ze(t,"mousedown",function(){e.state.focused&&setTimeout(function(){return e.display.input.focus()},0)}),t.setAttribute("cm-not-content","true")},function(t,n){"horizontal"==n?Pr(e,t):Or(e,t)},e),e.display.scrollbars.addClass&&I(e.display.wrapper,e.display.scrollbars.addClass)}var zr=0;function _r(e){var t;e.curOp={cm:e,viewChanged:!1,startHeight:e.doc.height,forceUpdate:!1,updateInput:null,typing:!1,changeObjs:null,cursorActivityHandlers:null,cursorActivityCalled:0,selectionChanged:!1,updateMaxLine:!1,scrollLeft:null,scrollTop:null,scrollToPos:null,focus:!1,id:++zr},t=e.curOp,on?on.ops.push(t):t.ownsGroup=on={ops:[t],delayedCallbacks:[]}}function Hr(e){var t=e.curOp;!function(e,t){var n=e.ownsGroup;if(n)try{!function(e){var t=e.delayedCallbacks,n=0;do{for(;n=n.viewTo)||n.maxLineChanged&&t.options.lineWrapping,e.update=e.mustUpdate&&new ri(t,e.mustUpdate&&{top:e.scrollTop,ensure:e.scrollToPos},e.forceUpdate)}function jr(e){var t=e.cm,n=t.display;e.updatedDisplay&&yr(t),e.barMeasure=Nr(t),n.maxLineChanged&&!t.options.lineWrapping&&(e.adjustWidthTo=On(t,n.maxLine,n.maxLine.text.length).left+3,t.display.sizerWidth=e.adjustWidthTo,e.barMeasure.scrollWidth=Math.max(n.scroller.clientWidth,n.sizer.offsetLeft+e.adjustWidthTo+Ln(t)+t.display.barWidth),e.maxScrollLeft=Math.max(0,n.sizer.offsetLeft+e.adjustWidthTo-Mn(t))),(e.updatedDisplay||e.selectionChanged)&&(e.preparedSelection=n.input.prepareSelection())}function Ur(e){var t=e.cm;null!=e.adjustWidthTo&&(t.display.sizer.style.minWidth=e.adjustWidthTo+"px",e.maxScrollLeft1&&(a=!0)),null!=c.scrollLeft&&(Pr(e,c.scrollLeft),Math.abs(e.doc.scrollLeft-f)>1&&(a=!0)),!a)break}return i}(t,ke(r,e.scrollToPos.from),ke(r,e.scrollToPos.to),e.scrollToPos.margin);!function(e,t){if(!rt(e,"scrollCursorIntoView")){var n=e.display,r=n.sizer.getBoundingClientRect(),i=null;if(t.top+r.top<0?i=!0:t.bottom+r.top>(window.innerHeight||document.documentElement.clientHeight)&&(i=!1),null!=i&&!p){var o=O("div","​",null,"position: absolute;\n top: "+(t.top-n.viewOffset-kn(e.display))+"px;\n height: "+(t.bottom-t.top+Ln(e)+n.barHeight)+"px;\n left: "+t.left+"px; width: "+Math.max(2,t.right-t.left)+"px;");e.display.lineSpace.appendChild(o),o.scrollIntoView(i),e.display.lineSpace.removeChild(o)}}}(t,i)}var o=e.maybeHiddenMarkers,a=e.maybeUnhiddenMarkers;if(o)for(var l=0;lt)&&(i.updateLineNumbers=t),e.curOp.viewChanged=!0,t>=i.viewTo)Le&&He(e.doc,t)i.viewFrom?Qr(e):(i.viewFrom+=r,i.viewTo+=r);else if(t<=i.viewFrom&&n>=i.viewTo)Qr(e);else if(t<=i.viewFrom){var o=Zr(e,n,n+r,1);o?(i.view=i.view.slice(o.index),i.viewFrom=o.lineN,i.viewTo+=r):Qr(e)}else if(n>=i.viewTo){var a=Zr(e,t,t,-1);a?(i.view=i.view.slice(0,a.index),i.viewTo=a.lineN):Qr(e)}else{var l=Zr(e,t,t,-1),s=Zr(e,n,n+r,1);l&&s?(i.view=i.view.slice(0,l.index).concat(rn(e,l.lineN,s.lineN)).concat(i.view.slice(s.index)),i.viewTo+=r):Qr(e)}var c=i.externalMeasured;c&&(n=i.lineN&&t=r.viewTo)){var o=r.view[lr(e,t)];if(null!=o.node){var a=o.changes||(o.changes=[]);-1==_(a,n)&&a.push(n)}}}function Qr(e){e.display.viewFrom=e.display.viewTo=e.doc.first,e.display.view=[],e.display.viewOffset=0}function Zr(e,t,n,r){var i,o=lr(e,t),a=e.display.view;if(!Le||n==e.doc.first+e.doc.size)return{index:o,lineN:n};for(var l=e.display.viewFrom,s=0;s0){if(o==a.length-1)return null;i=l+a[o].size-t,o++}else i=l-t;t+=i,n+=i}for(;He(e.doc,n)!=n;){if(o==(r<0?0:a.length-1))return null;n+=r*a[o-(r<0?1:0)].size,o+=r}return{index:o,lineN:n}}function ei(e){for(var t=e.display.view,n=0,r=0;r=e.display.viewTo)){var n=+new Date+e.options.workTime,r=Ft(e,t.highlightFrontier),i=[];t.iter(r.line,Math.min(t.first+t.size,e.display.viewTo+500),function(o){if(r.line>=e.display.viewFrom){var a=o.styles,l=o.text.length>e.options.maxHighlightLength?Ot(t.mode,r.state):null,s=Bt(e,o,r,!0);l&&(r.state=l),o.styles=s.styles;var c=o.styleClasses,u=s.classes;u?o.styleClasses=u:c&&(o.styleClasses=null);for(var f=!a||a.length!=o.styles.length||c!=u&&(!c||!u||c.bgClass!=u.bgClass||c.textClass!=u.textClass),d=0;!f&&dn)return ti(e,e.options.workDelay),!0}),t.highlightFrontier=r.line,t.modeFrontier=Math.max(t.modeFrontier,r.line),i.length&&qr(e,function(){for(var t=0;t=n.viewFrom&&t.visible.to<=n.viewTo&&(null==n.updateLineNumbers||n.updateLineNumbers>=n.viewTo)&&n.renderedView==n.view&&0==ei(e))return!1;kr(e)&&(Qr(e),t.dims=nr(e));var i=r.first+r.size,o=Math.max(t.visible.from-e.options.viewportMargin,r.first),a=Math.min(i,t.visible.to+e.options.viewportMargin);n.viewFroma&&n.viewTo-a<20&&(a=Math.min(i,n.viewTo)),Le&&(o=He(e.doc,o),a=Ke(e.doc,a));var l=o!=n.viewFrom||a!=n.viewTo||n.lastWrapHeight!=t.wrapperHeight||n.lastWrapWidth!=t.wrapperWidth;!function(e,t,n){var r=e.display;0==r.view.length||t>=r.viewTo||n<=r.viewFrom?(r.view=rn(e,t,n),r.viewFrom=t):(r.viewFrom>t?r.view=rn(e,t,r.viewFrom).concat(r.view):r.viewFromn&&(r.view=r.view.slice(0,lr(e,n)))),r.viewTo=n}(e,o,a),n.viewOffset=Ve(le(e.doc,n.viewFrom)),e.display.mover.style.top=n.viewOffset+"px";var c=ei(e);if(!l&&0==c&&!t.force&&n.renderedView==n.view&&(null==n.updateLineNumbers||n.updateLineNumbers>=n.viewTo))return!1;var u=function(e){if(e.hasFocus())return null;var t=N();if(!t||!P(e.display.lineDiv,t))return null;var n={activeElt:t};if(window.getSelection){var r=window.getSelection();r.anchorNode&&r.extend&&P(e.display.lineDiv,r.anchorNode)&&(n.anchorNode=r.anchorNode,n.anchorOffset=r.anchorOffset,n.focusNode=r.focusNode,n.focusOffset=r.focusOffset)}return n}(e);return c>4&&(n.lineDiv.style.display="none"),function(e,t,n){var r=e.display,i=e.options.lineNumbers,o=r.lineDiv,a=o.firstChild;function l(t){var n=t.nextSibling;return s&&y&&e.display.currentWheelTarget==t?t.style.display="none":t.parentNode.removeChild(t),n}for(var c=r.view,u=r.viewFrom,f=0;f-1&&(h=!1),cn(e,d,u,n)),h&&(T(d.lineNumber),d.lineNumber.appendChild(document.createTextNode(pe(e.options,u)))),a=d.node.nextSibling}else{var p=gn(e,d,u,n);o.insertBefore(p,a)}u+=d.size}for(;a;)a=l(a)}(e,n.updateLineNumbers,t.dims),c>4&&(n.lineDiv.style.display=""),n.renderedView=n.view,function(e){if(e&&e.activeElt&&e.activeElt!=N()&&(e.activeElt.focus(),e.anchorNode&&P(document.body,e.anchorNode)&&P(document.body,e.focusNode))){var t=window.getSelection(),n=document.createRange();n.setEnd(e.anchorNode,e.anchorOffset),n.collapse(!1),t.removeAllRanges(),t.addRange(n),t.extend(e.focusNode,e.focusOffset)}}(u),T(n.cursorDiv),T(n.selectionDiv),n.gutters.style.height=n.sizer.style.minHeight=0,l&&(n.lastWrapHeight=t.wrapperHeight,n.lastWrapWidth=t.wrapperWidth,ti(e,400)),n.updateLineNumbers=null,!0}function oi(e,t){for(var n=t.viewport,r=!0;(r&&e.options.lineWrapping&&t.oldDisplayWidth!=Mn(e)||(n&&null!=n.top&&(n={top:Math.min(e.doc.height+Cn(e.display)-Tn(e),n.top)}),t.visible=wr(e.display,e.doc,n),!(t.visible.from>=e.display.viewFrom&&t.visible.to<=e.display.viewTo)))&&ii(e,t);r=!1){yr(e);var i=Nr(e);sr(e),Br(e,i),si(e,i),t.force=!1}t.signal(e,"update",e),e.display.viewFrom==e.display.reportedViewFrom&&e.display.viewTo==e.display.reportedViewTo||(t.signal(e,"viewportChange",e,e.display.viewFrom,e.display.viewTo),e.display.reportedViewFrom=e.display.viewFrom,e.display.reportedViewTo=e.display.viewTo)}function ai(e,t){var n=new ri(e,t);if(ii(e,n)){yr(e),oi(e,n);var r=Nr(e);sr(e),Br(e,r),si(e,r),n.finish()}}function li(e){var t=e.display.gutters.offsetWidth;e.display.sizer.style.marginLeft=t+"px"}function si(e,t){e.display.sizer.style.minHeight=t.docHeight+"px",e.display.heightForcer.style.top=t.docHeight+"px",e.display.gutters.style.height=t.docHeight+e.display.barHeight+Ln(e)+"px"}function ci(e){var t=e.display.gutters,n=e.options.gutters;T(t);for(var r=0;r-1&&!e.lineNumbers&&(e.gutters=e.gutters.slice(0),e.gutters.splice(t,1))}ri.prototype.signal=function(e,t){ot(e,t)&&this.events.push(arguments)},ri.prototype.finish=function(){for(var e=0;el.clientWidth,u=l.scrollHeight>l.clientHeight;if(i&&c||o&&u){if(o&&y&&s)e:for(var d=t.target,h=a.view;d!=l;d=d.parentNode)for(var p=0;p=0&&ge(e,r.to())<=0)return n}return-1};var vi=function(e,t){this.anchor=e,this.head=t};function yi(e,t){var n=e[t];e.sort(function(e,t){return ge(e.from(),t.from())}),t=_(e,n);for(var r=1;r=0){var a=we(o.from(),i.from()),l=be(o.to(),i.to()),s=o.empty()?i.from()==i.head:o.from()==o.head;r<=t&&--t,e.splice(--r,2,new vi(s?l:a,s?a:l))}}return new gi(e,t)}function bi(e,t){return new gi([new vi(e,t||e)],0)}function wi(e){return e.text?me(e.from.line+e.text.length-1,X(e.text).length+(1==e.text.length?e.from.ch:0)):e.to}function xi(e,t){if(ge(e,t.from)<0)return e;if(ge(e,t.to)<=0)return wi(t);var n=e.line+t.text.length-(t.to.line-t.from.line)-1,r=e.ch;return e.line==t.to.line&&(r+=wi(t).ch-t.to.ch),me(n,r)}function ki(e,t){for(var n=[],r=0;r1&&e.remove(l.line+1,p-1),e.insert(l.line+1,v)}ln(e,"change",e,t)}function Ai(e,t,n){!function e(r,i,o){if(r.linked)for(var a=0;al-(e.cm?e.cm.options.historyEventDelay:500)||"*"==t.origin.charAt(0)))&&(o=function(e,t){return t?(Ii(e.done),X(e.done)):e.done.length&&!X(e.done).ranges?X(e.done):e.done.length>1&&!e.done[e.done.length-2].ranges?(e.done.pop(),X(e.done)):void 0}(i,i.lastOp==r)))a=X(o.changes),0==ge(t.from,t.to)&&0==ge(t.from,a.to)?a.to=wi(t):o.changes.push(Ni(e,t));else{var s=X(i.done);for(s&&s.ranges||Di(e.sel,i.done),o={changes:[Ni(e,t)],generation:i.generation},i.done.push(o);i.done.length>i.undoDepth;)i.done.shift(),i.done[0].ranges||i.done.shift()}i.done.push(n),i.generation=++i.maxGeneration,i.lastModTime=i.lastSelTime=l,i.lastOp=i.lastSelOp=r,i.lastOrigin=i.lastSelOrigin=t.origin,a||nt(e,"historyAdded")}function Bi(e,t,n,r){var i=e.history,o=r&&r.origin;n==i.lastSelOp||o&&i.lastSelOrigin==o&&(i.lastModTime==i.lastSelTime&&i.lastOrigin==o||function(e,t,n,r){var i=t.charAt(0);return"*"==i||"+"==i&&n.ranges.length==r.ranges.length&&n.somethingSelected()==r.somethingSelected()&&new Date-e.history.lastSelTime<=(e.cm?e.cm.options.historyEventDelay:500)}(e,o,X(i.done),t))?i.done[i.done.length-1]=t:Di(t,i.done),i.lastSelTime=+new Date,i.lastSelOrigin=o,i.lastSelOp=n,r&&!1!==r.clearRedo&&Ii(i.undone)}function Di(e,t){var n=X(t);n&&n.ranges&&n.equals(e)||t.push(e)}function Fi(e,t,n,r){var i=t["spans_"+e.id],o=0;e.iter(Math.max(e.first,n),Math.min(e.first+e.size,r),function(n){n.markedSpans&&((i||(i=t["spans_"+e.id]={}))[o]=n.markedSpans),++o})}function Wi(e){if(!e)return null;for(var t,n=0;n-1&&(X(l)[f]=c[f],delete c[f])}}}return r}function Hi(e,t,n,r){if(r){var i=e.anchor;if(n){var o=ge(t,i)<0;o!=ge(n,i)<0?(i=t,t=n):o!=ge(t,n)<0&&(t=n)}return new vi(i,t)}return new vi(n||t,t)}function Ki(e,t,n,r,i){null==i&&(i=e.cm&&(e.cm.display.shift||e.extend)),$i(e,new gi([Hi(e.sel.primary(),t,n,i)],0),r)}function ji(e,t,n){for(var r=[],i=e.cm&&(e.cm.display.shift||e.extend),o=0;o=t.ch:l.to>t.ch))){if(i&&(nt(s,"beforeCursorEnter"),s.explicitlyCleared)){if(o.markedSpans){--a;continue}break}if(!s.atomic)continue;if(n){var c=s.find(r<0?1:-1),u=void 0;if((r<0?s.inclusiveRight:s.inclusiveLeft)&&(c=eo(e,c,-r,c&&c.line==t.line?o:null)),c&&c.line==t.line&&(u=ge(c,n))&&(r<0?u<0:u>0))return Qi(e,c,t,r,i)}var f=s.find(r<0?-1:1);return(r<0?s.inclusiveLeft:s.inclusiveRight)&&(f=eo(e,f,r,f.line==t.line?o:null)),f?Qi(e,f,t,r,i):null}}return t}function Zi(e,t,n,r,i){var o=r||1,a=Qi(e,t,n,o,i)||!i&&Qi(e,t,n,o,!0)||Qi(e,t,n,-o,i)||!i&&Qi(e,t,n,-o,!0);return a||(e.cantEdit=!0,me(e.first,0))}function eo(e,t,n,r){return n<0&&0==t.ch?t.line>e.first?ke(e,me(t.line-1)):null:n>0&&t.ch==(r||le(e,t.line)).text.length?t.line0)){var u=[s,1],f=ge(c.from,l.from),d=ge(c.to,l.to);(f<0||!a.inclusiveLeft&&!f)&&u.push({from:c.from,to:l.from}),(d>0||!a.inclusiveRight&&!d)&&u.push({from:l.to,to:c.to}),i.splice.apply(i,u),s+=u.length-3}}return i}(e,t.from,t.to);if(r)for(var i=r.length-1;i>=0;--i)io(e,{from:r[i].from,to:r[i].to,text:i?[""]:t.text,origin:t.origin});else io(e,t)}}function io(e,t){if(1!=t.text.length||""!=t.text[0]||0!=ge(t.from,t.to)){var n=ki(e,t);Ri(e,t,n,e.cm?e.cm.curOp.id:NaN),lo(e,t,n,Oe(e,t));var r=[];Ai(e,function(e,n){n||-1!=_(r,e.history)||(fo(e.history,t),r.push(e.history)),lo(e,t,null,Oe(e,t))})}}function oo(e,t,n){var r=e.cm&&e.cm.state.suppressEdits;if(!r||n){for(var i,o=e.history,a=e.sel,l="undo"==t?o.done:o.undone,s="undo"==t?o.undone:o.done,c=0;c=0;--h){var p=d(h);if(p)return p.v}}}}function ao(e,t){if(0!=t&&(e.first+=t,e.sel=new gi(Y(e.sel.ranges,function(e){return new vi(me(e.anchor.line+t,e.anchor.ch),me(e.head.line+t,e.head.ch))}),e.sel.primIndex),e.cm)){Yr(e.cm,e.first,e.first-t,t);for(var n=e.cm.display,r=n.viewFrom;re.lastLine())){if(t.from.lineo&&(t={from:t.from,to:me(o,le(e,o).text.length),text:[t.text[0]],origin:t.origin}),t.removed=se(e,t.from,t.to),n||(n=ki(e,t)),e.cm?function(e,t,n){var r=e.doc,i=e.display,o=t.from,a=t.to,l=!1,s=o.line;e.options.lineWrapping||(s=fe(_e(le(r,o.line))),r.iter(s,a.line+1,function(e){if(e==i.maxLine)return l=!0,!0})),r.sel.contains(t.from,t.to)>-1&&it(e),Ti(r,t,n,ir(e)),e.options.lineWrapping||(r.iter(s,o.line+t.text.length,function(e){var t=qe(e);t>i.maxLineLength&&(i.maxLine=e,i.maxLineLength=t,i.maxLineChanged=!0,l=!1)}),l&&(e.curOp.updateMaxLine=!0)),function(e,t){if(e.modeFrontier=Math.min(e.modeFrontier,t),!(e.highlightFrontiern;r--){var i=le(e,r).stateAfter;if(i&&(!(i instanceof It)||r+i.lookAhead1||!(this.children[0]instanceof po))){var l=[];this.collapse(l),this.children=[new po(l)],this.children[0].parent=this}},collapse:function(e){for(var t=0;t50){for(var a=i.lines.length%25+25,l=a;l10);e.parent.maybeSpill()}},iterN:function(e,t,n){for(var r=0;r0||0==a&&!1!==o.clearWhenEmpty)return o;if(o.replacedWith&&(o.collapsed=!0,o.widgetNode=E("span",[o.replacedWith],"CodeMirror-widget"),r.handleMouseEvents||o.widgetNode.setAttribute("cm-ignore-events","true"),r.insertLeft&&(o.widgetNode.insertLeft=!0)),o.collapsed){if(ze(e,t.line,t,n,o)||t.line!=n.line&&ze(e,n.line,t,n,o))throw new Error("Inserting collapsed marker partially overlapping an existing one");Le=!0}o.addToHistory&&Ri(e,{from:t,to:n,origin:"markText"},e.sel,NaN);var l,s=t.line,c=e.cm;if(e.iter(s,n.line+1,function(e){c&&o.collapsed&&!c.options.lineWrapping&&_e(e)==c.display.maxLine&&(l=!0),o.collapsed&&s!=t.line&&ue(e,0),function(e,t){e.markedSpans=e.markedSpans?e.markedSpans.concat([t]):[t],t.marker.attachLine(e)}(e,new Me(o,s==t.line?t.ch:null,s==n.line?n.ch:null)),++s}),o.collapsed&&e.iter(t.line,n.line+1,function(t){je(e,t)&&ue(t,0)}),o.clearOnEnter&&Ze(o,"beforeCursorEnter",function(){return o.clear()}),o.readOnly&&(Se=!0,(e.history.done.length||e.history.undone.length)&&e.clearHistory()),o.collapsed&&(o.id=++yo,o.atomic=!0),c){if(l&&(c.curOp.updateMaxLine=!0),o.collapsed)Yr(c,t.line,n.line+1);else if(o.className||o.title||o.startStyle||o.endStyle||o.css)for(var u=t.line;u<=n.line;u++)Jr(c,u,"text");o.atomic&&Yi(c.doc),ln(c,"markerAdded",c,o)}return o}bo.prototype.clear=function(){if(!this.explicitlyCleared){var e=this.doc.cm,t=e&&!e.curOp;if(t&&_r(e),ot(this,"clear")){var n=this.find();n&&ln(this,"clear",n.from,n.to)}for(var r=null,i=null,o=0;oe.display.maxLineLength&&(e.display.maxLine=c,e.display.maxLineLength=u,e.display.maxLineChanged=!0)}null!=r&&e&&this.collapsed&&Yr(e,r,i+1),this.lines.length=0,this.explicitlyCleared=!0,this.atomic&&this.doc.cantEdit&&(this.doc.cantEdit=!1,e&&Yi(e.doc)),e&&ln(e,"markerCleared",e,this,r,i),t&&Hr(e),this.parent&&this.parent.clear()}},bo.prototype.find=function(e,t){var n,r;null==e&&"bookmark"==this.type&&(e=1);for(var i=0;i=0;s--)ro(this,r[s]);l?qi(this,l):this.cm&&Lr(this.cm)}),undo:Xr(function(){oo(this,"undo")}),redo:Xr(function(){oo(this,"redo")}),undoSelection:Xr(function(){oo(this,"undo",!0)}),redoSelection:Xr(function(){oo(this,"redo",!0)}),setExtending:function(e){this.extend=e},getExtending:function(){return this.extend},historySize:function(){for(var e=this.history,t=0,n=0,r=0;r=e.ch)&&t.push(i.marker.parent||i.marker)}return t},findMarks:function(e,t,n){e=ke(this,e),t=ke(this,t);var r=[],i=e.line;return this.iter(e.line,t.line+1,function(o){var a=o.markedSpans;if(a)for(var l=0;l=s.to||null==s.from&&i!=e.line||null!=s.from&&i==t.line&&s.from>=t.ch||n&&!n(s.marker)||r.push(s.marker.parent||s.marker)}++i}),r},getAllMarks:function(){var e=[];return this.iter(function(t){var n=t.markedSpans;if(n)for(var r=0;re)return t=e,!0;e-=o,++n}),ke(this,me(n,t))},indexFromPos:function(e){var t=(e=ke(this,e)).ch;if(e.linet&&(t=e.from),null!=e.to&&e.to-1)return t.state.draggingText(e),void setTimeout(function(){return t.display.input.focus()},20);try{var u=e.dataTransfer.getData("Text");if(u){var f;if(t.state.draggingText&&!t.state.draggingText.copy&&(f=t.listSelections()),Gi(t.doc,bi(n,n)),f)for(var d=0;d=0;t--)so(e.doc,"",r[t].from,r[t].to,"+delete");Lr(e)})}function qo(e,t,n){var r=oe(e.text,t+n,n);return r<0||r>e.text.length?null:r}function $o(e,t,n){var r=qo(e,t.ch,n);return null==r?null:new me(t.line,r,n<0?"after":"before")}function Go(e,t,n,r,i){if(e){var o=Je(n,t.doc.direction);if(o){var a,l=i<0?X(o):o[0],s=i<0==(1==l.level),c=s?"after":"before";if(l.level>0||"rtl"==t.doc.direction){var u=Pn(t,n);a=i<0?n.text.length-1:0;var f=Nn(t,u,a).top;a=ae(function(e){return Nn(t,u,e).top==f},i<0==(1==l.level)?l.from:l.to-1,a),"before"==c&&(a=qo(n,a,1))}else a=i<0?l.to:l.from;return new me(r,a,c)}}return new me(r,i<0?n.text.length:0,i<0?"before":"after")}Fo.basic={Left:"goCharLeft",Right:"goCharRight",Up:"goLineUp",Down:"goLineDown",End:"goLineEnd",Home:"goLineStartSmart",PageUp:"goPageUp",PageDown:"goPageDown",Delete:"delCharAfter",Backspace:"delCharBefore","Shift-Backspace":"delCharBefore",Tab:"defaultTab","Shift-Tab":"indentAuto",Enter:"newlineAndIndent",Insert:"toggleOverwrite",Esc:"singleSelection"},Fo.pcDefault={"Ctrl-A":"selectAll","Ctrl-D":"deleteLine","Ctrl-Z":"undo","Shift-Ctrl-Z":"redo","Ctrl-Y":"redo","Ctrl-Home":"goDocStart","Ctrl-End":"goDocEnd","Ctrl-Up":"goLineUp","Ctrl-Down":"goLineDown","Ctrl-Left":"goGroupLeft","Ctrl-Right":"goGroupRight","Alt-Left":"goLineStart","Alt-Right":"goLineEnd","Ctrl-Backspace":"delGroupBefore","Ctrl-Delete":"delGroupAfter","Ctrl-S":"save","Ctrl-F":"find","Ctrl-G":"findNext","Shift-Ctrl-G":"findPrev","Shift-Ctrl-F":"replace","Shift-Ctrl-R":"replaceAll","Ctrl-[":"indentLess","Ctrl-]":"indentMore","Ctrl-U":"undoSelection","Shift-Ctrl-U":"redoSelection","Alt-U":"redoSelection",fallthrough:"basic"},Fo.emacsy={"Ctrl-F":"goCharRight","Ctrl-B":"goCharLeft","Ctrl-P":"goLineUp","Ctrl-N":"goLineDown","Alt-F":"goWordRight","Alt-B":"goWordLeft","Ctrl-A":"goLineStart","Ctrl-E":"goLineEnd","Ctrl-V":"goPageDown","Shift-Ctrl-V":"goPageUp","Ctrl-D":"delCharAfter","Ctrl-H":"delCharBefore","Alt-D":"delWordAfter","Alt-Backspace":"delWordBefore","Ctrl-K":"killLine","Ctrl-T":"transposeChars","Ctrl-O":"openLine"},Fo.macDefault={"Cmd-A":"selectAll","Cmd-D":"deleteLine","Cmd-Z":"undo","Shift-Cmd-Z":"redo","Cmd-Y":"redo","Cmd-Home":"goDocStart","Cmd-Up":"goDocStart","Cmd-End":"goDocEnd","Cmd-Down":"goDocEnd","Alt-Left":"goGroupLeft","Alt-Right":"goGroupRight","Cmd-Left":"goLineLeft","Cmd-Right":"goLineRight","Alt-Backspace":"delGroupBefore","Ctrl-Alt-Backspace":"delGroupAfter","Alt-Delete":"delGroupAfter","Cmd-S":"save","Cmd-F":"find","Cmd-G":"findNext","Shift-Cmd-G":"findPrev","Cmd-Alt-F":"replace","Shift-Cmd-Alt-F":"replaceAll","Cmd-[":"indentLess","Cmd-]":"indentMore","Cmd-Backspace":"delWrappedLineLeft","Cmd-Delete":"delWrappedLineRight","Cmd-U":"undoSelection","Shift-Cmd-U":"redoSelection","Ctrl-Up":"goDocStart","Ctrl-Down":"goDocEnd",fallthrough:["basic","emacsy"]},Fo.default=y?Fo.macDefault:Fo.pcDefault;var Xo={selectAll:to,singleSelection:function(e){return e.setSelection(e.getCursor("anchor"),e.getCursor("head"),j)},killLine:function(e){return Vo(e,function(t){if(t.empty()){var n=le(e.doc,t.head.line).text.length;return t.head.ch==n&&t.head.line0)i=new me(i.line,i.ch+1),e.replaceRange(o.charAt(i.ch-1)+o.charAt(i.ch-2),me(i.line,i.ch-2),i,"+transpose");else if(i.line>e.doc.first){var a=le(e.doc,i.line-1).text;a&&(i=new me(i.line,1),e.replaceRange(o.charAt(0)+e.doc.lineSeparator()+a.charAt(a.length-1),me(i.line-1,a.length-1),i,"+transpose"))}n.push(new vi(i,i))}e.setSelections(n)})},newlineAndIndent:function(e){return qr(e,function(){for(var t=e.listSelections(),n=t.length-1;n>=0;n--)e.replaceRange(e.doc.lineSeparator(),t[n].anchor,t[n].head,"+input");t=e.listSelections();for(var r=0;r-1&&(ge((i=c.ranges[i]).from(),t)<0||t.xRel>0)&&(ge(i.to(),t)>0||t.xRel<0)?function(e,t,n,r){var i=e.display,o=!1,c=$r(e,function(t){s&&(i.scroller.draggable=!1),e.state.draggingText=!1,tt(i.wrapper.ownerDocument,"mouseup",c),tt(i.wrapper.ownerDocument,"mousemove",u),tt(i.scroller,"dragstart",f),tt(i.scroller,"drop",c),o||(lt(t),r.addNew||Ki(e.doc,n,null,null,r.extend),s||a&&9==l?setTimeout(function(){i.wrapper.ownerDocument.body.focus(),i.input.focus()},20):i.input.focus())}),u=function(e){o=o||Math.abs(t.clientX-e.clientX)+Math.abs(t.clientY-e.clientY)>=10},f=function(){return o=!0};s&&(i.scroller.draggable=!0),e.state.draggingText=c,c.copy=!r.moveOnDrag,i.scroller.dragDrop&&i.scroller.dragDrop(),Ze(i.wrapper.ownerDocument,"mouseup",c),Ze(i.wrapper.ownerDocument,"mousemove",u),Ze(i.scroller,"dragstart",f),Ze(i.scroller,"drop",c),mr(e),setTimeout(function(){return i.input.focus()},20)}(e,r,t,o):function(e,t,n,r){var i=e.display,o=e.doc;lt(t);var a,l,s=o.sel,c=s.ranges;if(r.addNew&&!r.extend?(l=o.sel.contains(n),a=l>-1?c[l]:new vi(n,n)):(a=o.sel.primary(),l=o.sel.primIndex),"rectangle"==r.unit)r.addNew||(a=new vi(n,n)),n=ar(e,t,!0,!0),l=-1;else{var u=fa(e,n,r.unit);a=r.extend?Hi(a,u.anchor,u.head,r.extend):u}r.addNew?-1==l?(l=c.length,$i(o,yi(c.concat([a]),l),{scroll:!1,origin:"*mouse"})):c.length>1&&c[l].empty()&&"char"==r.unit&&!r.extend?($i(o,yi(c.slice(0,l).concat(c.slice(l+1)),0),{scroll:!1,origin:"*mouse"}),s=o.sel):Ui(o,l,a,U):(l=0,$i(o,new gi([a],0),U),s=o.sel);var f=n;function d(t){if(0!=ge(f,t))if(f=t,"rectangle"==r.unit){for(var i=[],c=e.options.tabSize,u=W(le(o,n.line).text,n.ch,c),d=W(le(o,t.line).text,t.ch,c),h=Math.min(u,d),p=Math.max(u,d),m=Math.min(n.line,t.line),g=Math.min(e.lastLine(),Math.max(n.line,t.line));m<=g;m++){var v=le(o,m).text,y=q(v,h,c);h==p?i.push(new vi(me(m,y),me(m,y))):v.length>y&&i.push(new vi(me(m,y),me(m,q(v,p,c))))}i.length||i.push(new vi(n,n)),$i(o,yi(s.ranges.slice(0,l).concat(i),l),{origin:"*mouse",scroll:!1}),e.scrollIntoView(t)}else{var b,w=a,x=fa(e,t,r.unit),k=w.anchor;ge(x.anchor,k)>0?(b=x.head,k=we(w.from(),x.anchor)):(b=x.anchor,k=be(w.to(),x.head));var C=s.ranges.slice(0);C[l]=function(e,t){var n=t.anchor,r=t.head,i=le(e.doc,n.line);if(0==ge(n,r)&&n.sticky==r.sticky)return t;var o=Je(i);if(!o)return t;var a=Xe(o,n.ch,n.sticky),l=o[a];if(l.from!=n.ch&&l.to!=n.ch)return t;var s,c=a+(l.from==n.ch==(1!=l.level)?0:1);if(0==c||c==o.length)return t;if(r.line!=n.line)s=(r.line-n.line)*("ltr"==e.doc.direction?1:-1)>0;else{var u=Xe(o,r.ch,r.sticky),f=u-a||(r.ch-n.ch)*(1==l.level?-1:1);s=u==c-1||u==c?f<0:f>0}var d=o[c+(s?-1:0)],h=s==(1==d.level),p=h?d.from:d.to,m=h?"after":"before";return n.ch==p&&n.sticky==m?t:new vi(new me(n.line,p,m),r)}(e,new vi(ke(o,k),b)),$i(o,yi(C,l),U)}}var h=i.wrapper.getBoundingClientRect(),p=0;function m(t){e.state.selectingText=!1,p=1/0,lt(t),i.input.focus(),tt(i.wrapper.ownerDocument,"mousemove",g),tt(i.wrapper.ownerDocument,"mouseup",v),o.history.lastSelOrigin=null}var g=$r(e,function(t){dt(t)?function t(n){var a=++p,l=ar(e,n,!0,"rectangle"==r.unit);if(l)if(0!=ge(l,f)){e.curOp.focus=N(),d(l);var s=wr(i,o);(l.line>=s.to||l.lineh.bottom?20:0;c&&setTimeout($r(e,function(){p==a&&(i.scroller.scrollTop+=c,t(n))}),50)}}(t):m(t)}),v=$r(e,m);e.state.selectingText=v,Ze(i.wrapper.ownerDocument,"mousemove",g),Ze(i.wrapper.ownerDocument,"mouseup",v)}(e,r,t,o)}(t,r,o,e):ft(e)==n.scroller&<(e):2==i?(r&&Ki(t.doc,r),setTimeout(function(){return n.input.focus()},20)):3==i&&(C?pa(t,e):mr(t)))}}function fa(e,t,n){if("char"==n)return new vi(t,t);if("word"==n)return e.findWordAt(t);if("line"==n)return new vi(me(t.line,0),ke(e.doc,me(t.line+1,0)));var r=n(e,t);return new vi(r.from,r.to)}function da(e,t,n,r){var i,o;if(t.touches)i=t.touches[0].clientX,o=t.touches[0].clientY;else try{i=t.clientX,o=t.clientY}catch(t){return!1}if(i>=Math.floor(e.display.gutters.getBoundingClientRect().right))return!1;r&<(t);var a=e.display,l=a.lineDiv.getBoundingClientRect();if(o>l.bottom||!ot(e,n))return ct(t);o-=l.top-a.viewOffset;for(var s=0;s=i){var u=de(e.doc,o),f=e.options.gutters[s];return nt(e,n,e,u,f,t),ct(t)}}}function ha(e,t){return da(e,t,"gutterClick",!0)}function pa(e,t){xn(e.display,t)||function(e,t){return!!ot(e,"gutterContextMenu")&&da(e,t,"gutterContextMenu",!1)}(e,t)||rt(e,t,"contextmenu")||e.display.input.onContextMenu(t)}function ma(e){e.display.wrapper.className=e.display.wrapper.className.replace(/\s*cm-s-\S+/g,"")+e.options.theme.replace(/(^|\s)\s*/g," cm-s-"),zn(e)}ca.prototype.compare=function(e,t,n){return this.time+400>e&&0==ge(t,this.pos)&&n==this.button};var ga={toString:function(){return"CodeMirror.Init"}},va={},ya={};function ba(e){ci(e),Yr(e),xr(e)}function wa(e,t,n){var r=n&&n!=ga;if(!t!=!r){var i=e.display.dragFunctions,o=t?Ze:tt;o(e.display.scroller,"dragstart",i.start),o(e.display.scroller,"dragenter",i.enter),o(e.display.scroller,"dragover",i.over),o(e.display.scroller,"dragleave",i.leave),o(e.display.scroller,"drop",i.drop)}}function xa(e){e.options.lineWrapping?(I(e.display.wrapper,"CodeMirror-wrap"),e.display.sizer.style.minWidth="",e.display.sizerWidth=null):(M(e.display.wrapper,"CodeMirror-wrap"),$e(e)),or(e),Yr(e),zn(e),setTimeout(function(){return Br(e)},100)}function ka(e,t){var r=this;if(!(this instanceof ka))return new ka(e,t);this.options=t=t?F(t):{},F(va,t,!1),ui(t);var i=t.value;"string"==typeof i&&(i=new Lo(i,t.mode,null,t.lineSeparator,t.direction)),this.doc=i;var o=new ka.inputStyles[t.inputStyle](this),c=this.display=new function(e,t,r){var i=this;this.input=r,i.scrollbarFiller=O("div",null,"CodeMirror-scrollbar-filler"),i.scrollbarFiller.setAttribute("cm-not-content","true"),i.gutterFiller=O("div",null,"CodeMirror-gutter-filler"),i.gutterFiller.setAttribute("cm-not-content","true"),i.lineDiv=E("div",null,"CodeMirror-code"),i.selectionDiv=O("div",null,null,"position: relative; z-index: 1"),i.cursorDiv=O("div",null,"CodeMirror-cursors"),i.measure=O("div",null,"CodeMirror-measure"),i.lineMeasure=O("div",null,"CodeMirror-measure"),i.lineSpace=E("div",[i.measure,i.lineMeasure,i.selectionDiv,i.cursorDiv,i.lineDiv],null,"position: relative; outline: none");var o=E("div",[i.lineSpace],"CodeMirror-lines");i.mover=O("div",[o],null,"position: relative"),i.sizer=O("div",[i.mover],"CodeMirror-sizer"),i.sizerWidth=null,i.heightForcer=O("div",null,null,"position: absolute; height: "+H+"px; width: 1px;"),i.gutters=O("div",null,"CodeMirror-gutters"),i.lineGutter=null,i.scroller=O("div",[i.sizer,i.heightForcer,i.gutters],"CodeMirror-scroll"),i.scroller.setAttribute("tabIndex","-1"),i.wrapper=O("div",[i.scrollbarFiller,i.gutterFiller,i.scroller],"CodeMirror"),a&&l<8&&(i.gutters.style.zIndex=-1,i.scroller.style.paddingRight=0),s||n&&v||(i.scroller.draggable=!0),e&&(e.appendChild?e.appendChild(i.wrapper):e(i.wrapper)),i.viewFrom=i.viewTo=t.first,i.reportedViewFrom=i.reportedViewTo=t.first,i.view=[],i.renderedView=null,i.externalMeasured=null,i.viewOffset=0,i.lastWrapHeight=i.lastWrapWidth=0,i.updateLineNumbers=null,i.nativeBarWidth=i.barHeight=i.barWidth=0,i.scrollbarsClipped=!1,i.lineNumWidth=i.lineNumInnerWidth=i.lineNumChars=null,i.alignWidgets=!1,i.cachedCharWidth=i.cachedTextHeight=i.cachedPaddingH=null,i.maxLine=null,i.maxLineLength=0,i.maxLineChanged=!1,i.wheelDX=i.wheelDY=i.wheelStartX=i.wheelStartY=null,i.shift=!1,i.selForContextMenu=null,i.activeTouch=null,r.init(i)}(e,i,o);for(var u in c.wrapper.CodeMirror=this,ci(this),ma(this),t.lineWrapping&&(this.display.wrapper.className+=" CodeMirror-wrap"),Wr(this),this.state={keyMaps:[],overlays:[],modeGen:0,overwrite:!1,delayingBlurEvent:!1,focused:!1,suppressEdits:!1,pasteIncoming:!1,cutIncoming:!1,selectingText:!1,draggingText:!1,highlight:new z,keySeq:null,specialChars:null},t.autofocus&&!v&&c.input.focus(),a&&l<11&&setTimeout(function(){return r.display.input.reset(!0)},20),function(e){var t=e.display;Ze(t.scroller,"mousedown",$r(e,ua)),Ze(t.scroller,"dblclick",a&&l<11?$r(e,function(t){if(!rt(e,t)){var n=ar(e,t);if(n&&!ha(e,t)&&!xn(e.display,t)){lt(t);var r=e.findWordAt(n);Ki(e.doc,r.anchor,r.head)}}}):function(t){return rt(e,t)||lt(t)}),C||Ze(t.scroller,"contextmenu",function(t){return pa(e,t)});var n,r={end:0};function i(){t.activeTouch&&(n=setTimeout(function(){return t.activeTouch=null},1e3),(r=t.activeTouch).end=+new Date)}function o(e,t){if(null==t.left)return!0;var n=t.left-e.left,r=t.top-e.top;return n*n+r*r>400}Ze(t.scroller,"touchstart",function(i){if(!rt(e,i)&&!function(e){if(1!=e.touches.length)return!1;var t=e.touches[0];return t.radiusX<=1&&t.radiusY<=1}(i)&&!ha(e,i)){t.input.ensurePolled(),clearTimeout(n);var o=+new Date;t.activeTouch={start:o,moved:!1,prev:o-r.end<=300?r:null},1==i.touches.length&&(t.activeTouch.left=i.touches[0].pageX,t.activeTouch.top=i.touches[0].pageY)}}),Ze(t.scroller,"touchmove",function(){t.activeTouch&&(t.activeTouch.moved=!0)}),Ze(t.scroller,"touchend",function(n){var r=t.activeTouch;if(r&&!xn(t,n)&&null!=r.left&&!r.moved&&new Date-r.start<300){var a,l=e.coordsChar(t.activeTouch,"page");a=!r.prev||o(r,r.prev)?new vi(l,l):!r.prev.prev||o(r,r.prev.prev)?e.findWordAt(l):new vi(me(l.line,0),ke(e.doc,me(l.line+1,0))),e.setSelection(a.anchor,a.head),e.focus(),lt(n)}i()}),Ze(t.scroller,"touchcancel",i),Ze(t.scroller,"scroll",function(){t.scroller.clientHeight&&(Or(e,t.scroller.scrollTop),Pr(e,t.scroller.scrollLeft,!0),nt(e,"scroll",e))}),Ze(t.scroller,"mousewheel",function(t){return mi(e,t)}),Ze(t.scroller,"DOMMouseScroll",function(t){return mi(e,t)}),Ze(t.wrapper,"scroll",function(){return t.wrapper.scrollTop=t.wrapper.scrollLeft=0}),t.dragFunctions={enter:function(t){rt(e,t)||ut(t)},over:function(t){rt(e,t)||(function(e,t){var n=ar(e,t);if(n){var r=document.createDocumentFragment();ur(e,n,r),e.display.dragCursor||(e.display.dragCursor=O("div",null,"CodeMirror-cursors CodeMirror-dragcursors"),e.display.lineSpace.insertBefore(e.display.dragCursor,e.display.cursorDiv)),A(e.display.dragCursor,r)}}(e,t),ut(t))},start:function(t){return function(e,t){if(a&&(!e.state.draggingText||+new Date-Mo<100))ut(t);else if(!rt(e,t)&&!xn(e.display,t)&&(t.dataTransfer.setData("Text",e.getSelection()),t.dataTransfer.effectAllowed="copyMove",t.dataTransfer.setDragImage&&!d)){var n=O("img",null,null,"position: fixed; left: 0; top: 0;");n.src="data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==",f&&(n.width=n.height=1,e.display.wrapper.appendChild(n),n._top=n.offsetTop),t.dataTransfer.setDragImage(n,0,0),f&&n.parentNode.removeChild(n)}}(e,t)},drop:$r(e,To),leave:function(t){rt(e,t)||Ao(e)}};var s=t.input.getField();Ze(s,"keyup",function(t){return oa.call(e,t)}),Ze(s,"keydown",$r(e,ia)),Ze(s,"keypress",$r(e,aa)),Ze(s,"focus",function(t){return gr(e,t)}),Ze(s,"blur",function(t){return vr(e,t)})}(this),Po(),_r(this),this.curOp.forceUpdate=!0,Oi(this,i),t.autofocus&&!v||this.hasFocus()?setTimeout(D(gr,this),20):vr(this),ya)ya.hasOwnProperty(u)&&ya[u](r,t[u],ga);kr(this),t.finishInit&&t.finishInit(this);for(var h=0;h150)){if(!r)return;n="prev"}}else c=0,n="not";"prev"==n?c=t>o.first?W(le(o,t-1).text,null,a):0:"add"==n?c=s+e.options.indentUnit:"subtract"==n?c=s-e.options.indentUnit:"number"==typeof n&&(c=s+n),c=Math.max(0,c);var f="",d=0;if(e.options.indentWithTabs)for(var h=Math.floor(c/a);h;--h)d+=a,f+="\t";if(d1)if(La&&La.text.join("\n")==t){if(r.ranges.length%La.text.length==0){c=[];for(var u=0;u=0;f--){var d=r.ranges[f],h=d.from(),p=d.to();d.empty()&&(n&&n>0?h=me(h.line,h.ch-n):e.state.overwrite&&!l?p=me(p.line,Math.min(le(o,p.line).text.length,p.ch+X(s).length)):La&&La.lineWise&&La.text.join("\n")==t&&(h=p=me(h.line,0))),a=e.curOp.updateInput;var m={from:h,to:p,text:c?c[f%c.length]:s,origin:i||(l?"paste":e.state.cutIncoming?"cut":"+input")};ro(e.doc,m),ln(e,"inputRead",e,m)}t&&!l&&Oa(e,t),Lr(e),e.curOp.updateInput=a,e.curOp.typing=!0,e.state.pasteIncoming=e.state.cutIncoming=!1}function Aa(e,t){var n=e.clipboardData&&e.clipboardData.getData("Text");if(n)return e.preventDefault(),t.isReadOnly()||t.options.disableInput||qr(t,function(){return Ta(t,n,0,null,"paste")}),!0}function Oa(e,t){if(e.options.electricChars&&e.options.smartIndent)for(var n=e.doc.sel,r=n.ranges.length-1;r>=0;r--){var i=n.ranges[r];if(!(i.head.ch>100||r&&n.ranges[r-1].head.line==i.head.line)){var o=e.getModeAt(i.head),a=!1;if(o.electricChars){for(var l=0;l-1){a=Sa(e,i.head.line,"smart");break}}else o.electricInput&&o.electricInput.test(le(e.doc,i.head.line).text.slice(0,i.head.ch))&&(a=Sa(e,i.head.line,"smart"));a&&ln(e,"electricInput",e,i.head.line)}}}function Ea(e){for(var t=[],n=[],r=0;r=t.text.length?(n.ch=t.text.length,n.sticky="before"):n.ch<=0&&(n.ch=0,n.sticky="after");var o=Xe(i,n.ch,n.sticky),a=i[o];if("ltr"==e.doc.direction&&a.level%2==0&&(r>0?a.to>n.ch:a.from=a.from&&d>=u.begin)){var h=f?"before":"after";return new me(n.line,d,h)}}var p=function(e,t,r){for(var o=function(e,t){return t?new me(n.line,s(e,1),"before"):new me(n.line,e,"after")};e>=0&&e0==(1!=a.level),c=l?r.begin:s(r.end,-1);if(a.from<=c&&c0?u.end:s(u.begin,-1);return null==g||r>0&&g==t.text.length||!(m=p(r>0?0:i.length-1,r,c(g)))?null:m}(e.cm,l,t,n):$o(l,t,n))){if(r||((a=t.line+n)=e.first+e.size||(t=new me(a,t.ch,t.sticky),!(l=le(e,a)))))return!1;t=Go(i,e.cm,l,t.line,n)}else t=o;return!0}if("char"==r)s();else if("column"==r)s(!0);else if("word"==r||"group"==r)for(var c=null,u="group"==r,f=e.cm&&e.cm.getHelper(t,"wordChars"),d=!0;!(n<0)||s(!d);d=!1){var h=l.text.charAt(t.ch)||"\n",p=te(h,f)?"w":u&&"\n"==h?"n":!u||/\s/.test(h)?null:"p";if(!u||d||p||(p="s"),c&&c!=p){n<0&&(n=1,s(),t.sticky="after");break}if(p&&(c=p),n>0&&!s(!d))break}var m=Zi(e,t,o,a,!0);return ve(o,m)&&(m.hitSide=!0),m}function Ra(e,t,n,r){var i,o,a=e.doc,l=t.left;if("page"==r){var s=Math.min(e.display.wrapper.clientHeight,window.innerHeight||document.documentElement.clientHeight),c=Math.max(s-.5*er(e.display),3);i=(n>0?t.bottom:t.top)+n*c}else"line"==r&&(i=n>0?t.bottom+3:t.top-3);for(;(o=Xn(e,l,i)).outside;){if(n<0?i<=0:i>=a.height){o.hitSide=!0;break}i+=5*n}return o}var Ba=function(e){this.cm=e,this.lastAnchorNode=this.lastAnchorOffset=this.lastFocusNode=this.lastFocusOffset=null,this.polling=new z,this.composing=null,this.gracePeriod=!1,this.readDOMTimeout=null};function Da(e,t){var n=En(e,t.line);if(!n||n.hidden)return null;var r=le(e.doc,t.line),i=An(n,r,t.line),o=Je(r,e.doc.direction),a="left";if(o){var l=Xe(o,t.ch);a=l%2?"right":"left"}var s=Bn(i.map,t.ch,a);return s.offset="right"==s.collapse?s.end:s.start,s}function Fa(e,t){return t&&(e.bad=!0),e}function Wa(e,t,n){var r;if(t==e.display.lineDiv){if(!(r=e.display.lineDiv.childNodes[n]))return Fa(e.clipPos(me(e.display.viewTo-1)),!0);t=null,n=0}else for(r=t;;r=r.parentNode){if(!r||r==e.display.lineDiv)return null;if(r.parentNode&&r.parentNode==e.display.lineDiv)break}for(var i=0;i=t.display.viewTo||o.line=t.display.viewFrom&&Da(t,i)||{node:s[0].measure.map[2],offset:0},u=o.liner.firstLine()&&(a=me(a.line-1,le(r.doc,a.line-1).length)),l.ch==le(r.doc,l.line).text.length&&l.linei.viewTo-1)return!1;a.line==i.viewFrom||0==(e=lr(r,a.line))?(t=fe(i.view[0].line),n=i.view[0].node):(t=fe(i.view[e].line),n=i.view[e-1].node.nextSibling);var s,c,u=lr(r,l.line);if(u==i.view.length-1?(s=i.viewTo-1,c=i.lineDiv.lastChild):(s=fe(i.view[u+1].line)-1,c=i.view[u+1].node.previousSibling),!n)return!1;for(var f=r.doc.splitLines(function(e,t,n,r,i){var o="",a=!1,l=e.doc.lineSeparator();function s(){a&&(o+=l,a=!1)}function c(e){e&&(s(),o+=e)}function u(t){if(1==t.nodeType){var n=t.getAttribute("cm-text");if(null!=n)return void c(n||t.textContent.replace(/\u200b/g,""));var o,f=t.getAttribute("cm-marker");if(f){var d=e.findMarks(me(r,0),me(i+1,0),(m=+f,function(e){return e.id==m}));return void(d.length&&(o=d[0].find(0))&&c(se(e.doc,o.from,o.to).join(l)))}if("false"==t.getAttribute("contenteditable"))return;var h=/^(pre|div|p)$/i.test(t.nodeName);h&&s();for(var p=0;p1&&d.length>1;)if(X(f)==X(d))f.pop(),d.pop(),s--;else{if(f[0]!=d[0])break;f.shift(),d.shift(),t++}for(var h=0,p=0,m=f[0],g=d[0],v=Math.min(m.length,g.length);ha.ch&&y.charCodeAt(y.length-p-1)==b.charCodeAt(b.length-p-1);)h--,p++;f[f.length-1]=y.slice(0,y.length-p).replace(/^\u200b+/,""),f[0]=f[0].slice(h).replace(/\u200b+$/,"");var x=me(t,h),k=me(s,d.length?X(d).length-p:0);return f.length>1||f[0]||ge(x,k)?(so(r.doc,f,x,k,"+input"),!0):void 0},Ba.prototype.ensurePolled=function(){this.forceCompositionEnd()},Ba.prototype.reset=function(){this.forceCompositionEnd()},Ba.prototype.forceCompositionEnd=function(){this.composing&&(clearTimeout(this.readDOMTimeout),this.composing=null,this.updateFromDOM(),this.div.blur(),this.div.focus())},Ba.prototype.readFromDOMSoon=function(){var e=this;null==this.readDOMTimeout&&(this.readDOMTimeout=setTimeout(function(){if(e.readDOMTimeout=null,e.composing){if(!e.composing.done)return;e.composing=null}e.updateFromDOM()},80))},Ba.prototype.updateFromDOM=function(){var e=this;!this.cm.isReadOnly()&&this.pollContent()||qr(this.cm,function(){return Yr(e.cm)})},Ba.prototype.setUneditable=function(e){e.contentEditable="false"},Ba.prototype.onKeyPress=function(e){0==e.charCode||this.composing||(e.preventDefault(),this.cm.isReadOnly()||$r(this.cm,Ta)(this.cm,String.fromCharCode(null==e.charCode?e.keyCode:e.charCode),0))},Ba.prototype.readOnlyChanged=function(e){this.div.contentEditable=String("nocursor"!=e)},Ba.prototype.onContextMenu=function(){},Ba.prototype.resetPosition=function(){},Ba.prototype.needsContentAttribute=!0;var _a=function(e){this.cm=e,this.prevInput="",this.pollingFast=!1,this.polling=new z,this.hasSelection=!1,this.composing=null};_a.prototype.init=function(e){var t=this,n=this,r=this.cm;this.createField(e);var i=this.textarea;function o(e){if(!rt(r,e)){if(r.somethingSelected())Ma({lineWise:!1,text:r.getSelections()});else{if(!r.options.lineWiseCopyCut)return;var t=Ea(r);Ma({lineWise:!0,text:t.text}),"cut"==e.type?r.setSelections(t.ranges,null,j):(n.prevInput="",i.value=t.text.join("\n"),B(i))}"cut"==e.type&&(r.state.cutIncoming=!0)}}e.wrapper.insertBefore(this.wrapper,e.wrapper.firstChild),m&&(i.style.width="0px"),Ze(i,"input",function(){a&&l>=9&&t.hasSelection&&(t.hasSelection=null),n.poll()}),Ze(i,"paste",function(e){rt(r,e)||Aa(e,r)||(r.state.pasteIncoming=!0,n.fastPoll())}),Ze(i,"cut",o),Ze(i,"copy",o),Ze(e.scroller,"paste",function(t){xn(e,t)||rt(r,t)||(r.state.pasteIncoming=!0,n.focus())}),Ze(e.lineSpace,"selectstart",function(t){xn(e,t)||lt(t)}),Ze(i,"compositionstart",function(){var e=r.getCursor("from");n.composing&&n.composing.range.clear(),n.composing={start:e,range:r.markText(e,r.getCursor("to"),{className:"CodeMirror-composing"})}}),Ze(i,"compositionend",function(){n.composing&&(n.poll(),n.composing.range.clear(),n.composing=null)})},_a.prototype.createField=function(e){this.wrapper=Na(),this.textarea=this.wrapper.firstChild},_a.prototype.prepareSelection=function(){var e=this.cm,t=e.display,n=e.doc,r=cr(e);if(e.options.moveInputWithCursor){var i=qn(e,n.sel.primary().head,"div"),o=t.wrapper.getBoundingClientRect(),a=t.lineDiv.getBoundingClientRect();r.teTop=Math.max(0,Math.min(t.wrapper.clientHeight-10,i.top+a.top-o.top)),r.teLeft=Math.max(0,Math.min(t.wrapper.clientWidth-10,i.left+a.left-o.left))}return r},_a.prototype.showSelection=function(e){var t=this.cm,n=t.display;A(n.cursorDiv,e.cursors),A(n.selectionDiv,e.selection),null!=e.teTop&&(this.wrapper.style.top=e.teTop+"px",this.wrapper.style.left=e.teLeft+"px")},_a.prototype.reset=function(e){if(!this.contextMenuPending&&!this.composing){var t=this.cm;if(t.somethingSelected()){this.prevInput="";var n=t.getSelection();this.textarea.value=n,t.state.focused&&B(this.textarea),a&&l>=9&&(this.hasSelection=n)}else e||(this.prevInput=this.textarea.value="",a&&l>=9&&(this.hasSelection=null))}},_a.prototype.getField=function(){return this.textarea},_a.prototype.supportsTouch=function(){return!1},_a.prototype.focus=function(){if("nocursor"!=this.cm.options.readOnly&&(!v||N()!=this.textarea))try{this.textarea.focus()}catch(e){}},_a.prototype.blur=function(){this.textarea.blur()},_a.prototype.resetPosition=function(){this.wrapper.style.top=this.wrapper.style.left=0},_a.prototype.receivedFocus=function(){this.slowPoll()},_a.prototype.slowPoll=function(){var e=this;this.pollingFast||this.polling.set(this.cm.options.pollInterval,function(){e.poll(),e.cm.state.focused&&e.slowPoll()})},_a.prototype.fastPoll=function(){var e=!1,t=this;t.pollingFast=!0,t.polling.set(20,function n(){var r=t.poll();r||e?(t.pollingFast=!1,t.slowPoll()):(e=!0,t.polling.set(60,n))})},_a.prototype.poll=function(){var e=this,t=this.cm,n=this.textarea,r=this.prevInput;if(this.contextMenuPending||!t.state.focused||wt(n)&&!r&&!this.composing||t.isReadOnly()||t.options.disableInput||t.state.keySeq)return!1;var i=n.value;if(i==r&&!t.somethingSelected())return!1;if(a&&l>=9&&this.hasSelection===i||y&&/[\uf700-\uf7ff]/.test(i))return t.display.input.reset(),!1;if(t.doc.sel==t.display.selForContextMenu){var o=i.charCodeAt(0);if(8203!=o||r||(r="​"),8666==o)return this.reset(),this.cm.execCommand("undo")}for(var s=0,c=Math.min(r.length,i.length);s1e3||i.indexOf("\n")>-1?n.value=e.prevInput="":e.prevInput=i,e.composing&&(e.composing.range.clear(),e.composing.range=t.markText(e.composing.start,t.getCursor("to"),{className:"CodeMirror-composing"}))}),!0},_a.prototype.ensurePolled=function(){this.pollingFast&&this.poll()&&(this.pollingFast=!1)},_a.prototype.onKeyPress=function(){a&&l>=9&&(this.hasSelection=null),this.fastPoll()},_a.prototype.onContextMenu=function(e){var t=this,n=t.cm,r=n.display,i=t.textarea,o=ar(n,e),c=r.scroller.scrollTop;if(o&&!f){var u=n.options.resetSelectionOnContextMenu;u&&-1==n.doc.sel.contains(o)&&$r(n,$i)(n.doc,bi(o),j);var d=i.style.cssText,h=t.wrapper.style.cssText;t.wrapper.style.cssText="position: absolute";var p,m=t.wrapper.getBoundingClientRect();if(i.style.cssText="position: absolute; width: 30px; height: 30px;\n top: "+(e.clientY-m.top-5)+"px; left: "+(e.clientX-m.left-5)+"px;\n z-index: 1000; background: "+(a?"rgba(255, 255, 255, .05)":"transparent")+";\n outline: none; border-width: 0; outline: none; overflow: hidden; opacity: .05; filter: alpha(opacity=5);",s&&(p=window.scrollY),r.input.focus(),s&&window.scrollTo(null,p),r.input.reset(),n.somethingSelected()||(i.value=t.prevInput=" "),t.contextMenuPending=!0,r.selForContextMenu=n.doc.sel,clearTimeout(r.detectingSelectAll),a&&l>=9&&v(),C){ut(e);var g=function(){tt(window,"mouseup",g),setTimeout(y,20)};Ze(window,"mouseup",g)}else setTimeout(y,50)}function v(){if(null!=i.selectionStart){var e=n.somethingSelected(),o="​"+(e?i.value:"");i.value="⇚",i.value=o,t.prevInput=e?"":"​",i.selectionStart=1,i.selectionEnd=o.length,r.selForContextMenu=n.doc.sel}}function y(){if(t.contextMenuPending=!1,t.wrapper.style.cssText=h,i.style.cssText=d,a&&l<9&&r.scrollbars.setScrollTop(r.scroller.scrollTop=c),null!=i.selectionStart){(!a||a&&l<9)&&v();var e=0,o=function(){r.selForContextMenu==n.doc.sel&&0==i.selectionStart&&i.selectionEnd>0&&"​"==t.prevInput?$r(n,to)(n):e++<10?r.detectingSelectAll=setTimeout(o,500):(r.selForContextMenu=null,r.input.reset())};r.detectingSelectAll=setTimeout(o,200)}}},_a.prototype.readOnlyChanged=function(e){e||this.reset(),this.textarea.disabled="nocursor"==e},_a.prototype.setUneditable=function(){},_a.prototype.needsContentAttribute=!1,function(e){var t=e.optionHandlers;function n(n,r,i,o){e.defaults[n]=r,i&&(t[n]=o?function(e,t,n){n!=ga&&i(e,t,n)}:i)}e.defineOption=n,e.Init=ga,n("value","",function(e,t){return e.setValue(t)},!0),n("mode",null,function(e,t){e.doc.modeOption=t,Si(e)},!0),n("indentUnit",2,Si,!0),n("indentWithTabs",!1),n("smartIndent",!0),n("tabSize",4,function(e){Li(e),zn(e),Yr(e)},!0),n("lineSeparator",null,function(e,t){if(e.doc.lineSep=t,t){var n=[],r=e.doc.first;e.doc.iter(function(e){for(var i=0;;){var o=e.text.indexOf(t,i);if(-1==o)break;i=o+t.length,n.push(me(r,o))}r++});for(var i=n.length-1;i>=0;i--)so(e.doc,t,n[i],me(n[i].line,n[i].ch+t.length))}}),n("specialChars",/[\u0000-\u001f\u007f-\u009f\u00ad\u061c\u200b-\u200f\u2028\u2029\ufeff]/g,function(e,t,n){e.state.specialChars=new RegExp(t.source+(t.test("\t")?"":"|\t"),"g"),n!=ga&&e.refresh()}),n("specialCharPlaceholder",Jt,function(e){return e.refresh()},!0),n("electricChars",!0),n("inputStyle",v?"contenteditable":"textarea",function(){throw new Error("inputStyle can not (yet) be changed in a running editor")},!0),n("spellcheck",!1,function(e,t){return e.getInputField().spellcheck=t},!0),n("rtlMoveVisually",!w),n("wholeLineUpdateBefore",!0),n("theme","default",function(e){ma(e),ba(e)},!0),n("keyMap","default",function(e,t,n){var r=Uo(t),i=n!=ga&&Uo(n);i&&i.detach&&i.detach(e,r),r.attach&&r.attach(e,i||null)}),n("extraKeys",null),n("configureMouse",null),n("lineWrapping",!1,xa,!0),n("gutters",[],function(e){ui(e.options),ba(e)},!0),n("fixedGutter",!0,function(e,t){e.display.gutters.style.left=t?rr(e.display)+"px":"0",e.refresh()},!0),n("coverGutterNextToScrollbar",!1,function(e){return Br(e)},!0),n("scrollbarStyle","native",function(e){Wr(e),Br(e),e.display.scrollbars.setScrollTop(e.doc.scrollTop),e.display.scrollbars.setScrollLeft(e.doc.scrollLeft)},!0),n("lineNumbers",!1,function(e){ui(e.options),ba(e)},!0),n("firstLineNumber",1,ba,!0),n("lineNumberFormatter",function(e){return e},ba,!0),n("showCursorWhenSelecting",!1,sr,!0),n("resetSelectionOnContextMenu",!0),n("lineWiseCopyCut",!0),n("pasteLinesPerSelection",!0),n("readOnly",!1,function(e,t){"nocursor"==t&&(vr(e),e.display.input.blur()),e.display.input.readOnlyChanged(t)}),n("disableInput",!1,function(e,t){t||e.display.input.reset()},!0),n("dragDrop",!0,wa),n("allowDropFileTypes",null),n("cursorBlinkRate",530),n("cursorScrollMargin",0),n("cursorHeight",1,sr,!0),n("singleCursorHeightPerLine",!0,sr,!0),n("workTime",100),n("workDelay",100),n("flattenSpans",!0,Li,!0),n("addModeClass",!1,Li,!0),n("pollInterval",100),n("undoDepth",200,function(e,t){return e.doc.history.undoDepth=t}),n("historyEventDelay",1250),n("viewportMargin",10,function(e){return e.refresh()},!0),n("maxHighlightLength",1e4,Li,!0),n("moveInputWithCursor",!0,function(e,t){t||e.display.input.resetPosition()}),n("tabindex",null,function(e,t){return e.display.input.getField().tabIndex=t||""}),n("autofocus",null),n("direction","ltr",function(e,t){return e.doc.setDirection(t)},!0)}(ka),function(e){var t=e.optionHandlers,n=e.helpers={};e.prototype={constructor:e,focus:function(){window.focus(),this.display.input.focus()},setOption:function(e,n){var r=this.options,i=r[e];r[e]==n&&"mode"!=e||(r[e]=n,t.hasOwnProperty(e)&&$r(this,t[e])(this,n,i),nt(this,"optionChange",this,e))},getOption:function(e){return this.options[e]},getDoc:function(){return this.doc},addKeyMap:function(e,t){this.state.keyMaps[t?"push":"unshift"](Uo(e))},removeKeyMap:function(e){for(var t=this.state.keyMaps,n=0;nn&&(Sa(this,i.head.line,e,!0),n=i.head.line,r==this.doc.sel.primIndex&&Lr(this));else{var o=i.from(),a=i.to(),l=Math.max(n,o.line);n=Math.min(this.lastLine(),a.line-(a.ch?0:1))+1;for(var s=l;s0&&Ui(this.doc,r,new vi(o,c[r].to()),j)}}}),getTokenAt:function(e,t){return Kt(this,e,t)},getLineTokens:function(e,t){return Kt(this,me(e),t,!0)},getTokenTypeAt:function(e){e=ke(this.doc,e);var t,n=Dt(this,le(this.doc,e.line)),r=0,i=(n.length-1)/2,o=e.ch;if(0==o)t=n[2];else for(;;){var a=r+i>>1;if((a?n[2*a-1]:0)>=o)i=a;else{if(!(n[2*a+1]o&&(e=o,i=!0),r=le(this.doc,e)}else r=e;return jn(this,r,{top:0,left:0},t||"page",n||i).top+(i?this.doc.height-Ve(r):0)},defaultTextHeight:function(){return er(this.display)},defaultCharWidth:function(){return tr(this.display)},getViewport:function(){return{from:this.display.viewFrom,to:this.display.viewTo}},addWidget:function(e,t,n,r,i){var o,a,l,s=this.display,c=(e=qn(this,ke(this.doc,e))).bottom,u=e.left;if(t.style.position="absolute",t.setAttribute("cm-ignore-events","true"),this.display.input.setUneditable(t),s.sizer.appendChild(t),"over"==r)c=e.top;else if("above"==r||"near"==r){var f=Math.max(s.wrapper.clientHeight,this.doc.height),d=Math.max(s.sizer.clientWidth,s.lineSpace.clientWidth);("above"==r||e.bottom+t.offsetHeight>f)&&e.top>t.offsetHeight?c=e.top-t.offsetHeight:e.bottom+t.offsetHeight<=f&&(c=e.bottom),u+t.offsetWidth>d&&(u=d-t.offsetWidth)}t.style.top=c+"px",t.style.left=t.style.right="","right"==i?(u=s.sizer.clientWidth-t.offsetWidth,t.style.right="0px"):("left"==i?u=0:"middle"==i&&(u=(s.sizer.clientWidth-t.offsetWidth)/2),t.style.left=u+"px"),n&&(o=this,a={left:u,top:c,right:u+t.offsetWidth,bottom:c+t.offsetHeight},null!=(l=Cr(o,a)).scrollTop&&Or(o,l.scrollTop),null!=l.scrollLeft&&Pr(o,l.scrollLeft))},triggerOnKeyDown:Gr(ia),triggerOnKeyPress:Gr(aa),triggerOnKeyUp:oa,triggerOnMouseDown:Gr(ua),execCommand:function(e){if(Xo.hasOwnProperty(e))return Xo[e].call(null,this)},triggerElectric:Gr(function(e){Oa(this,e)}),findPosH:function(e,t,n,r){var i=1;t<0&&(i=-1,t=-t);for(var o=ke(this.doc,e),a=0;a0&&l(n.charAt(r-1));)--r;for(;i.5)&&or(this),nt(this,"refresh",this)}),swapDoc:Gr(function(e){var t=this.doc;return t.cm=null,Oi(this,e),zn(this),this.display.input.reset(),Mr(this,e.scrollLeft,e.scrollTop),this.curOp.forceScroll=!0,ln(this,"swapDoc",this,t),t}),getInputField:function(){return this.display.input.getField()},getWrapperElement:function(){return this.display.wrapper},getScrollerElement:function(){return this.display.scroller},getGutterElement:function(){return this.display.gutters}},at(e),e.registerHelper=function(t,r,i){n.hasOwnProperty(t)||(n[t]=e[t]={_global:[]}),n[t][r]=i},e.registerGlobalHelper=function(t,r,i,o){e.registerHelper(t,r,o),n[t]._global.push({pred:i,val:o})}}(ka);var Ha="iter insert remove copy getEditor constructor".split(" ");for(var Ka in Lo.prototype)Lo.prototype.hasOwnProperty(Ka)&&_(Ha,Ka)<0&&(ka.prototype[Ka]=function(e){return function(){return e.apply(this.doc,arguments)}}(Lo.prototype[Ka]));return at(Lo),ka.inputStyles={textarea:_a,contenteditable:Ba},ka.defineMode=function(e){ka.defaults.mode||"null"==e||(ka.defaults.mode=e),function(e,t){arguments.length>2&&(t.dependencies=Array.prototype.slice.call(arguments,2)),Ct[e]=t}.apply(this,arguments)},ka.defineMIME=function(e,t){St[e]=t},ka.defineMode("null",function(){return{token:function(e){return e.skipToEnd()}}}),ka.defineMIME("text/plain","null"),ka.defineExtension=function(e,t){ka.prototype[e]=t},ka.defineDocExtension=function(e,t){Lo.prototype[e]=t},ka.fromTextArea=function(e,t){if((t=t?F(t):{}).value=e.value,!t.tabindex&&e.tabIndex&&(t.tabindex=e.tabIndex),!t.placeholder&&e.placeholder&&(t.placeholder=e.placeholder),null==t.autofocus){var n=N();t.autofocus=n==e||null!=e.getAttribute("autofocus")&&n==document.body}function r(){e.value=l.getValue()}var i;if(e.form&&(Ze(e.form,"submit",r),!t.leaveSubmitMethodAlone)){var o=e.form;i=o.submit;try{var a=o.submit=function(){r(),o.submit=i,o.submit(),o.submit=a}}catch(e){}}t.finishInit=function(t){t.save=r,t.getTextArea=function(){return e},t.toTextArea=function(){t.toTextArea=isNaN,r(),e.parentNode.removeChild(t.getWrapperElement()),e.style.display="",e.form&&(tt(e.form,"submit",r),"function"==typeof e.form.submit&&(e.form.submit=i))}},e.style.display="none";var l=ka(function(t){return e.parentNode.insertBefore(t,e.nextSibling)},t);return l},function(e){e.off=tt,e.on=Ze,e.wheelEventPixels=pi,e.Doc=Lo,e.splitLines=bt,e.countColumn=W,e.findColumn=q,e.isWordChar=ee,e.Pass=K,e.signal=nt,e.Line=Vt,e.changeEnd=wi,e.scrollbarModel=Fr,e.Pos=me,e.cmpPos=ge,e.modes=Ct,e.mimeModes=St,e.resolveMode=Lt,e.getMode=Mt,e.modeExtensions=Tt,e.extendMode=At,e.copyState=Ot,e.startState=Pt,e.innerMode=Et,e.commands=Xo,e.keyMap=Fo,e.keyName=jo,e.isModifierKey=Ho,e.lookupKey=_o,e.normalizeKeyMap=zo,e.StringStream=Nt,e.SharedTextMarker=xo,e.TextMarker=bo,e.LineWidget=go,e.e_preventDefault=lt,e.e_stopPropagation=st,e.e_stop=ut,e.addClass=I,e.contains=P,e.rmClass=M,e.keyNames=Io}(ka),ka.version="5.37.0",ka}()},function(e,t,n){!function(e){"use strict";var t,n,r=e.Pos;function i(e,t){for(var n=function(e){var t=e.flags;return null!=t?t:(e.ignoreCase?"i":"")+(e.global?"g":"")+(e.multiline?"m":"")}(e),r=n,i=0;i>1,l=r(e.slice(0,a)).length;if(l==n)return a;l>n?o=a:i=a+1}}function s(e,s,c,u){var f;this.atOccurrence=!1,this.doc=e,c=c?e.clipPos(c):r(0,0),this.pos={from:c,to:c},"object"==typeof u?f=u.caseFold:(f=u,u=null),"string"==typeof s?(null==f&&(f=!1),this.matches=function(i,o){return(i?function(e,i,o,a){if(!i.length)return null;var s=a?t:n,c=s(i).split(/\r|\n\r?/);e:for(var u=o.line,f=o.ch,d=e.firstLine()-1+c.length;u>=d;u--,f=-1){var h=e.getLine(u);f>-1&&(h=h.slice(0,f));var p=s(h);if(1==c.length){var m=p.lastIndexOf(c[0]);if(-1==m)continue e;return{from:r(u,l(h,p,m,s)),to:r(u,l(h,p,m+c[0].length,s))}}var g=c[c.length-1];if(p.slice(0,g.length)==g){for(var v=1,o=u-c.length+1;v=s;o--,l=-1){var c=e.getLine(o);l>-1&&(c=c.slice(0,l));var u=a(c,t);if(u)return{from:r(o,u.index),to:r(o,u.index+u[0].length),match:u}}}:o)(e,s,n)}:this.matches=function(t,n){return(t?function(e,t,n){t=i(t,"gm");for(var o,l=1,s=n.line,c=e.firstLine();s>=c;){for(var u=0;uc);u++){var f=e.getLine(s++);a=null==a?f:a+"\n"+f}l*=2,t.lastIndex=n.ch;var d=t.exec(a);if(d){var h=a.slice(0,d.index).split("\n"),p=d[0].split("\n"),m=n.line+h.length-1,g=h[h.length-1].length;return{from:r(m,g),to:r(m+p.length-1,1==p.length?g+p[0].length:p[p.length-1].length),match:d}}}})(e,s,n)})}String.prototype.normalize?(t=function(e){return e.normalize("NFD").toLowerCase()},n=function(e){return e.normalize("NFD")}):(t=function(e){return e.toLowerCase()},n=function(e){return e}),s.prototype={findNext:function(){return this.find(!1)},findPrevious:function(){return this.find(!0)},find:function(t){for(var n=this.matches(t,this.doc.clipPos(t?this.pos.from:this.pos.to));n&&0==e.cmpPos(n.from,n.to);)t?n.from.ch?n.from=r(n.from.line,n.from.ch-1):n=n.from.line==this.doc.firstLine()?null:this.matches(t,this.doc.clipPos(r(n.from.line-1))):n.to.ch0);)r.push({anchor:i.from(),head:i.to()});r.length&&this.setSelections(r,0)})}(n(0))},function(e,t,n){!function(e){"use strict";var t={autoSelfClosers:{area:!0,base:!0,br:!0,col:!0,command:!0,embed:!0,frame:!0,hr:!0,img:!0,input:!0,keygen:!0,link:!0,meta:!0,param:!0,source:!0,track:!0,wbr:!0,menuitem:!0},implicitlyClosed:{dd:!0,li:!0,optgroup:!0,option:!0,p:!0,rp:!0,rt:!0,tbody:!0,td:!0,tfoot:!0,th:!0,tr:!0},contextGrabbers:{dd:{dd:!0,dt:!0},dt:{dd:!0,dt:!0},li:{li:!0},option:{option:!0,optgroup:!0},optgroup:{optgroup:!0},p:{address:!0,article:!0,aside:!0,blockquote:!0,dir:!0,div:!0,dl:!0,fieldset:!0,footer:!0,form:!0,h1:!0,h2:!0,h3:!0,h4:!0,h5:!0,h6:!0,header:!0,hgroup:!0,hr:!0,menu:!0,nav:!0,ol:!0,p:!0,pre:!0,section:!0,table:!0,ul:!0},rp:{rp:!0,rt:!0},rt:{rp:!0,rt:!0},tbody:{tbody:!0,tfoot:!0},td:{td:!0,th:!0},tfoot:{tbody:!0},th:{td:!0,th:!0},thead:{tbody:!0,tfoot:!0},tr:{tr:!0}},doNotIndent:{pre:!0},allowUnquoted:!0,allowMissing:!0,caseFold:!0},n={autoSelfClosers:{},implicitlyClosed:{},contextGrabbers:{},doNotIndent:{},allowUnquoted:!1,allowMissing:!1,allowMissingTagName:!1,caseFold:!1};e.defineMode("xml",function(r,i){var o,a,l=r.indentUnit,s={},c=i.htmlMode?t:n;for(var u in c)s[u]=c[u];for(var u in i)s[u]=i[u];function f(e,t){function n(n){return t.tokenize=n,n(e,t)}var r=e.next();return"<"==r?e.eat("!")?e.eat("[")?e.match("CDATA[")?n(h("atom","]]>")):null:e.match("--")?n(h("comment","--\x3e")):e.match("DOCTYPE",!0,!0)?(e.eatWhile(/[\w\._\-]/),n(function e(t){return function(n,r){for(var i;null!=(i=n.next());){if("<"==i)return r.tokenize=e(t+1),r.tokenize(n,r);if(">"==i){if(1==t){r.tokenize=f;break}return r.tokenize=e(t-1),r.tokenize(n,r)}}return"meta"}}(1))):null:e.eat("?")?(e.eatWhile(/[\w\._\-]/),t.tokenize=h("meta","?>"),"meta"):(o=e.eat("/")?"closeTag":"openTag",t.tokenize=d,"tag bracket"):"&"==r?(e.eat("#")?e.eat("x")?e.eatWhile(/[a-fA-F\d]/)&&e.eat(";"):e.eatWhile(/[\d]/)&&e.eat(";"):e.eatWhile(/[\w\.\-:]/)&&e.eat(";"))?"atom":"error":(e.eatWhile(/[^&<]/),null)}function d(e,t){var n,r,i=e.next();if(">"==i||"/"==i&&e.eat(">"))return t.tokenize=f,o=">"==i?"endTag":"selfcloseTag","tag bracket";if("="==i)return o="equals",null;if("<"==i){t.tokenize=f,t.state=g,t.tagName=t.tagStart=null;var a=t.tokenize(e,t);return a?a+" tag error":"tag error"}return/[\'\"]/.test(i)?(t.tokenize=(n=i,(r=function(e,t){for(;!e.eol();)if(e.next()==n){t.tokenize=d;break}return"string"}).isInAttribute=!0,r),t.stringStartCol=e.column(),t.tokenize(e,t)):(e.match(/^[^\s\u00a0=<>\"\']*[^\s\u00a0=<>\"\'\/]/),"word")}function h(e,t){return function(n,r){for(;!n.eol();){if(n.match(t)){r.tokenize=f;break}n.next()}return e}}function p(e){e.context&&(e.context=e.context.prev)}function m(e,t){for(var n;;){if(!e.context)return;if(n=e.context.tagName,!s.contextGrabbers.hasOwnProperty(n)||!s.contextGrabbers[n].hasOwnProperty(t))return;p(e)}}function g(e,t,n){return"openTag"==e?(n.tagStart=t.column(),v):"closeTag"==e?y:g}function v(e,t,n){return"word"==e?(n.tagName=t.current(),a="tag",x):s.allowMissingTagName&&"endTag"==e?(a="tag bracket",x(e,0,n)):(a="error",v)}function y(e,t,n){if("word"==e){var r=t.current();return n.context&&n.context.tagName!=r&&s.implicitlyClosed.hasOwnProperty(n.context.tagName)&&p(n),n.context&&n.context.tagName==r||!1===s.matchClosing?(a="tag",b):(a="tag error",w)}return s.allowMissingTagName&&"endTag"==e?(a="tag bracket",b(e,0,n)):(a="error",w)}function b(e,t,n){return"endTag"!=e?(a="error",b):(p(n),g)}function w(e,t,n){return a="error",b(e,0,n)}function x(e,t,n){if("word"==e)return a="attribute",k;if("endTag"==e||"selfcloseTag"==e){var r=n.tagName,i=n.tagStart;return n.tagName=n.tagStart=null,"selfcloseTag"==e||s.autoSelfClosers.hasOwnProperty(r)?m(n,r):(m(n,r),n.context=new function(e,t,n){this.prev=e.context,this.tagName=t,this.indent=e.indented,this.startOfLine=n,(s.doNotIndent.hasOwnProperty(t)||e.context&&e.context.noIndent)&&(this.noIndent=!0)}(n,r,i==n.indented)),g}return a="error",x}function k(e,t,n){return"equals"==e?C:(s.allowMissing||(a="error"),x(e,0,n))}function C(e,t,n){return"string"==e?S:"word"==e&&s.allowUnquoted?(a="string",x):(a="error",x(e,0,n))}function S(e,t,n){return"string"==e?S:x(e,0,n)}return f.isInText=!0,{startState:function(e){var t={tokenize:f,state:g,indented:e||0,tagName:null,tagStart:null,context:null};return null!=e&&(t.baseIndent=e),t},token:function(e,t){if(!t.tagName&&e.sol()&&(t.indented=e.indentation()),e.eatSpace())return null;o=null;var n=t.tokenize(e,t);return(n||o)&&"comment"!=n&&(a=null,t.state=t.state(o||n,e,t),a&&(n="error"==a?n+" error":a)),n},indent:function(t,n,r){var i=t.context;if(t.tokenize.isInAttribute)return t.tagStart==t.indented?t.stringStartCol+1:t.indented+l;if(i&&i.noIndent)return e.Pass;if(t.tokenize!=d&&t.tokenize!=f)return r?r.match(/^(\s*)/)[0].length:0;if(t.tagName)return!1!==s.multilineTagIndentPastTag?t.tagStart+t.tagName.length+2:t.tagStart+l*(s.multilineTagIndentFactor||1);if(s.alignCDATA&&/$/,blockCommentStart:"\x3c!--",blockCommentEnd:"--\x3e",configuration:s.htmlMode?"html":"xml",helperType:s.htmlMode?"html":"xml",skipAttribute:function(e){e.state==C&&(e.state=x)}}}),e.defineMIME("text/xml","xml"),e.defineMIME("application/xml","xml"),e.mimeModes.hasOwnProperty("text/html")||e.defineMIME("text/html",{name:"xml",htmlMode:!0})}(n(0))},function(e,t,n){!function(e){"use strict";e.defineMode("javascript",function(t,n){var r,i,o=t.indentUnit,a=n.statementIndent,l=n.jsonld,s=n.json||l,c=n.typescript,u=n.wordCharacters||/[\w$\xa1-\uffff]/,f=function(){function e(e){return{type:e,style:"keyword"}}var t=e("keyword a"),n=e("keyword b"),r=e("keyword c"),i=e("keyword d"),o=e("operator"),a={type:"atom",style:"atom"};return{if:e("if"),while:t,with:t,else:n,do:n,try:n,finally:n,return:i,break:i,continue:i,new:e("new"),delete:r,void:r,throw:r,debugger:e("debugger"),var:e("var"),const:e("var"),let:e("var"),function:e("function"),catch:e("catch"),for:e("for"),switch:e("switch"),case:e("case"),default:e("default"),in:o,typeof:o,instanceof:o,true:a,false:a,null:a,undefined:a,NaN:a,Infinity:a,this:e("this"),class:e("class"),super:e("atom"),yield:r,export:e("export"),import:e("import"),extends:r,await:r}}(),d=/[+\-*&%=<>!?|~^@]/,h=/^@(context|id|value|language|type|container|list|set|reverse|index|base|vocab|graph)"/;function p(e,t,n){return r=e,i=n,t}function m(e,t){var n,r=e.next();if('"'==r||"'"==r)return t.tokenize=(n=r,function(e,t){var r,i=!1;if(l&&"@"==e.peek()&&e.match(h))return t.tokenize=m,p("jsonld-keyword","meta");for(;null!=(r=e.next())&&(r!=n||i);)i=!i&&"\\"==r;return i||(t.tokenize=m),p("string","string")}),t.tokenize(e,t);if("."==r&&e.match(/^\d+(?:[eE][+\-]?\d+)?/))return p("number","number");if("."==r&&e.match(".."))return p("spread","meta");if(/[\[\]{}\(\),;\:\.]/.test(r))return p(r);if("="==r&&e.eat(">"))return p("=>","operator");if("0"==r&&e.eat(/x/i))return e.eatWhile(/[\da-f]/i),p("number","number");if("0"==r&&e.eat(/o/i))return e.eatWhile(/[0-7]/i),p("number","number");if("0"==r&&e.eat(/b/i))return e.eatWhile(/[01]/i),p("number","number");if(/\d/.test(r))return e.match(/^\d*(?:\.\d*)?(?:[eE][+\-]?\d+)?/),p("number","number");if("/"==r)return e.eat("*")?(t.tokenize=g,g(e,t)):e.eat("/")?(e.skipToEnd(),p("comment","comment")):He(e,t,1)?(function(e){for(var t,n=!1,r=!1;null!=(t=e.next());){if(!n){if("/"==t&&!r)return;"["==t?r=!0:r&&"]"==t&&(r=!1)}n=!n&&"\\"==t}}(e),e.match(/^\b(([gimyu])(?![gimyu]*\2))+\b/),p("regexp","string-2")):(e.eat("="),p("operator","operator",e.current()));if("`"==r)return t.tokenize=v,v(e,t);if("#"==r)return e.skipToEnd(),p("error","error");if(d.test(r))return">"==r&&t.lexical&&">"==t.lexical.type||(e.eat("=")?"!"!=r&&"="!=r||e.eat("="):/[<>*+\-]/.test(r)&&(e.eat(r),">"==r&&e.eat(r))),p("operator","operator",e.current());if(u.test(r)){e.eatWhile(u);var i=e.current();if("."!=t.lastType){if(f.propertyIsEnumerable(i)){var o=f[i];return p(o.type,o.style,i)}if("async"==i&&e.match(/^(\s|\/\*.*?\*\/)*[\[\(\w]/,!1))return p("async","keyword",i)}return p("variable","variable",i)}}function g(e,t){for(var n,r=!1;n=e.next();){if("/"==n&&r){t.tokenize=m;break}r="*"==n}return p("comment","comment")}function v(e,t){for(var n,r=!1;null!=(n=e.next());){if(!r&&("`"==n||"$"==n&&e.eat("{"))){t.tokenize=m;break}r=!r&&"\\"==n}return p("quasi","string-2",e.current())}var y="([{}])";function b(e,t){t.fatArrowAt&&(t.fatArrowAt=null);var n=e.string.indexOf("=>",e.start);if(!(n<0)){if(c){var r=/:\s*(?:\w+(?:<[^>]*>|\[\])?|\{[^}]*\})\s*$/.exec(e.string.slice(e.start,n));r&&(n=r.index)}for(var i=0,o=!1,a=n-1;a>=0;--a){var l=e.string.charAt(a),s=y.indexOf(l);if(s>=0&&s<3){if(!i){++a;break}if(0==--i){"("==l&&(o=!0);break}}else if(s>=3&&s<6)++i;else if(u.test(l))o=!0;else{if(/["'\/]/.test(l))return;if(o&&!i){++a;break}}}o&&!i&&(t.fatArrowAt=a)}}var w={atom:!0,number:!0,variable:!0,string:!0,regexp:!0,this:!0,"jsonld-keyword":!0};function x(e,t,n,r,i,o){this.indented=e,this.column=t,this.type=n,this.prev=i,this.info=o,null!=r&&(this.align=r)}function k(e,t){for(var n=e.localVars;n;n=n.next)if(n.name==t)return!0;for(var r=e.context;r;r=r.prev)for(var n=r.vars;n;n=n.next)if(n.name==t)return!0}var C={state:null,column:null,marked:null,cc:null};function S(){for(var e=arguments.length-1;e>=0;e--)C.cc.push(arguments[e])}function L(){return S.apply(null,arguments),!0}function M(e){function t(t){for(var n=t;n;n=n.next)if(n.name==e)return!0;return!1}var r=C.state;if(C.marked="def",r.context){if(t(r.localVars))return;r.localVars={name:e,next:r.localVars}}else{if(t(r.globalVars))return;n.globalVars&&(r.globalVars={name:e,next:r.globalVars})}}function T(e){return"public"==e||"private"==e||"protected"==e||"abstract"==e||"readonly"==e}var A={name:"this",next:{name:"arguments"}};function O(){C.state.context={prev:C.state.context,vars:C.state.localVars},C.state.localVars=A}function E(){C.state.localVars=C.state.context.vars,C.state.context=C.state.context.prev}function P(e,t){var n=function(){var n=C.state,r=n.indented;if("stat"==n.lexical.type)r=n.lexical.indented;else for(var i=n.lexical;i&&")"==i.type&&i.align;i=i.prev)r=i.indented;n.lexical=new x(r,C.stream.column(),e,null,n.lexical,t)};return n.lex=!0,n}function N(){var e=C.state;e.lexical.prev&&(")"==e.lexical.type&&(e.indented=e.lexical.indented),e.lexical=e.lexical.prev)}function I(e){return function t(n){return n==e?L():";"==e?S():L(t)}}function R(e,t){return"var"==e?L(P("vardef",t.length),he,I(";"),N):"keyword a"==e?L(P("form"),F,R,N):"keyword b"==e?L(P("form"),R,N):"keyword d"==e?C.stream.match(/^\s*$/,!1)?L():L(P("stat"),z,I(";"),N):"debugger"==e?L(I(";")):"{"==e?L(P("}"),te,N):";"==e?L():"if"==e?("else"==C.state.lexical.info&&C.state.cc[C.state.cc.length-1]==N&&C.state.cc.pop()(),L(P("form"),F,R,N,ye)):"function"==e?L(Se):"for"==e?L(P("form"),be,R,N):"class"==e||c&&"interface"==t?(C.marked="keyword",L(P("form"),Te,N)):"variable"==e?c&&"declare"==t?(C.marked="keyword",L(R)):c&&("module"==t||"enum"==t||"type"==t)&&C.stream.match(/^\s*\w/,!1)?(C.marked="keyword","enum"==t?L(ze):"type"==t?L(oe,I("operator"),oe,I(";")):L(P("form"),pe,I("{"),P("}"),te,N,N)):c&&"namespace"==t?(C.marked="keyword",L(P("form"),B,te,N)):c&&"abstract"==t?(C.marked="keyword",L(R)):L(P("stat"),G):"switch"==e?L(P("form"),F,I("{"),P("}","switch"),te,N,N):"case"==e?L(B,I(":")):"default"==e?L(I(":")):"catch"==e?L(P("form"),O,I("("),Le,I(")"),R,N,E):"export"==e?L(P("stat"),Pe,N):"import"==e?L(P("stat"),Ie,N):"async"==e?L(R):"@"==t?L(B,R):S(P("stat"),B,I(";"),N)}function B(e,t){return W(e,t,!1)}function D(e,t){return W(e,t,!0)}function F(e){return"("!=e?S():L(P(")"),B,I(")"),N)}function W(e,t,n){if(C.state.fatArrowAt==C.stream.start){var r=n?V:U;if("("==e)return L(O,P(")"),Z(Le,")"),N,I("=>"),r,E);if("variable"==e)return S(O,pe,I("=>"),r,E)}var i=n?H:_;return w.hasOwnProperty(e)?L(i):"function"==e?L(Se,i):"class"==e||c&&"interface"==t?(C.marked="keyword",L(P("form"),Me,N)):"keyword c"==e||"async"==e?L(n?D:B):"("==e?L(P(")"),z,I(")"),N,i):"operator"==e||"spread"==e?L(n?D:B):"["==e?L(P("]"),We,N,i):"{"==e?ee(Y,"}",null,i):"quasi"==e?S(K,i):"new"==e?L(function(e){return function(t){return"."==t?L(e?$:q):"variable"==t&&c?L(ue,e?H:_):S(e?D:B)}}(n)):"import"==e?L(B):L()}function z(e){return e.match(/[;\}\)\],]/)?S():S(B)}function _(e,t){return","==e?L(B):H(e,t,!1)}function H(e,t,n){var r=0==n?_:H,i=0==n?B:D;return"=>"==e?L(O,n?V:U,E):"operator"==e?/\+\+|--/.test(t)||c&&"!"==t?L(r):c&&"<"==t&&C.stream.match(/^([^>]|<.*?>)*>\s*\(/,!1)?L(P(">"),Z(oe,">"),N,r):"?"==t?L(B,I(":"),i):L(i):"quasi"==e?S(K,r):";"!=e?"("==e?ee(D,")","call",r):"."==e?L(X,r):"["==e?L(P("]"),z,I("]"),N,r):c&&"as"==t?(C.marked="keyword",L(oe,r)):"regexp"==e?(C.state.lastType=C.marked="operator",C.stream.backUp(C.stream.pos-C.stream.start-1),L(i)):void 0:void 0}function K(e,t){return"quasi"!=e?S():"${"!=t.slice(t.length-2)?L(K):L(B,j)}function j(e){if("}"==e)return C.marked="string-2",C.state.tokenize=v,L(K)}function U(e){return b(C.stream,C.state),S("{"==e?R:B)}function V(e){return b(C.stream,C.state),S("{"==e?R:D)}function q(e,t){if("target"==t)return C.marked="keyword",L(_)}function $(e,t){if("target"==t)return C.marked="keyword",L(H)}function G(e){return":"==e?L(N,R):S(_,I(";"),N)}function X(e){if("variable"==e)return C.marked="property",L()}function Y(e,t){if("async"==e)return C.marked="property",L(Y);if("variable"==e||"keyword"==C.style){return C.marked="property","get"==t||"set"==t?L(J):(c&&C.state.fatArrowAt==C.stream.start&&(n=C.stream.match(/^\s*:\s*/,!1))&&(C.state.fatArrowAt=C.stream.pos+n[0].length),L(Q));var n}else{if("number"==e||"string"==e)return C.marked=l?"property":C.style+" property",L(Q);if("jsonld-keyword"==e)return L(Q);if(c&&T(t))return C.marked="keyword",L(Y);if("["==e)return L(B,ne,I("]"),Q);if("spread"==e)return L(D,Q);if("*"==t)return C.marked="keyword",L(Y);if(":"==e)return S(Q)}}function J(e){return"variable"!=e?S(Q):(C.marked="property",L(Se))}function Q(e){return":"==e?L(D):"("==e?S(Se):void 0}function Z(e,t,n){function r(i,o){if(n?n.indexOf(i)>-1:","==i){var a=C.state.lexical;return"call"==a.info&&(a.pos=(a.pos||0)+1),L(function(n,r){return n==t||r==t?S():S(e)},r)}return i==t||o==t?L():L(I(t))}return function(n,i){return n==t||i==t?L():S(e,r)}}function ee(e,t,n){for(var r=3;r"),oe):void 0}function ae(e){if("=>"==e)return L(oe)}function le(e,t){return"variable"==e||"keyword"==C.style?(C.marked="property",L(le)):"?"==t?L(le):":"==e?L(oe):"["==e?L(B,ne,I("]"),le):void 0}function se(e,t){return"variable"==e&&C.stream.match(/^\s*[?:]/,!1)||"?"==t?L(se):":"==e?L(oe):S(oe)}function ce(e,t){return"<"==t?L(P(">"),Z(oe,">"),N,ce):"|"==t||"."==e||"&"==t?L(oe):"["==e?L(I("]"),ce):"extends"==t||"implements"==t?(C.marked="keyword",L(oe)):void 0}function ue(e,t){if("<"==t)return L(P(">"),Z(oe,">"),N,ce)}function fe(){return S(oe,de)}function de(e,t){if("="==t)return L(oe)}function he(e,t){return"enum"==t?(C.marked="keyword",L(ze)):S(pe,ne,ge,ve)}function pe(e,t){return c&&T(t)?(C.marked="keyword",L(pe)):"variable"==e?(M(t),L()):"spread"==e?L(pe):"["==e?ee(pe,"]"):"{"==e?ee(me,"}"):void 0}function me(e,t){return"variable"!=e||C.stream.match(/^\s*:/,!1)?("variable"==e&&(C.marked="property"),"spread"==e?L(pe):"}"==e?S():L(I(":"),pe,ge)):(M(t),L(ge))}function ge(e,t){if("="==t)return L(D)}function ve(e){if(","==e)return L(he)}function ye(e,t){if("keyword b"==e&&"else"==t)return L(P("form","else"),R,N)}function be(e,t){return"await"==t?L(be):"("==e?L(P(")"),we,I(")"),N):void 0}function we(e){return"var"==e?L(he,I(";"),ke):";"==e?L(ke):"variable"==e?L(xe):S(B,I(";"),ke)}function xe(e,t){return"in"==t||"of"==t?(C.marked="keyword",L(B)):L(_,ke)}function ke(e,t){return";"==e?L(Ce):"in"==t||"of"==t?(C.marked="keyword",L(B)):S(B,I(";"),Ce)}function Ce(e){")"!=e&&L(B)}function Se(e,t){return"*"==t?(C.marked="keyword",L(Se)):"variable"==e?(M(t),L(Se)):"("==e?L(O,P(")"),Z(Le,")"),N,re,R,E):c&&"<"==t?L(P(">"),Z(fe,">"),N,Se):void 0}function Le(e,t){return"@"==t&&L(B,Le),"spread"==e?L(Le):c&&T(t)?(C.marked="keyword",L(Le)):S(pe,ne,ge)}function Me(e,t){return"variable"==e?Te(e,t):Ae(e,t)}function Te(e,t){if("variable"==e)return M(t),L(Ae)}function Ae(e,t){return"<"==t?L(P(">"),Z(fe,">"),N,Ae):"extends"==t||"implements"==t||c&&","==e?("implements"==t&&(C.marked="keyword"),L(c?oe:B,Ae)):"{"==e?L(P("}"),Oe,N):void 0}function Oe(e,t){return"async"==e||"variable"==e&&("static"==t||"get"==t||"set"==t||c&&T(t))&&C.stream.match(/^\s+[\w$\xa1-\uffff]/,!1)?(C.marked="keyword",L(Oe)):"variable"==e||"keyword"==C.style?(C.marked="property",L(c?Ee:Se,Oe)):"["==e?L(B,ne,I("]"),c?Ee:Se,Oe):"*"==t?(C.marked="keyword",L(Oe)):";"==e?L(Oe):"}"==e?L():"@"==t?L(B,Oe):void 0}function Ee(e,t){return"?"==t?L(Ee):":"==e?L(oe,ge):"="==t?L(D):S(Se)}function Pe(e,t){return"*"==t?(C.marked="keyword",L(Fe,I(";"))):"default"==t?(C.marked="keyword",L(B,I(";"))):"{"==e?L(Z(Ne,"}"),Fe,I(";")):S(R)}function Ne(e,t){return"as"==t?(C.marked="keyword",L(I("variable"))):"variable"==e?S(D,Ne):void 0}function Ie(e){return"string"==e?L():"("==e?S(B):S(Re,Be,Fe)}function Re(e,t){return"{"==e?ee(Re,"}"):("variable"==e&&M(t),"*"==t&&(C.marked="keyword"),L(De))}function Be(e){if(","==e)return L(Re,Be)}function De(e,t){if("as"==t)return C.marked="keyword",L(Re)}function Fe(e,t){if("from"==t)return C.marked="keyword",L(B)}function We(e){return"]"==e?L():S(Z(D,"]"))}function ze(){return S(P("form"),pe,I("{"),P("}"),Z(_e,"}"),N,N)}function _e(){return S(pe,ge)}function He(e,t,n){return t.tokenize==m&&/^(?:operator|sof|keyword [bcd]|case|new|export|default|spread|[\[{}\(,;:]|=>)$/.test(t.lastType)||"quasi"==t.lastType&&/\{\s*$/.test(e.string.slice(0,e.pos-(n||0)))}return N.lex=!0,{startState:function(e){var t={tokenize:m,lastType:"sof",cc:[],lexical:new x((e||0)-o,0,"block",!1),localVars:n.localVars,context:n.localVars&&{vars:n.localVars},indented:e||0};return n.globalVars&&"object"==typeof n.globalVars&&(t.globalVars=n.globalVars),t},token:function(e,t){if(e.sol()&&(t.lexical.hasOwnProperty("align")||(t.lexical.align=!1),t.indented=e.indentation(),b(e,t)),t.tokenize!=g&&e.eatSpace())return null;var n=t.tokenize(e,t);return"comment"==r?n:(t.lastType="operator"!=r||"++"!=i&&"--"!=i?r:"incdec",function(e,t,n,r,i){var o=e.cc;for(C.state=e,C.stream=i,C.marked=null,C.cc=o,C.style=t,e.lexical.hasOwnProperty("align")||(e.lexical.align=!0);;){var a=o.length?o.pop():s?B:R;if(a(n,r)){for(;o.length&&o[o.length-1].lex;)o.pop()();return C.marked?C.marked:"variable"==n&&k(e,r)?"variable-2":t}}}(t,n,r,i,e))},indent:function(t,r){if(t.tokenize==g)return e.Pass;if(t.tokenize!=m)return 0;var i,l=r&&r.charAt(0),s=t.lexical;if(!/^\s*else\b/.test(r))for(var c=t.cc.length-1;c>=0;--c){var u=t.cc[c];if(u==N)s=s.prev;else if(u!=ye)break}for(;("stat"==s.type||"form"==s.type)&&("}"==l||(i=t.cc[t.cc.length-1])&&(i==_||i==H)&&!/^[,\.=+\-*:?[\(]/.test(r));)s=s.prev;a&&")"==s.type&&"stat"==s.prev.type&&(s=s.prev);var f=s.type,h=l==f;return"vardef"==f?s.indented+("operator"==t.lastType||","==t.lastType?s.info+1:0):"form"==f&&"{"==l?s.indented:"form"==f?s.indented+o:"stat"==f?s.indented+(function(e,t){return"operator"==e.lastType||","==e.lastType||d.test(t.charAt(0))||/[,.]/.test(t.charAt(0))}(t,r)?a||o:0):"switch"!=s.info||h||0==n.doubleIndentSwitch?s.align?s.column+(h?0:1):s.indented+(h?0:o):s.indented+(/^(?:case|default)\b/.test(r)?o:2*o)},electricInput:/^\s*(?:case .*?:|default:|\{|\})$/,blockCommentStart:s?null:"/*",blockCommentEnd:s?null:"*/",blockCommentContinue:s?null:" * ",lineComment:s?null:"//",fold:"brace",closeBrackets:"()[]{}''\"\"``",helperType:s?"json":"javascript",jsonldMode:l,jsonMode:s,expressionAllowed:He,skipExpression:function(e){var t=e.cc[e.cc.length-1];t!=B&&t!=D||e.cc.pop()}}}),e.registerHelper("wordChars","javascript",/[\w$]/),e.defineMIME("text/javascript","javascript"),e.defineMIME("text/ecmascript","javascript"),e.defineMIME("application/javascript","javascript"),e.defineMIME("application/x-javascript","javascript"),e.defineMIME("application/ecmascript","javascript"),e.defineMIME("application/json",{name:"javascript",json:!0}),e.defineMIME("application/x-json",{name:"javascript",json:!0}),e.defineMIME("application/ld+json",{name:"javascript",jsonld:!0}),e.defineMIME("text/typescript",{name:"javascript",typescript:!0}),e.defineMIME("application/typescript",{name:"javascript",typescript:!0})}(n(0))},function(e,t,n){!function(e){var t=/MSIE \d/.test(navigator.userAgent)&&(null==document.documentMode||document.documentMode<8),n=e.Pos,r={"(":")>",")":"(<","[":"]>","]":"[<","{":"}>","}":"{<"};function i(e,t,i){var a=e.getLineHandle(t.line),l=t.ch-1,s=i&&i.afterCursor;null==s&&(s=/(^| )cm-fat-cursor($| )/.test(e.getWrapperElement().className));var c=!s&&l>=0&&r[a.text.charAt(l)]||r[a.text.charAt(++l)];if(!c)return null;var u=">"==c.charAt(1)?1:-1;if(i&&i.strict&&u>0!=(l==t.ch))return null;var f=e.getTokenTypeAt(n(t.line,l+1)),d=o(e,n(t.line,l+(u>0?1:0)),u,f||null,i);return null==d?null:{from:n(t.line,l),to:d&&d.pos,match:d&&d.ch==c.charAt(0),forward:u>0}}function o(e,t,i,o,a){for(var l=a&&a.maxScanLineLength||1e4,s=a&&a.maxScanLines||1e3,c=[],u=a&&a.bracketRegex?a.bracketRegex:/[(){}[\]]/,f=i>0?Math.min(t.line+s,e.lastLine()+1):Math.max(e.firstLine()-1,t.line-s),d=t.line;d!=f;d+=i){var h=e.getLine(d);if(h){var p=i>0?0:h.length-1,m=i>0?h.length:-1;if(!(h.length>l))for(d==t.line&&(p=t.ch-(i<0?1:0));p!=m;p+=i){var g=h.charAt(p);if(u.test(g)&&(void 0===o||e.getTokenTypeAt(n(d,p+1))==o)){var v=r[g];if(">"==v.charAt(1)==i>0)c.push(g);else{if(!c.length)return{pos:n(d,p),ch:g};c.pop()}}}}}return d-i!=(i>0?e.lastLine():e.firstLine())&&null}function a(e,r,o){for(var a=e.state.matchBrackets.maxHighlightLineLength||1e3,l=[],s=e.listSelections(),c=0;ct.firstLine();)n=e.Pos(n.line-1,0),c=s(!1);if(c&&!c.cleared&&"unfold"!==o){var u=function(e,t){var n=r(e,t,"widget");if("string"==typeof n){var i=document.createTextNode(n);(n=document.createElement("span")).appendChild(i),n.className="CodeMirror-foldmarker"}else n&&(n=n.cloneNode(!0));return n}(t,i);e.on(u,"mousedown",function(t){f.clear(),e.e_preventDefault(t)});var f=t.markText(c.from,c.to,{replacedWith:u,clearOnEnter:r(t,i,"clearOnEnter"),__isFold:!0});f.on("clear",function(n,r){e.signal(t,"unfold",t,n,r)}),e.signal(t,"fold",t,c.from,c.to)}}e.newFoldFunction=function(e,n){return function(r,i){t(r,i,{rangeFinder:e,widget:n})}},e.defineExtension("foldCode",function(e,n,r){t(this,e,n,r)}),e.defineExtension("isFolded",function(e){for(var t=this.findMarksAt(e),n=0;n0;i--)n.context=n.context.prev;return T(e,t,n)}function O(e){var t=e.current().toLowerCase();o=v.hasOwnProperty(t)?"atom":g.hasOwnProperty(t)?"keyword":"variable"}var E={top:function(e,t,n){if("{"==e)return L(n,t,"block");if("}"==e&&n.context.prev)return M(n);if(w&&/@component/i.test(e))return L(n,t,"atComponentBlock");if(/^@(-moz-)?document$/i.test(e))return L(n,t,"documentTypes");if(/^@(media|supports|(-moz-)?document|import)$/i.test(e))return L(n,t,"atBlock");if(/^@(font-face|counter-style)/i.test(e))return n.stateArg=e,"restricted_atBlock_before";if(/^@(-(moz|ms|o|webkit)-)?keyframes$/i.test(e))return"keyframes";if(e&&"@"==e.charAt(0))return L(n,t,"at");if("hash"==e)o="builtin";else if("word"==e)o="tag";else{if("variable-definition"==e)return"maybeprop";if("interpolation"==e)return L(n,t,"interpolation");if(":"==e)return"pseudo";if(y&&"("==e)return L(n,t,"parens")}return n.context.type},block:function(e,t,n){if("word"==e){var r=t.current().toLowerCase();return d.hasOwnProperty(r)?(o="property","maybeprop"):h.hasOwnProperty(r)?(o="string-2","maybeprop"):y?(o=t.match(/^\s*:(?:\s|$)/,!1)?"property":"tag","block"):(o+=" error","maybeprop")}return"meta"==e?"block":y||"hash"!=e&&"qualifier"!=e?E.top(e,t,n):(o="error","block")},maybeprop:function(e,t,n){return":"==e?L(n,t,"prop"):T(e,t,n)},prop:function(e,t,n){if(";"==e)return M(n);if("{"==e&&y)return L(n,t,"propBlock");if("}"==e||"{"==e)return A(e,t,n);if("("==e)return L(n,t,"parens");if("hash"!=e||/^#([0-9a-fA-f]{3,4}|[0-9a-fA-f]{6}|[0-9a-fA-f]{8})$/.test(t.current())){if("word"==e)O(t);else if("interpolation"==e)return L(n,t,"interpolation")}else o+=" error";return"prop"},propBlock:function(e,t,n){return"}"==e?M(n):"word"==e?(o="property","maybeprop"):n.context.type},parens:function(e,t,n){return"{"==e||"}"==e?A(e,t,n):")"==e?M(n):"("==e?L(n,t,"parens"):"interpolation"==e?L(n,t,"interpolation"):("word"==e&&O(t),"parens")},pseudo:function(e,t,n){return"meta"==e?"pseudo":"word"==e?(o="variable-3",n.context.type):T(e,t,n)},documentTypes:function(e,t,n){return"word"==e&&s.hasOwnProperty(t.current())?(o="tag",n.context.type):E.atBlock(e,t,n)},atBlock:function(e,t,n){if("("==e)return L(n,t,"atBlock_parens");if("}"==e||";"==e)return A(e,t,n);if("{"==e)return M(n)&&L(n,t,y?"block":"top");if("interpolation"==e)return L(n,t,"interpolation");if("word"==e){var r=t.current().toLowerCase();o="only"==r||"not"==r||"and"==r||"or"==r?"keyword":c.hasOwnProperty(r)?"attribute":u.hasOwnProperty(r)?"property":f.hasOwnProperty(r)?"keyword":d.hasOwnProperty(r)?"property":h.hasOwnProperty(r)?"string-2":v.hasOwnProperty(r)?"atom":g.hasOwnProperty(r)?"keyword":"error"}return n.context.type},atComponentBlock:function(e,t,n){return"}"==e?A(e,t,n):"{"==e?M(n)&&L(n,t,y?"block":"top",!1):("word"==e&&(o="error"),n.context.type)},atBlock_parens:function(e,t,n){return")"==e?M(n):"{"==e||"}"==e?A(e,t,n,2):E.atBlock(e,t,n)},restricted_atBlock_before:function(e,t,n){return"{"==e?L(n,t,"restricted_atBlock"):"word"==e&&"@counter-style"==n.stateArg?(o="variable","restricted_atBlock_before"):T(e,t,n)},restricted_atBlock:function(e,t,n){return"}"==e?(n.stateArg=null,M(n)):"word"==e?(o="@font-face"==n.stateArg&&!p.hasOwnProperty(t.current().toLowerCase())||"@counter-style"==n.stateArg&&!m.hasOwnProperty(t.current().toLowerCase())?"error":"property","maybeprop"):"restricted_atBlock"},keyframes:function(e,t,n){return"word"==e?(o="variable","keyframes"):"{"==e?L(n,t,"top"):T(e,t,n)},at:function(e,t,n){return";"==e?M(n):"{"==e||"}"==e?A(e,t,n):("word"==e?o="tag":"hash"==e&&(o="builtin"),"at")},interpolation:function(e,t,n){return"}"==e?M(n):"{"==e||";"==e?A(e,t,n):("word"==e?o="variable":"variable"!=e&&"("!=e&&")"!=e&&(o="error"),"interpolation")}};return{startState:function(e){return{tokenize:null,state:r?"block":"top",stateArg:null,context:new S(r?"block":"top",e||0,null)}},token:function(e,t){if(!t.tokenize&&e.eatSpace())return null;var n=(t.tokenize||function(e,t){var n=e.next();if(l[n]){var r=l[n](e,t);if(!1!==r)return r}return"@"==n?(e.eatWhile(/[\w\\\-]/),x("def",e.current())):"="==n||("~"==n||"|"==n)&&e.eat("=")?x(null,"compare"):'"'==n||"'"==n?(t.tokenize=k(n),t.tokenize(e,t)):"#"==n?(e.eatWhile(/[\w\\\-]/),x("atom","hash")):"!"==n?(e.match(/^\s*\w*/),x("keyword","important")):/\d/.test(n)||"."==n&&e.eat(/\d/)?(e.eatWhile(/[\w.%]/),x("number","unit")):"-"!==n?/[,+>*\/]/.test(n)?x(null,"select-op"):"."==n&&e.match(/^-?[_a-z][_a-z0-9-]*/i)?x("qualifier","qualifier"):/[:;{}\[\]\(\)]/.test(n)?x(null,n):("u"==n||"U"==n)&&e.match(/rl(-prefix)?\(/i)||("d"==n||"D"==n)&&e.match("omain(",!0,!0)||("r"==n||"R"==n)&&e.match("egexp(",!0,!0)?(e.backUp(1),t.tokenize=C,x("property","word")):/[\w\\\-]/.test(n)?(e.eatWhile(/[\w\\\-]/),x("property","word")):x(null,null):/[\d.]/.test(e.peek())?(e.eatWhile(/[\w.%]/),x("number","unit")):e.match(/^-[\w\\\-]+/)?(e.eatWhile(/[\w\\\-]/),e.match(/^\s*:/,!1)?x("variable-2","variable-definition"):x("variable-2","variable")):e.match(/^\w+-/)?x("meta","meta"):void 0})(e,t);return n&&"object"==typeof n&&(i=n[1],n=n[0]),o=n,"comment"!=i&&(t.state=E[t.state](i,e,t)),o},indent:function(e,t){var n=e.context,r=t&&t.charAt(0),i=n.indent;return"prop"!=n.type||"}"!=r&&")"!=r||(n=n.prev),n.prev&&("}"!=r||"block"!=n.type&&"top"!=n.type&&"interpolation"!=n.type&&"restricted_atBlock"!=n.type?(")"!=r||"parens"!=n.type&&"atBlock_parens"!=n.type)&&("{"!=r||"at"!=n.type&&"atBlock"!=n.type)||(i=Math.max(0,n.indent-a)):(n=n.prev,i=n.indent)),i},electricChars:"}",blockCommentStart:"/*",blockCommentEnd:"*/",blockCommentContinue:" * ",lineComment:b,fold:"brace"}});var n=["domain","regexp","url","url-prefix"],r=t(n),i=["all","aural","braille","handheld","print","projection","screen","tty","tv","embossed"],o=t(i),a=["width","min-width","max-width","height","min-height","max-height","device-width","min-device-width","max-device-width","device-height","min-device-height","max-device-height","aspect-ratio","min-aspect-ratio","max-aspect-ratio","device-aspect-ratio","min-device-aspect-ratio","max-device-aspect-ratio","color","min-color","max-color","color-index","min-color-index","max-color-index","monochrome","min-monochrome","max-monochrome","resolution","min-resolution","max-resolution","scan","grid","orientation","device-pixel-ratio","min-device-pixel-ratio","max-device-pixel-ratio","pointer","any-pointer","hover","any-hover"],l=t(a),s=["landscape","portrait","none","coarse","fine","on-demand","hover","interlace","progressive"],c=t(s),u=["align-content","align-items","align-self","alignment-adjust","alignment-baseline","anchor-point","animation","animation-delay","animation-direction","animation-duration","animation-fill-mode","animation-iteration-count","animation-name","animation-play-state","animation-timing-function","appearance","azimuth","backface-visibility","background","background-attachment","background-blend-mode","background-clip","background-color","background-image","background-origin","background-position","background-repeat","background-size","baseline-shift","binding","bleed","bookmark-label","bookmark-level","bookmark-state","bookmark-target","border","border-bottom","border-bottom-color","border-bottom-left-radius","border-bottom-right-radius","border-bottom-style","border-bottom-width","border-collapse","border-color","border-image","border-image-outset","border-image-repeat","border-image-slice","border-image-source","border-image-width","border-left","border-left-color","border-left-style","border-left-width","border-radius","border-right","border-right-color","border-right-style","border-right-width","border-spacing","border-style","border-top","border-top-color","border-top-left-radius","border-top-right-radius","border-top-style","border-top-width","border-width","bottom","box-decoration-break","box-shadow","box-sizing","break-after","break-before","break-inside","caption-side","caret-color","clear","clip","color","color-profile","column-count","column-fill","column-gap","column-rule","column-rule-color","column-rule-style","column-rule-width","column-span","column-width","columns","content","counter-increment","counter-reset","crop","cue","cue-after","cue-before","cursor","direction","display","dominant-baseline","drop-initial-after-adjust","drop-initial-after-align","drop-initial-before-adjust","drop-initial-before-align","drop-initial-size","drop-initial-value","elevation","empty-cells","fit","fit-position","flex","flex-basis","flex-direction","flex-flow","flex-grow","flex-shrink","flex-wrap","float","float-offset","flow-from","flow-into","font","font-feature-settings","font-family","font-kerning","font-language-override","font-size","font-size-adjust","font-stretch","font-style","font-synthesis","font-variant","font-variant-alternates","font-variant-caps","font-variant-east-asian","font-variant-ligatures","font-variant-numeric","font-variant-position","font-weight","grid","grid-area","grid-auto-columns","grid-auto-flow","grid-auto-rows","grid-column","grid-column-end","grid-column-gap","grid-column-start","grid-gap","grid-row","grid-row-end","grid-row-gap","grid-row-start","grid-template","grid-template-areas","grid-template-columns","grid-template-rows","hanging-punctuation","height","hyphens","icon","image-orientation","image-rendering","image-resolution","inline-box-align","justify-content","justify-items","justify-self","left","letter-spacing","line-break","line-height","line-stacking","line-stacking-ruby","line-stacking-shift","line-stacking-strategy","list-style","list-style-image","list-style-position","list-style-type","margin","margin-bottom","margin-left","margin-right","margin-top","marks","marquee-direction","marquee-loop","marquee-play-count","marquee-speed","marquee-style","max-height","max-width","min-height","min-width","move-to","nav-down","nav-index","nav-left","nav-right","nav-up","object-fit","object-position","opacity","order","orphans","outline","outline-color","outline-offset","outline-style","outline-width","overflow","overflow-style","overflow-wrap","overflow-x","overflow-y","padding","padding-bottom","padding-left","padding-right","padding-top","page","page-break-after","page-break-before","page-break-inside","page-policy","pause","pause-after","pause-before","perspective","perspective-origin","pitch","pitch-range","place-content","place-items","place-self","play-during","position","presentation-level","punctuation-trim","quotes","region-break-after","region-break-before","region-break-inside","region-fragment","rendering-intent","resize","rest","rest-after","rest-before","richness","right","rotation","rotation-point","ruby-align","ruby-overhang","ruby-position","ruby-span","shape-image-threshold","shape-inside","shape-margin","shape-outside","size","speak","speak-as","speak-header","speak-numeral","speak-punctuation","speech-rate","stress","string-set","tab-size","table-layout","target","target-name","target-new","target-position","text-align","text-align-last","text-decoration","text-decoration-color","text-decoration-line","text-decoration-skip","text-decoration-style","text-emphasis","text-emphasis-color","text-emphasis-position","text-emphasis-style","text-height","text-indent","text-justify","text-outline","text-overflow","text-shadow","text-size-adjust","text-space-collapse","text-transform","text-underline-position","text-wrap","top","transform","transform-origin","transform-style","transition","transition-delay","transition-duration","transition-property","transition-timing-function","unicode-bidi","user-select","vertical-align","visibility","voice-balance","voice-duration","voice-family","voice-pitch","voice-range","voice-rate","voice-stress","voice-volume","volume","white-space","widows","width","will-change","word-break","word-spacing","word-wrap","z-index","clip-path","clip-rule","mask","enable-background","filter","flood-color","flood-opacity","lighting-color","stop-color","stop-opacity","pointer-events","color-interpolation","color-interpolation-filters","color-rendering","fill","fill-opacity","fill-rule","image-rendering","marker","marker-end","marker-mid","marker-start","shape-rendering","stroke","stroke-dasharray","stroke-dashoffset","stroke-linecap","stroke-linejoin","stroke-miterlimit","stroke-opacity","stroke-width","text-rendering","baseline-shift","dominant-baseline","glyph-orientation-horizontal","glyph-orientation-vertical","text-anchor","writing-mode"],f=t(u),d=["scrollbar-arrow-color","scrollbar-base-color","scrollbar-dark-shadow-color","scrollbar-face-color","scrollbar-highlight-color","scrollbar-shadow-color","scrollbar-3d-light-color","scrollbar-track-color","shape-inside","searchfield-cancel-button","searchfield-decoration","searchfield-results-button","searchfield-results-decoration","zoom"],h=t(d),p=t(["font-family","src","unicode-range","font-variant","font-feature-settings","font-stretch","font-weight","font-style"]),m=t(["additive-symbols","fallback","negative","pad","prefix","range","speak-as","suffix","symbols","system"]),g=["aliceblue","antiquewhite","aqua","aquamarine","azure","beige","bisque","black","blanchedalmond","blue","blueviolet","brown","burlywood","cadetblue","chartreuse","chocolate","coral","cornflowerblue","cornsilk","crimson","cyan","darkblue","darkcyan","darkgoldenrod","darkgray","darkgreen","darkkhaki","darkmagenta","darkolivegreen","darkorange","darkorchid","darkred","darksalmon","darkseagreen","darkslateblue","darkslategray","darkturquoise","darkviolet","deeppink","deepskyblue","dimgray","dodgerblue","firebrick","floralwhite","forestgreen","fuchsia","gainsboro","ghostwhite","gold","goldenrod","gray","grey","green","greenyellow","honeydew","hotpink","indianred","indigo","ivory","khaki","lavender","lavenderblush","lawngreen","lemonchiffon","lightblue","lightcoral","lightcyan","lightgoldenrodyellow","lightgray","lightgreen","lightpink","lightsalmon","lightseagreen","lightskyblue","lightslategray","lightsteelblue","lightyellow","lime","limegreen","linen","magenta","maroon","mediumaquamarine","mediumblue","mediumorchid","mediumpurple","mediumseagreen","mediumslateblue","mediumspringgreen","mediumturquoise","mediumvioletred","midnightblue","mintcream","mistyrose","moccasin","navajowhite","navy","oldlace","olive","olivedrab","orange","orangered","orchid","palegoldenrod","palegreen","paleturquoise","palevioletred","papayawhip","peachpuff","peru","pink","plum","powderblue","purple","rebeccapurple","red","rosybrown","royalblue","saddlebrown","salmon","sandybrown","seagreen","seashell","sienna","silver","skyblue","slateblue","slategray","snow","springgreen","steelblue","tan","teal","thistle","tomato","turquoise","violet","wheat","white","whitesmoke","yellow","yellowgreen"],v=t(g),y=["above","absolute","activeborder","additive","activecaption","afar","after-white-space","ahead","alias","all","all-scroll","alphabetic","alternate","always","amharic","amharic-abegede","antialiased","appworkspace","arabic-indic","armenian","asterisks","attr","auto","auto-flow","avoid","avoid-column","avoid-page","avoid-region","background","backwards","baseline","below","bidi-override","binary","bengali","blink","block","block-axis","bold","bolder","border","border-box","both","bottom","break","break-all","break-word","bullets","button","button-bevel","buttonface","buttonhighlight","buttonshadow","buttontext","calc","cambodian","capitalize","caps-lock-indicator","caption","captiontext","caret","cell","center","checkbox","circle","cjk-decimal","cjk-earthly-branch","cjk-heavenly-stem","cjk-ideographic","clear","clip","close-quote","col-resize","collapse","color","color-burn","color-dodge","column","column-reverse","compact","condensed","contain","content","contents","content-box","context-menu","continuous","copy","counter","counters","cover","crop","cross","crosshair","currentcolor","cursive","cyclic","darken","dashed","decimal","decimal-leading-zero","default","default-button","dense","destination-atop","destination-in","destination-out","destination-over","devanagari","difference","disc","discard","disclosure-closed","disclosure-open","document","dot-dash","dot-dot-dash","dotted","double","down","e-resize","ease","ease-in","ease-in-out","ease-out","element","ellipse","ellipsis","embed","end","ethiopic","ethiopic-abegede","ethiopic-abegede-am-et","ethiopic-abegede-gez","ethiopic-abegede-ti-er","ethiopic-abegede-ti-et","ethiopic-halehame-aa-er","ethiopic-halehame-aa-et","ethiopic-halehame-am-et","ethiopic-halehame-gez","ethiopic-halehame-om-et","ethiopic-halehame-sid-et","ethiopic-halehame-so-et","ethiopic-halehame-ti-er","ethiopic-halehame-ti-et","ethiopic-halehame-tig","ethiopic-numeric","ew-resize","exclusion","expanded","extends","extra-condensed","extra-expanded","fantasy","fast","fill","fixed","flat","flex","flex-end","flex-start","footnotes","forwards","from","geometricPrecision","georgian","graytext","grid","groove","gujarati","gurmukhi","hand","hangul","hangul-consonant","hard-light","hebrew","help","hidden","hide","higher","highlight","highlighttext","hiragana","hiragana-iroha","horizontal","hsl","hsla","hue","icon","ignore","inactiveborder","inactivecaption","inactivecaptiontext","infinite","infobackground","infotext","inherit","initial","inline","inline-axis","inline-block","inline-flex","inline-grid","inline-table","inset","inside","intrinsic","invert","italic","japanese-formal","japanese-informal","justify","kannada","katakana","katakana-iroha","keep-all","khmer","korean-hangul-formal","korean-hanja-formal","korean-hanja-informal","landscape","lao","large","larger","left","level","lighter","lighten","line-through","linear","linear-gradient","lines","list-item","listbox","listitem","local","logical","loud","lower","lower-alpha","lower-armenian","lower-greek","lower-hexadecimal","lower-latin","lower-norwegian","lower-roman","lowercase","ltr","luminosity","malayalam","match","matrix","matrix3d","media-controls-background","media-current-time-display","media-fullscreen-button","media-mute-button","media-play-button","media-return-to-realtime-button","media-rewind-button","media-seek-back-button","media-seek-forward-button","media-slider","media-sliderthumb","media-time-remaining-display","media-volume-slider","media-volume-slider-container","media-volume-sliderthumb","medium","menu","menulist","menulist-button","menulist-text","menulist-textfield","menutext","message-box","middle","min-intrinsic","mix","mongolian","monospace","move","multiple","multiply","myanmar","n-resize","narrower","ne-resize","nesw-resize","no-close-quote","no-drop","no-open-quote","no-repeat","none","normal","not-allowed","nowrap","ns-resize","numbers","numeric","nw-resize","nwse-resize","oblique","octal","opacity","open-quote","optimizeLegibility","optimizeSpeed","oriya","oromo","outset","outside","outside-shape","overlay","overline","padding","padding-box","painted","page","paused","persian","perspective","plus-darker","plus-lighter","pointer","polygon","portrait","pre","pre-line","pre-wrap","preserve-3d","progress","push-button","radial-gradient","radio","read-only","read-write","read-write-plaintext-only","rectangle","region","relative","repeat","repeating-linear-gradient","repeating-radial-gradient","repeat-x","repeat-y","reset","reverse","rgb","rgba","ridge","right","rotate","rotate3d","rotateX","rotateY","rotateZ","round","row","row-resize","row-reverse","rtl","run-in","running","s-resize","sans-serif","saturation","scale","scale3d","scaleX","scaleY","scaleZ","screen","scroll","scrollbar","scroll-position","se-resize","searchfield","searchfield-cancel-button","searchfield-decoration","searchfield-results-button","searchfield-results-decoration","self-start","self-end","semi-condensed","semi-expanded","separate","serif","show","sidama","simp-chinese-formal","simp-chinese-informal","single","skew","skewX","skewY","skip-white-space","slide","slider-horizontal","slider-vertical","sliderthumb-horizontal","sliderthumb-vertical","slow","small","small-caps","small-caption","smaller","soft-light","solid","somali","source-atop","source-in","source-out","source-over","space","space-around","space-between","space-evenly","spell-out","square","square-button","start","static","status-bar","stretch","stroke","sub","subpixel-antialiased","super","sw-resize","symbolic","symbols","system-ui","table","table-caption","table-cell","table-column","table-column-group","table-footer-group","table-header-group","table-row","table-row-group","tamil","telugu","text","text-bottom","text-top","textarea","textfield","thai","thick","thin","threeddarkshadow","threedface","threedhighlight","threedlightshadow","threedshadow","tibetan","tigre","tigrinya-er","tigrinya-er-abegede","tigrinya-et","tigrinya-et-abegede","to","top","trad-chinese-formal","trad-chinese-informal","transform","translate","translate3d","translateX","translateY","translateZ","transparent","ultra-condensed","ultra-expanded","underline","unset","up","upper-alpha","upper-armenian","upper-greek","upper-hexadecimal","upper-latin","upper-norwegian","upper-roman","uppercase","urdu","url","var","vertical","vertical-text","visible","visibleFill","visiblePainted","visibleStroke","visual","w-resize","wait","wave","wider","window","windowframe","windowtext","words","wrap","wrap-reverse","x-large","x-small","xor","xx-large","xx-small"],b=t(y),w=n.concat(i).concat(a).concat(s).concat(u).concat(d).concat(g).concat(y);function x(e,t){for(var n,r=!1;null!=(n=e.next());){if(r&&"/"==n){t.tokenize=null;break}r="*"==n}return["comment","comment"]}e.registerHelper("hintWords","css",w),e.defineMIME("text/css",{documentTypes:r,mediaTypes:o,mediaFeatures:l,mediaValueKeywords:c,propertyKeywords:f,nonStandardPropertyKeywords:h,fontProperties:p,counterDescriptors:m,colorKeywords:v,valueKeywords:b,tokenHooks:{"/":function(e,t){return!!e.eat("*")&&(t.tokenize=x,x(e,t))}},name:"css"}),e.defineMIME("text/x-scss",{mediaTypes:o,mediaFeatures:l,mediaValueKeywords:c,propertyKeywords:f,nonStandardPropertyKeywords:h,colorKeywords:v,valueKeywords:b,fontProperties:p,allowNested:!0,lineComment:"//",tokenHooks:{"/":function(e,t){return e.eat("/")?(e.skipToEnd(),["comment","comment"]):e.eat("*")?(t.tokenize=x,x(e,t)):["operator","operator"]},":":function(e){return!!e.match(/\s*\{/,!1)&&[null,null]},$:function(e){return e.match(/^[\w-]+/),e.match(/^\s*:/,!1)?["variable-2","variable-definition"]:["variable-2","variable"]},"#":function(e){return!!e.eat("{")&&[null,"interpolation"]}},name:"css",helperType:"scss"}),e.defineMIME("text/x-less",{mediaTypes:o,mediaFeatures:l,mediaValueKeywords:c,propertyKeywords:f,nonStandardPropertyKeywords:h,colorKeywords:v,valueKeywords:b,fontProperties:p,allowNested:!0,lineComment:"//",tokenHooks:{"/":function(e,t){return e.eat("/")?(e.skipToEnd(),["comment","comment"]):e.eat("*")?(t.tokenize=x,x(e,t)):["operator","operator"]},"@":function(e){return e.eat("{")?[null,"interpolation"]:!e.match(/^(charset|document|font-face|import|(-(moz|ms|o|webkit)-)?keyframes|media|namespace|page|supports)\b/i,!1)&&(e.eatWhile(/[\w\\\-]/),e.match(/^\s*:/,!1)?["variable-2","variable-definition"]:["variable-2","variable"])},"&":function(){return["atom","atom"]}},name:"css",helperType:"less"}),e.defineMIME("text/x-gss",{documentTypes:r,mediaTypes:o,mediaFeatures:l,propertyKeywords:f,nonStandardPropertyKeywords:h,fontProperties:p,counterDescriptors:m,colorKeywords:v,valueKeywords:b,supportsAtComponent:!0,tokenHooks:{"/":function(e,t){return!!e.eat("*")&&(t.tokenize=x,x(e,t))}},name:"css",helperType:"gss"})}(n(0))},function(e,t,n){!function(e){"use strict";e.defineOption("foldGutter",!1,function(t,n,r){var i;r&&r!=e.Init&&(t.clearGutter(t.state.foldGutter.options.gutter),t.state.foldGutter=null,t.off("gutterClick",a),t.off("change",l),t.off("viewportChange",s),t.off("fold",c),t.off("unfold",c),t.off("swapDoc",l)),n&&(t.state.foldGutter=new function(e){this.options=e,this.from=this.to=0}((!0===(i=n)&&(i={}),null==i.gutter&&(i.gutter="CodeMirror-foldgutter"),null==i.indicatorOpen&&(i.indicatorOpen="CodeMirror-foldgutter-open"),null==i.indicatorFolded&&(i.indicatorFolded="CodeMirror-foldgutter-folded"),i)),o(t),t.on("gutterClick",a),t.on("change",l),t.on("viewportChange",s),t.on("fold",c),t.on("unfold",c),t.on("swapDoc",l))});var t=e.Pos;function n(e,n){for(var r=e.findMarks(t(n,0),t(n+1,0)),i=0;i=s&&(o=r(a.indicatorOpen))}e.setGutterMarker(i,a.gutter,o),++l})}function o(e){var t=e.getViewport(),n=e.state.foldGutter;n&&(e.operation(function(){i(e,t.from,t.to)}),n.from=t.from,n.to=t.to)}function a(e,r,i){var o=e.state.foldGutter;if(o){var a=o.options;if(i==a.gutter){var l=n(e,r);l?l.clear():e.foldCode(t(r,0),a.rangeFinder)}}}function l(e){var t=e.state.foldGutter;if(t){var n=t.options;t.from=t.to=0,clearTimeout(t.changeUpdate),t.changeUpdate=setTimeout(function(){o(e)},n.foldOnChangeTimeSpan||600)}}function s(e){var t=e.state.foldGutter;if(t){var n=t.options;clearTimeout(t.changeUpdate),t.changeUpdate=setTimeout(function(){var n=e.getViewport();t.from==t.to||n.from-t.to>20||t.from-n.to>20?o(e):e.operation(function(){n.fromt.to&&(i(e,t.to,n.to),t.to=n.to)})},n.updateViewportTimeSpan||400)}}function c(e,t){var n=e.state.foldGutter;if(n){var r=t.line;r>=n.from&&r=e.max))return e.ch=0,e.text=e.cm.getLine(++e.line),!0}function s(e){if(!(e.line<=e.min))return e.text=e.cm.getLine(--e.line),e.ch=e.text.length,!0}function c(e){for(;;){var t=e.text.indexOf(">",e.ch);if(-1==t){if(l(e))continue;return}if(a(e,t+1)){var n=e.text.lastIndexOf("/",t),r=n>-1&&!/\S/.test(e.text.slice(n+1,t));return e.ch=t+1,r?"selfClose":"regular"}e.ch=t+1}}function u(e){for(;;){var t=e.ch?e.text.lastIndexOf("<",e.ch-1):-1;if(-1==t){if(s(e))continue;return}if(a(e,t+1)){i.lastIndex=t,e.ch=t;var n=i.exec(e.text);if(n&&n.index==t)return n}else e.ch=t}}function f(e){for(;;){i.lastIndex=e.ch;var t=i.exec(e.text);if(!t){if(l(e))continue;return}if(a(e,t.index+1))return e.ch=t.index+t[0].length,t;e.ch=t.index+1}}function d(e){for(;;){var t=e.ch?e.text.lastIndexOf(">",e.ch-1):-1;if(-1==t){if(s(e))continue;return}if(a(e,t+1)){var n=e.text.lastIndexOf("/",t),r=n>-1&&!/\S/.test(e.text.slice(n+1,t));return e.ch=t+1,r?"selfClose":"regular"}e.ch=t}}function h(e,n){for(var r=[];;){var i,o=f(e),a=e.line,l=e.ch-(o?o[0].length:0);if(!o||!(i=c(e)))return;if("selfClose"!=i)if(o[1]){for(var s=r.length-1;s>=0;--s)if(r[s]==o[2]){r.length=s;break}if(s<0&&(!n||n==o[2]))return{tag:o[2],from:t(a,l),to:t(e.line,e.ch)}}else r.push(o[2])}}function p(e,n){for(var r=[];;){var i=d(e);if(!i)return;if("selfClose"!=i){var o=e.line,a=e.ch,l=u(e);if(!l)return;if(l[1])r.push(l[2]);else{for(var s=r.length-1;s>=0;--s)if(r[s]==l[2]){r.length=s;break}if(s<0&&(!n||n==l[2]))return{tag:l[2],from:t(e.line,e.ch),to:t(o,a)}}}else u(e)}}e.registerHelper("fold","xml",function(e,r){for(var i=new o(e,r.line,0);;){var a=f(i);if(!a||i.line!=r.line)return;var l=c(i);if(!l)return;if(!a[1]&&"selfClose"!=l){var s=t(i.line,i.ch),u=h(i,a[2]);return u&&n(u.from,s)>0?{from:s,to:u.from}:null}}}),e.findMatchingTag=function(e,r,i){var a=new o(e,r.line,r.ch,i);if(-1!=a.text.indexOf(">")||-1!=a.text.indexOf("<")){var l=c(a),s=l&&t(a.line,a.ch),f=l&&u(a);if(l&&f&&!(n(a,r)>0)){var d={from:t(a.line,a.ch),to:s,tag:f[2]};return"selfClose"==l?{open:d,close:null,at:"open"}:f[1]?{open:p(a,f[2]),close:d,at:"close"}:(a=new o(e,s.line,s.ch,i),{open:d,close:h(a,f[2]),at:"open"})}}},e.findEnclosingTag=function(e,t,n,r){for(var i=new o(e,t.line,t.ch,n);;){var a=p(i,r);if(!a)break;var l=new o(e,t.line,t.ch,n),s=h(l,a.tag);if(s)return{open:a,close:s}}},e.scanForClosingTag=function(e,t,n,r){var i=new o(e,t.line,t.ch,r?{from:0,to:r}:null);return h(i,n)}}(n(0))},function(e,t,n){!function(e){"use strict";e.registerGlobalHelper("fold","comment",function(e){return e.blockCommentStart&&e.blockCommentEnd},function(t,n){var r=t.getModeAt(n),i=r.blockCommentStart,o=r.blockCommentEnd;if(i&&o){for(var a,l=n.line,s=t.getLine(l),c=n.ch,u=0;;){var f=c<=0?-1:s.lastIndexOf(i,c-1);if(-1!=f){if(1==u&&ft.lastLine())return null;var r=t.getTokenAt(e.Pos(n,1));if(/\S/.test(r.string)||(r=t.getTokenAt(e.Pos(n,r.end+1))),"keyword"!=r.type||"import"!=r.string)return null;for(var i=n,o=Math.min(t.lastLine(),n+10);i<=o;++i){var a=t.getLine(i),l=a.indexOf(";");if(-1!=l)return{startCh:r.end,end:e.Pos(i,l)}}}var i,o=n.line,a=r(o);if(!a||r(o-1)||(i=r(o-2))&&i.end.line==o-1)return null;for(var l=a.end;;){var s=r(l.line+1);if(null==s)break;l=s.end}return{from:t.clipPos(e.Pos(o,a.startCh+1)),to:l}}),e.registerHelper("fold","include",function(t,n){function r(n){if(nt.lastLine())return null;var r=t.getTokenAt(e.Pos(n,1));return/\S/.test(r.string)||(r=t.getTokenAt(e.Pos(n,r.end+1))),"meta"==r.type&&"#include"==r.string.slice(0,8)?r.start+8:void 0}var i=n.line,o=r(i);if(null==o||null!=r(i-1))return null;for(var a=i;;){var l=r(a+1);if(null==l)break;++a}return{from:e.Pos(i,o+1),to:t.clipPos(e.Pos(a))}})}(n(0))},function(e,t,n){!function(e){"use strict";var t=e.commands,n=e.Pos;function r(t,r){t.extendSelectionsBy(function(i){return t.display.shift||t.doc.extend||i.empty()?function(t,r,i){if(i<0&&0==r.ch)return t.clipPos(n(r.line-1));var o=t.getLine(r.line);if(i>0&&r.ch>=o.length)return t.clipPos(n(r.line+1,0));for(var a,l="start",s=r.ch,c=i<0?0:o.length,u=0;s!=c;s+=i,u++){var f=o.charAt(i<0?s-1:s),d="_"!=f&&e.isWordChar(f)?"w":"o";if("w"==d&&f.toUpperCase()==f&&(d="W"),"start"==l)"o"!=d&&(l="in",a=d);else if("in"==l&&a!=d){if("w"==a&&"W"==d&&i<0&&s--,"W"==a&&"w"==d&&i>0){a="w";continue}break}}return n(r.line,s)}(t.doc,i.head,r):r<0?i.from():i.to()})}function i(t,r){if(t.isReadOnly())return e.Pass;t.operation(function(){for(var e=t.listSelections().length,i=[],o=-1,a=0;a=n&&e.execCommand("goLineUp")}e.scrollTo(null,t.top-e.defaultTextHeight())},t.scrollLineDown=function(e){var t=e.getScrollInfo();if(!e.somethingSelected()){var n=e.lineAtHeight(t.top,"local")+1;e.getCursor().line<=n&&e.execCommand("goLineDown")}e.scrollTo(null,t.top+e.defaultTextHeight())},t.splitSelectionByLine=function(e){for(var t=e.listSelections(),r=[],i=0;io.line&&l==a.line&&0==a.ch||r.push({anchor:l==o.line?o:n(l,0),head:l==a.line?a:n(l)});e.setSelections(r,0)},t.singleSelectionTop=function(e){var t=e.listSelections()[0];e.setSelection(t.anchor,t.head,{scroll:!1})},t.selectLine=function(e){for(var t=e.listSelections(),r=[],i=0;i=0;l--){var s=r[i[l]];if(!(c&&e.cmpPos(s.head,c)>0)){var u=o(t,s.head);c=u.from,t.replaceRange(n(u.word),u.from,u.to)}}})}function f(t){var n=t.getCursor("from"),r=t.getCursor("to");if(0==e.cmpPos(n,r)){var i=o(t,n);if(!i.word)return;n=i.from,r=i.to}return{from:n,to:r,query:t.getRange(n,r),word:i}}function d(e,t){var r=f(e);if(r){var i=r.query,o=e.getSearchCursor(i,t?r.to:r.from);(t?o.findNext():o.findPrevious())?e.setSelection(o.from(),o.to()):(o=e.getSearchCursor(i,t?n(e.firstLine(),0):e.clipPos(n(e.lastLine()))),(t?o.findNext():o.findPrevious())?e.setSelection(o.from(),o.to()):r.word&&e.setSelection(r.from,r.to))}}t.selectScope=function(e){s(e)||e.execCommand("selectAll")},t.selectBetweenBrackets=function(t){if(!s(t))return e.Pass},t.goToBracket=function(t){t.extendSelectionsBy(function(r){var i=t.scanForBracket(r.head,1);if(i&&0!=e.cmpPos(i.pos,r.head))return i.pos;var o=t.scanForBracket(r.head,-1);return o&&n(o.pos.line,o.pos.ch+1)||r.head})},t.swapLineUp=function(t){if(t.isReadOnly())return e.Pass;for(var r=t.listSelections(),i=[],o=t.firstLine()-1,a=[],l=0;lo?i.push(c,u):i.length&&(i[i.length-1]=u),o=u}t.operation(function(){for(var e=0;et.lastLine()?t.replaceRange("\n"+l,n(t.lastLine()),null,"+swapLine"):t.replaceRange(l+"\n",n(o,0),null,"+swapLine")}t.setSelections(a),t.scrollIntoView()})},t.swapLineDown=function(t){if(t.isReadOnly())return e.Pass;for(var r=t.listSelections(),i=[],o=t.lastLine()+1,a=r.length-1;a>=0;a--){var l=r[a],s=l.to().line+1,c=l.from().line;0!=l.to().ch||l.empty()||s--,s=0;e-=2){var r=i[e],o=i[e+1],a=t.getLine(r);r==t.lastLine()?t.replaceRange("",n(r-1),n(r),"+swapLine"):t.replaceRange("",n(r,0),n(r+1,0),"+swapLine"),t.replaceRange(a+"\n",n(o,0),null,"+swapLine")}t.scrollIntoView()})},t.toggleCommentIndented=function(e){e.toggleComment({indent:!0})},t.joinLines=function(e){for(var t=e.listSelections(),r=[],i=0;i=0;o--){var a=r[o].head,l=t.getRange({line:a.line,ch:0},a),s=e.countColumn(l,null,t.getOption("tabSize")),c=t.findPosH(a,-1,"char",!1);if(l&&!/\S/.test(l)&&s%i==0){var u=new n(a.line,e.findColumn(l,s-i,i));u.ch!=a.ch&&(c=u)}t.replaceRange("",c,a,"+delete")}})},t.delLineRight=function(e){e.operation(function(){for(var t=e.listSelections(),r=t.length-1;r>=0;r--)e.replaceRange("",t[r].anchor,n(t[r].to().line),"+delete");e.scrollIntoView()})},t.upcaseAtCursor=function(e){u(e,function(e){return e.toUpperCase()})},t.downcaseAtCursor=function(e){u(e,function(e){return e.toLowerCase()})},t.setSublimeMark=function(e){e.state.sublimeMark&&e.state.sublimeMark.clear(),e.state.sublimeMark=e.setBookmark(e.getCursor())},t.selectToSublimeMark=function(e){var t=e.state.sublimeMark&&e.state.sublimeMark.find();t&&e.setSelection(e.getCursor(),t)},t.deleteToSublimeMark=function(t){var n=t.state.sublimeMark&&t.state.sublimeMark.find();if(n){var r=t.getCursor(),i=n;if(e.cmpPos(r,i)>0){var o=i;i=r,r=o}t.state.sublimeKilled=t.getRange(r,i),t.replaceRange("",r,i)}},t.swapWithSublimeMark=function(e){var t=e.state.sublimeMark&&e.state.sublimeMark.find();t&&(e.state.sublimeMark.clear(),e.state.sublimeMark=e.setBookmark(e.getCursor()),e.setCursor(t))},t.sublimeYank=function(e){null!=e.state.sublimeKilled&&e.replaceSelection(e.state.sublimeKilled,null,"paste")},t.showInCenter=function(e){var t=e.cursorCoords(null,"local");e.scrollTo(null,(t.top+t.bottom)/2-e.getScrollInfo().clientHeight/2)},t.findUnder=function(e){d(e,!0)},t.findUnderPrevious=function(e){d(e,!1)},t.findAllUnder=function(e){var t=f(e);if(t){for(var n=e.getSearchCursor(t.query),r=[],i=-1;n.findNext();)r.push({anchor:n.from(),head:n.to()}),n.from().line<=t.from.line&&n.from().ch<=t.from.ch&&i++;e.setSelections(r,i)}};var h=e.keyMap;h.macSublime={"Cmd-Left":"goLineStartSmart","Shift-Tab":"indentLess","Shift-Ctrl-K":"deleteLine","Alt-Q":"wrapLines","Ctrl-Left":"goSubwordLeft","Ctrl-Right":"goSubwordRight","Ctrl-Alt-Up":"scrollLineUp","Ctrl-Alt-Down":"scrollLineDown","Cmd-L":"selectLine","Shift-Cmd-L":"splitSelectionByLine",Esc:"singleSelectionTop","Cmd-Enter":"insertLineAfter","Shift-Cmd-Enter":"insertLineBefore","Cmd-D":"selectNextOccurrence","Shift-Cmd-Space":"selectScope","Shift-Cmd-M":"selectBetweenBrackets","Cmd-M":"goToBracket","Cmd-Ctrl-Up":"swapLineUp","Cmd-Ctrl-Down":"swapLineDown","Cmd-/":"toggleCommentIndented","Cmd-J":"joinLines","Shift-Cmd-D":"duplicateLine",F9:"sortLines","Cmd-F9":"sortLinesInsensitive",F2:"nextBookmark","Shift-F2":"prevBookmark","Cmd-F2":"toggleBookmark","Shift-Cmd-F2":"clearBookmarks","Alt-F2":"selectBookmarks",Backspace:"smartBackspace","Cmd-K Cmd-K":"delLineRight","Cmd-K Cmd-U":"upcaseAtCursor","Cmd-K Cmd-L":"downcaseAtCursor","Cmd-K Cmd-Space":"setSublimeMark","Cmd-K Cmd-A":"selectToSublimeMark","Cmd-K Cmd-W":"deleteToSublimeMark","Cmd-K Cmd-X":"swapWithSublimeMark","Cmd-K Cmd-Y":"sublimeYank","Cmd-K Cmd-C":"showInCenter","Cmd-K Cmd-G":"clearBookmarks","Cmd-K Cmd-Backspace":"delLineLeft","Cmd-K Cmd-0":"unfoldAll","Cmd-K Cmd-J":"unfoldAll","Ctrl-Shift-Up":"addCursorToPrevLine","Ctrl-Shift-Down":"addCursorToNextLine","Cmd-F3":"findUnder","Shift-Cmd-F3":"findUnderPrevious","Alt-F3":"findAllUnder","Shift-Cmd-[":"fold","Shift-Cmd-]":"unfold","Cmd-I":"findIncremental","Shift-Cmd-I":"findIncrementalReverse","Cmd-H":"replace",F3:"findNext","Shift-F3":"findPrev",fallthrough:"macDefault"},e.normalizeKeyMap(h.macSublime),h.pcSublime={"Shift-Tab":"indentLess","Shift-Ctrl-K":"deleteLine","Alt-Q":"wrapLines","Ctrl-T":"transposeChars","Alt-Left":"goSubwordLeft","Alt-Right":"goSubwordRight","Ctrl-Up":"scrollLineUp","Ctrl-Down":"scrollLineDown","Ctrl-L":"selectLine","Shift-Ctrl-L":"splitSelectionByLine",Esc:"singleSelectionTop","Ctrl-Enter":"insertLineAfter","Shift-Ctrl-Enter":"insertLineBefore","Ctrl-D":"selectNextOccurrence","Shift-Ctrl-Space":"selectScope","Shift-Ctrl-M":"selectBetweenBrackets","Ctrl-M":"goToBracket","Shift-Ctrl-Up":"swapLineUp","Shift-Ctrl-Down":"swapLineDown","Ctrl-/":"toggleCommentIndented","Ctrl-J":"joinLines","Shift-Ctrl-D":"duplicateLine",F9:"sortLines","Ctrl-F9":"sortLinesInsensitive",F2:"nextBookmark","Shift-F2":"prevBookmark","Ctrl-F2":"toggleBookmark","Shift-Ctrl-F2":"clearBookmarks","Alt-F2":"selectBookmarks",Backspace:"smartBackspace","Ctrl-K Ctrl-K":"delLineRight","Ctrl-K Ctrl-U":"upcaseAtCursor","Ctrl-K Ctrl-L":"downcaseAtCursor","Ctrl-K Ctrl-Space":"setSublimeMark","Ctrl-K Ctrl-A":"selectToSublimeMark","Ctrl-K Ctrl-W":"deleteToSublimeMark","Ctrl-K Ctrl-X":"swapWithSublimeMark","Ctrl-K Ctrl-Y":"sublimeYank","Ctrl-K Ctrl-C":"showInCenter","Ctrl-K Ctrl-G":"clearBookmarks","Ctrl-K Ctrl-Backspace":"delLineLeft","Ctrl-K Ctrl-0":"unfoldAll","Ctrl-K Ctrl-J":"unfoldAll","Ctrl-Alt-Up":"addCursorToPrevLine","Ctrl-Alt-Down":"addCursorToNextLine","Ctrl-F3":"findUnder","Shift-Ctrl-F3":"findUnderPrevious","Alt-F3":"findAllUnder","Shift-Ctrl-[":"fold","Shift-Ctrl-]":"unfold","Ctrl-I":"findIncremental","Shift-Ctrl-I":"findIncrementalReverse","Ctrl-H":"replace",F3:"findNext","Shift-F3":"findPrev",fallthrough:"pcDefault"},e.normalizeKeyMap(h.pcSublime);var p=h.default==h.macDefault;h.sublime=p?h.macSublime:h.pcSublime}(n(0),n(1),n(4))},function(e,t,n){!function(e){"use strict";var t=[{keys:"",type:"keyToKey",toKeys:"h"},{keys:"",type:"keyToKey",toKeys:"l"},{keys:"",type:"keyToKey",toKeys:"k"},{keys:"",type:"keyToKey",toKeys:"j"},{keys:"",type:"keyToKey",toKeys:"l"},{keys:"",type:"keyToKey",toKeys:"h",context:"normal"},{keys:"",type:"keyToKey",toKeys:"W"},{keys:"",type:"keyToKey",toKeys:"B",context:"normal"},{keys:"",type:"keyToKey",toKeys:"w"},{keys:"",type:"keyToKey",toKeys:"b",context:"normal"},{keys:"",type:"keyToKey",toKeys:"j"},{keys:"",type:"keyToKey",toKeys:"k"},{keys:"",type:"keyToKey",toKeys:""},{keys:"",type:"keyToKey",toKeys:""},{keys:"",type:"keyToKey",toKeys:"",context:"insert"},{keys:"",type:"keyToKey",toKeys:"",context:"insert"},{keys:"s",type:"keyToKey",toKeys:"cl",context:"normal"},{keys:"s",type:"keyToKey",toKeys:"c",context:"visual"},{keys:"S",type:"keyToKey",toKeys:"cc",context:"normal"},{keys:"S",type:"keyToKey",toKeys:"VdO",context:"visual"},{keys:"",type:"keyToKey",toKeys:"0"},{keys:"",type:"keyToKey",toKeys:"$"},{keys:"",type:"keyToKey",toKeys:""},{keys:"",type:"keyToKey",toKeys:""},{keys:"",type:"keyToKey",toKeys:"j^",context:"normal"},{keys:"",type:"action",action:"toggleOverwrite",context:"insert"},{keys:"H",type:"motion",motion:"moveToTopLine",motionArgs:{linewise:!0,toJumplist:!0}},{keys:"M",type:"motion",motion:"moveToMiddleLine",motionArgs:{linewise:!0,toJumplist:!0}},{keys:"L",type:"motion",motion:"moveToBottomLine",motionArgs:{linewise:!0,toJumplist:!0}},{keys:"h",type:"motion",motion:"moveByCharacters",motionArgs:{forward:!1}},{keys:"l",type:"motion",motion:"moveByCharacters",motionArgs:{forward:!0}},{keys:"j",type:"motion",motion:"moveByLines",motionArgs:{forward:!0,linewise:!0}},{keys:"k",type:"motion",motion:"moveByLines",motionArgs:{forward:!1,linewise:!0}},{keys:"gj",type:"motion",motion:"moveByDisplayLines",motionArgs:{forward:!0}},{keys:"gk",type:"motion",motion:"moveByDisplayLines",motionArgs:{forward:!1}},{keys:"w",type:"motion",motion:"moveByWords",motionArgs:{forward:!0,wordEnd:!1}},{keys:"W",type:"motion",motion:"moveByWords",motionArgs:{forward:!0,wordEnd:!1,bigWord:!0}},{keys:"e",type:"motion",motion:"moveByWords",motionArgs:{forward:!0,wordEnd:!0,inclusive:!0}},{keys:"E",type:"motion",motion:"moveByWords",motionArgs:{forward:!0,wordEnd:!0,bigWord:!0,inclusive:!0}},{keys:"b",type:"motion",motion:"moveByWords",motionArgs:{forward:!1,wordEnd:!1}},{keys:"B",type:"motion",motion:"moveByWords",motionArgs:{forward:!1,wordEnd:!1,bigWord:!0}},{keys:"ge",type:"motion",motion:"moveByWords",motionArgs:{forward:!1,wordEnd:!0,inclusive:!0}},{keys:"gE",type:"motion",motion:"moveByWords",motionArgs:{forward:!1,wordEnd:!0,bigWord:!0,inclusive:!0}},{keys:"{",type:"motion",motion:"moveByParagraph",motionArgs:{forward:!1,toJumplist:!0}},{keys:"}",type:"motion",motion:"moveByParagraph",motionArgs:{forward:!0,toJumplist:!0}},{keys:"(",type:"motion",motion:"moveBySentence",motionArgs:{forward:!1}},{keys:")",type:"motion",motion:"moveBySentence",motionArgs:{forward:!0}},{keys:"",type:"motion",motion:"moveByPage",motionArgs:{forward:!0}},{keys:"",type:"motion",motion:"moveByPage",motionArgs:{forward:!1}},{keys:"",type:"motion",motion:"moveByScroll",motionArgs:{forward:!0,explicitRepeat:!0}},{keys:"",type:"motion",motion:"moveByScroll",motionArgs:{forward:!1,explicitRepeat:!0}},{keys:"gg",type:"motion",motion:"moveToLineOrEdgeOfDocument",motionArgs:{forward:!1,explicitRepeat:!0,linewise:!0,toJumplist:!0}},{keys:"G",type:"motion",motion:"moveToLineOrEdgeOfDocument",motionArgs:{forward:!0,explicitRepeat:!0,linewise:!0,toJumplist:!0}},{keys:"0",type:"motion",motion:"moveToStartOfLine"},{keys:"^",type:"motion",motion:"moveToFirstNonWhiteSpaceCharacter"},{keys:"+",type:"motion",motion:"moveByLines",motionArgs:{forward:!0,toFirstChar:!0}},{keys:"-",type:"motion",motion:"moveByLines",motionArgs:{forward:!1,toFirstChar:!0}},{keys:"_",type:"motion",motion:"moveByLines",motionArgs:{forward:!0,toFirstChar:!0,repeatOffset:-1}},{keys:"$",type:"motion",motion:"moveToEol",motionArgs:{inclusive:!0}},{keys:"%",type:"motion",motion:"moveToMatchedSymbol",motionArgs:{inclusive:!0,toJumplist:!0}},{keys:"f",type:"motion",motion:"moveToCharacter",motionArgs:{forward:!0,inclusive:!0}},{keys:"F",type:"motion",motion:"moveToCharacter",motionArgs:{forward:!1}},{keys:"t",type:"motion",motion:"moveTillCharacter",motionArgs:{forward:!0,inclusive:!0}},{keys:"T",type:"motion",motion:"moveTillCharacter",motionArgs:{forward:!1}},{keys:";",type:"motion",motion:"repeatLastCharacterSearch",motionArgs:{forward:!0}},{keys:",",type:"motion",motion:"repeatLastCharacterSearch",motionArgs:{forward:!1}},{keys:"'",type:"motion",motion:"goToMark",motionArgs:{toJumplist:!0,linewise:!0}},{keys:"`",type:"motion",motion:"goToMark",motionArgs:{toJumplist:!0}},{keys:"]`",type:"motion",motion:"jumpToMark",motionArgs:{forward:!0}},{keys:"[`",type:"motion",motion:"jumpToMark",motionArgs:{forward:!1}},{keys:"]'",type:"motion",motion:"jumpToMark",motionArgs:{forward:!0,linewise:!0}},{keys:"['",type:"motion",motion:"jumpToMark",motionArgs:{forward:!1,linewise:!0}},{keys:"]p",type:"action",action:"paste",isEdit:!0,actionArgs:{after:!0,isEdit:!0,matchIndent:!0}},{keys:"[p",type:"action",action:"paste",isEdit:!0,actionArgs:{after:!1,isEdit:!0,matchIndent:!0}},{keys:"]",type:"motion",motion:"moveToSymbol",motionArgs:{forward:!0,toJumplist:!0}},{keys:"[",type:"motion",motion:"moveToSymbol",motionArgs:{forward:!1,toJumplist:!0}},{keys:"|",type:"motion",motion:"moveToColumn"},{keys:"o",type:"motion",motion:"moveToOtherHighlightedEnd",context:"visual"},{keys:"O",type:"motion",motion:"moveToOtherHighlightedEnd",motionArgs:{sameLine:!0},context:"visual"},{keys:"d",type:"operator",operator:"delete"},{keys:"y",type:"operator",operator:"yank"},{keys:"c",type:"operator",operator:"change"},{keys:">",type:"operator",operator:"indent",operatorArgs:{indentRight:!0}},{keys:"<",type:"operator",operator:"indent",operatorArgs:{indentRight:!1}},{keys:"g~",type:"operator",operator:"changeCase"},{keys:"gu",type:"operator",operator:"changeCase",operatorArgs:{toLower:!0},isEdit:!0},{keys:"gU",type:"operator",operator:"changeCase",operatorArgs:{toLower:!1},isEdit:!0},{keys:"n",type:"motion",motion:"findNext",motionArgs:{forward:!0,toJumplist:!0}},{keys:"N",type:"motion",motion:"findNext",motionArgs:{forward:!1,toJumplist:!0}},{keys:"x",type:"operatorMotion",operator:"delete",motion:"moveByCharacters",motionArgs:{forward:!0},operatorMotionArgs:{visualLine:!1}},{keys:"X",type:"operatorMotion",operator:"delete",motion:"moveByCharacters",motionArgs:{forward:!1},operatorMotionArgs:{visualLine:!0}},{keys:"D",type:"operatorMotion",operator:"delete",motion:"moveToEol",motionArgs:{inclusive:!0},context:"normal"},{keys:"D",type:"operator",operator:"delete",operatorArgs:{linewise:!0},context:"visual"},{keys:"Y",type:"operatorMotion",operator:"yank",motion:"expandToLine",motionArgs:{linewise:!0},context:"normal"},{keys:"Y",type:"operator",operator:"yank",operatorArgs:{linewise:!0},context:"visual"},{keys:"C",type:"operatorMotion",operator:"change",motion:"moveToEol",motionArgs:{inclusive:!0},context:"normal"},{keys:"C",type:"operator",operator:"change",operatorArgs:{linewise:!0},context:"visual"},{keys:"~",type:"operatorMotion",operator:"changeCase",motion:"moveByCharacters",motionArgs:{forward:!0},operatorArgs:{shouldMoveCursor:!0},context:"normal"},{keys:"~",type:"operator",operator:"changeCase",context:"visual"},{keys:"",type:"operatorMotion",operator:"delete",motion:"moveByWords",motionArgs:{forward:!1,wordEnd:!1},context:"insert"},{keys:"",type:"action",action:"jumpListWalk",actionArgs:{forward:!0}},{keys:"",type:"action",action:"jumpListWalk",actionArgs:{forward:!1}},{keys:"",type:"action",action:"scroll",actionArgs:{forward:!0,linewise:!0}},{keys:"",type:"action",action:"scroll",actionArgs:{forward:!1,linewise:!0}},{keys:"a",type:"action",action:"enterInsertMode",isEdit:!0,actionArgs:{insertAt:"charAfter"},context:"normal"},{keys:"A",type:"action",action:"enterInsertMode",isEdit:!0,actionArgs:{insertAt:"eol"},context:"normal"},{keys:"A",type:"action",action:"enterInsertMode",isEdit:!0,actionArgs:{insertAt:"endOfSelectedArea"},context:"visual"},{keys:"i",type:"action",action:"enterInsertMode",isEdit:!0,actionArgs:{insertAt:"inplace"},context:"normal"},{keys:"I",type:"action",action:"enterInsertMode",isEdit:!0,actionArgs:{insertAt:"firstNonBlank"},context:"normal"},{keys:"I",type:"action",action:"enterInsertMode",isEdit:!0,actionArgs:{insertAt:"startOfSelectedArea"},context:"visual"},{keys:"o",type:"action",action:"newLineAndEnterInsertMode",isEdit:!0,interlaceInsertRepeat:!0,actionArgs:{after:!0},context:"normal"},{keys:"O",type:"action",action:"newLineAndEnterInsertMode",isEdit:!0,interlaceInsertRepeat:!0,actionArgs:{after:!1},context:"normal"},{keys:"v",type:"action",action:"toggleVisualMode"},{keys:"V",type:"action",action:"toggleVisualMode",actionArgs:{linewise:!0}},{keys:"",type:"action",action:"toggleVisualMode",actionArgs:{blockwise:!0}},{keys:"",type:"action",action:"toggleVisualMode",actionArgs:{blockwise:!0}},{keys:"gv",type:"action",action:"reselectLastSelection"},{keys:"J",type:"action",action:"joinLines",isEdit:!0},{keys:"p",type:"action",action:"paste",isEdit:!0,actionArgs:{after:!0,isEdit:!0}},{keys:"P",type:"action",action:"paste",isEdit:!0,actionArgs:{after:!1,isEdit:!0}},{keys:"r",type:"action",action:"replace",isEdit:!0},{keys:"@",type:"action",action:"replayMacro"},{keys:"q",type:"action",action:"enterMacroRecordMode"},{keys:"R",type:"action",action:"enterInsertMode",isEdit:!0,actionArgs:{replace:!0}},{keys:"u",type:"action",action:"undo",context:"normal"},{keys:"u",type:"operator",operator:"changeCase",operatorArgs:{toLower:!0},context:"visual",isEdit:!0},{keys:"U",type:"operator",operator:"changeCase",operatorArgs:{toLower:!1},context:"visual",isEdit:!0},{keys:"",type:"action",action:"redo"},{keys:"m",type:"action",action:"setMark"},{keys:'"',type:"action",action:"setRegister"},{keys:"zz",type:"action",action:"scrollToCursor",actionArgs:{position:"center"}},{keys:"z.",type:"action",action:"scrollToCursor",actionArgs:{position:"center"},motion:"moveToFirstNonWhiteSpaceCharacter"},{keys:"zt",type:"action",action:"scrollToCursor",actionArgs:{position:"top"}},{keys:"z",type:"action",action:"scrollToCursor",actionArgs:{position:"top"},motion:"moveToFirstNonWhiteSpaceCharacter"},{keys:"z-",type:"action",action:"scrollToCursor",actionArgs:{position:"bottom"}},{keys:"zb",type:"action",action:"scrollToCursor",actionArgs:{position:"bottom"},motion:"moveToFirstNonWhiteSpaceCharacter"},{keys:".",type:"action",action:"repeatLastEdit"},{keys:"",type:"action",action:"incrementNumberToken",isEdit:!0,actionArgs:{increase:!0,backtrack:!1}},{keys:"",type:"action",action:"incrementNumberToken",isEdit:!0,actionArgs:{increase:!1,backtrack:!1}},{keys:"",type:"action",action:"indent",actionArgs:{indentRight:!0},context:"insert"},{keys:"",type:"action",action:"indent",actionArgs:{indentRight:!1},context:"insert"},{keys:"a",type:"motion",motion:"textObjectManipulation"},{keys:"i",type:"motion",motion:"textObjectManipulation",motionArgs:{textObjectInner:!0}},{keys:"/",type:"search",searchArgs:{forward:!0,querySrc:"prompt",toJumplist:!0}},{keys:"?",type:"search",searchArgs:{forward:!1,querySrc:"prompt",toJumplist:!0}},{keys:"*",type:"search",searchArgs:{forward:!0,querySrc:"wordUnderCursor",wholeWordOnly:!0,toJumplist:!0}},{keys:"#",type:"search",searchArgs:{forward:!1,querySrc:"wordUnderCursor",wholeWordOnly:!0,toJumplist:!0}},{keys:"g*",type:"search",searchArgs:{forward:!0,querySrc:"wordUnderCursor",toJumplist:!0}},{keys:"g#",type:"search",searchArgs:{forward:!1,querySrc:"wordUnderCursor",toJumplist:!0}},{keys:":",type:"ex"}],n=[{name:"colorscheme",shortName:"colo"},{name:"map"},{name:"imap",shortName:"im"},{name:"nmap",shortName:"nm"},{name:"vmap",shortName:"vm"},{name:"unmap"},{name:"write",shortName:"w"},{name:"undo",shortName:"u"},{name:"redo",shortName:"red"},{name:"set",shortName:"se"},{name:"set",shortName:"se"},{name:"setlocal",shortName:"setl"},{name:"setglobal",shortName:"setg"},{name:"sort",shortName:"sor"},{name:"substitute",shortName:"s",possiblyAsync:!0},{name:"nohlsearch",shortName:"noh"},{name:"yank",shortName:"y"},{name:"delmarks",shortName:"delm"},{name:"registers",shortName:"reg",excludeFromCommandHistory:!0},{name:"global",shortName:"g"}],r=e.Pos;e.Vim=function(){function i(t,n){this==e.keyMap.vim&&(e.rmClass(t.getWrapperElement(),"cm-fat-cursor"),"contenteditable"==t.getOption("inputStyle")&&null!=document.body.style.caretColor&&(function(e){var t=e.state.fatCursorMarks;if(t)for(var n=0;n")}(t);if(!r)return!1;var i=e.Vim.findKey(n,r);return"function"==typeof i&&e.signal(n,"vim-keypress",r),i}}e.defineOption("vimMode",!1,function(t,n,r){n&&"vim"!=t.getOption("keyMap")?t.setOption("keyMap","vim"):!n&&r!=e.Init&&/^vim/.test(t.getOption("keyMap"))&&t.setOption("keyMap","default")});var c={Shift:"S",Ctrl:"C",Alt:"A",Cmd:"D",Mod:"A"},u={Enter:"CR",Backspace:"BS",Delete:"Del",Insert:"Ins"};function f(e){var t=e.state.vim;return t.onPasteFn||(t.onPasteFn=function(){t.insertMode||(e.setCursor(J(e.getCursor(),0,1)),G.enterInsertMode(e,{},t))}),t.onPasteFn}var d=/[\d]/,h=[e.isWordChar,function(t){return t&&!e.isWordChar(t)&&!/\s/.test(t)}],p=[function(e){return/\S/.test(e)}];function m(e,t){for(var n=[],r=e;r"]),w=[].concat(g,v,y,["-",'"',".",":","/"]);function x(e,t){return t>=e.firstLine()&&t<=e.lastLine()}function k(e){return/^[a-z]$/.test(e)}function C(e){return/^[A-Z]$/.test(e)}function S(e){return/^\s*$/.test(e)}function L(e){return-1!=".?!".indexOf(e)}function M(e,t){for(var n=0;nn?t=n:t0?1:-1,u=o.getCursor();do{if((l=i[(e+(t+=c))%e])&&(s=l.find())&&!te(u,s))break}while(tr)}return l}}},R=function(e){return e?{changes:e.changes,expectCursorActivityForChange:e.expectCursorActivityForChange}:{changes:[],expectCursorActivityForChange:!1}};function B(){this.latestRegister=void 0,this.isPlaying=!1,this.isRecording=!1,this.replaySearchQueries=[],this.onRecordingDone=void 0,this.lastInsertModeChanges=R()}function D(e){return e.state.vim||(e.state.vim={inputState:new z,lastEditInputState:void 0,lastEditActionCommand:void 0,lastHPos:-1,lastHSPos:-1,lastMotion:null,marks:{},fakeCursor:null,insertMode:!1,insertModeRepeat:void 0,visualMode:!1,visualLine:!1,visualBlock:!1,lastSelection:null,lastPastedText:null,sel:{},options:{}}),e.state.vim}function F(){for(var e in P={searchQuery:null,searchIsReversed:!1,lastSubstituteReplacePart:void 0,jumpList:I(),macroModeState:new B,lastCharacterSearch:{increment:0,forward:!0,selectedCharacter:""},registerController:new K({}),searchHistoryController:new j,exCommandHistoryController:new j},T){var t=T[e];t.value=t.defaultValue}}B.prototype={exitMacroRecordMode:function(){var e=P.macroModeState;e.onRecordingDone&&e.onRecordingDone(),e.onRecordingDone=void 0,e.isRecording=!1},enterMacroRecordMode:function(e,t){var n=P.registerController.getRegister(t);n&&(n.clear(),this.latestRegister=t,e.openDialog&&(this.onRecordingDone=e.openDialog("(recording)["+t+"]",null,{bottom:!0})),this.isRecording=!0)}};var W={buildKeyMap:function(){},getRegisterController:function(){return P.registerController},resetVimGlobalState_:F,getVimGlobalState_:function(){return P},maybeInitVimState_:D,suppressErrorLogging:!1,InsertModeKey:Qe,map:function(e,t,n){Ve.map(e,t,n)},unmap:function(e,t){Ve.unmap(e,t)},setOption:O,getOption:E,defineOption:A,defineEx:function(e,t,n){if(t){if(0!==e.indexOf(t))throw new Error('(Vim.defineEx) "'+t+'" is not a prefix of "'+e+'", command not registered')}else t=e;Ue[e]=n,Ve.commandMap_[t]={name:e,shortName:t,type:"api"}},handleKey:function(e,t,n){var r=this.findKey(e,t,n);if("function"==typeof r)return r()},findKey:function(n,r,i){var o,a=D(n);function l(){var e=P.macroModeState;if(e.isRecording){if("q"==r)return e.exitMacroRecordMode(),_(n),!0;"mapping"!=i&&function(e,t){if(!e.isPlaying){var n=e.latestRegister,r=P.registerController.getRegister(n);r&&r.pushText(t)}}(e,r)}}function s(){if(""==r)return _(n),a.visualMode?pe(n):a.insertMode&&qe(n),!0}return!1===(o=a.insertMode?function(){if(s())return!0;for(var e=a.inputState.keyBuffer=a.inputState.keyBuffer+r,i=1==r.length,o=U.matchCommand(e,t,a.inputState,"insert");e.length>1&&"full"!=o.type;){var e=a.inputState.keyBuffer=e.slice(1),l=U.matchCommand(e,t,a.inputState,"insert");"none"!=l.type&&(o=l)}if("none"==o.type)return _(n),!1;if("partial"==o.type)return N&&window.clearTimeout(N),N=window.setTimeout(function(){a.insertMode&&a.inputState.keyBuffer&&_(n)},E("insertModeEscKeysTimeout")),!i;if(N&&window.clearTimeout(N),i){for(var c=n.listSelections(),u=0;u|<\w+>|./.exec(t),r=i[0],t=t.substring(i.index+r.length),e.Vim.handleKey(n,r,"mapping")}(o.toKeys):U.processCommand(n,a,o)}catch(t){throw n.state.vim=void 0,D(n),e.Vim.suppressErrorLogging||console.log(t),t}return!0})}},handleEx:function(e,t){Ve.processCommand(e,t)},defineMotion:function(e,t){V[e]=t},defineAction:function(e,t){G[e]=t},defineOperator:function(e,t){$[e]=t},mapCommand:function(e,t,n,r,i){var o={keys:e,type:t};for(var a in o[t]=n,o[t+"Args"]=r,i)o[a]=i[a];$e(o)},_mapCommand:$e,defineRegister:function(e,t){var n=P.registerController.registers;if(!e||1!=e.length)throw Error("Register name must be 1 character");if(n[e])throw Error("Register already defined "+e);n[e]=t,w.push(e)},exitVisualMode:pe,exitInsertMode:qe};function z(){this.prefixRepeat=[],this.motionRepeat=[],this.operator=null,this.operatorArgs=null,this.motion=null,this.motionArgs=null,this.keyBuffer=[],this.registerName=null}function _(t,n){t.state.vim.inputState=new z,e.signal(t,"vim-command-done",n)}function H(e,t,n){this.clear(),this.keyBuffer=[e||""],this.insertModeChanges=[],this.searchQueries=[],this.linewise=!!t,this.blockwise=!!n}function K(e){this.registers=e,this.unnamedRegister=e['"']=new H,e["."]=new H,e[":"]=new H,e["/"]=new H}function j(){this.historyBuffer=[],this.iterator=0,this.initialPrefix=null}z.prototype.pushRepeatDigit=function(e){this.operator?this.motionRepeat=this.motionRepeat.concat(e):this.prefixRepeat=this.prefixRepeat.concat(e)},z.prototype.getRepeat=function(){var e=0;return(this.prefixRepeat.length>0||this.motionRepeat.length>0)&&(e=1,this.prefixRepeat.length>0&&(e*=parseInt(this.prefixRepeat.join(""),10)),this.motionRepeat.length>0&&(e*=parseInt(this.motionRepeat.join(""),10))),e},H.prototype={setText:function(e,t,n){this.keyBuffer=[e||""],this.linewise=!!t,this.blockwise=!!n},pushText:function(e,t){t&&(this.linewise||this.keyBuffer.push("\n"),this.linewise=!0),this.keyBuffer.push(e)},pushInsertModeChanges:function(e){this.insertModeChanges.push(R(e))},pushSearchQuery:function(e){this.searchQueries.push(e)},clear:function(){this.keyBuffer=[],this.insertModeChanges=[],this.searchQueries=[],this.linewise=!1},toString:function(){return this.keyBuffer.join("")}},K.prototype={pushText:function(e,t,n,r,i){r&&"\n"!==n.charAt(n.length-1)&&(n+="\n");var o=this.isValidRegister(e)?this.getRegister(e):null;if(o){var a=C(e);a?o.pushText(n,r):o.setText(n,r,i),this.unnamedRegister.setText(o.toString(),r)}else{switch(t){case"yank":this.registers[0]=new H(n,r,i);break;case"delete":case"change":-1==n.indexOf("\n")?this.registers["-"]=new H(n,r):(this.shiftNumericRegisters_(),this.registers[1]=new H(n,r))}this.unnamedRegister.setText(n,r,i)}},getRegister:function(e){return this.isValidRegister(e)?(e=e.toLowerCase(),this.registers[e]||(this.registers[e]=new H),this.registers[e]):this.unnamedRegister},isValidRegister:function(e){return e&&M(e,w)},shiftNumericRegisters_:function(){for(var e=9;e>=2;e--)this.registers[e]=this.getRegister(""+(e-1))}},j.prototype={nextMatch:function(e,t){var n=this.historyBuffer,r=t?-1:1;null===this.initialPrefix&&(this.initialPrefix=e);for(var i=this.iterator+r;t?i>=0:i=n.length?(this.iterator=n.length,this.initialPrefix):i<0?e:void 0},pushInput:function(e){var t=this.historyBuffer.indexOf(e);t>-1&&this.historyBuffer.splice(t,1),e.length&&this.historyBuffer.push(e)},reset:function(){this.initialPrefix=null,this.iterator=this.historyBuffer.length}};var U={matchCommand:function(e,t,n,r){var i,o=function(e,t,n,r){for(var i,o=[],a=[],l=0;l"==i.keys.slice(-11)){var s=function(e){var t=/^.*(<[^>]+>)$/.exec(e),n=t?t[1]:e.slice(-1);if(n.length>1)switch(n){case"":n="\n";break;case"":n=" ";break;default:n=""}return n}(e);if(!s)return{type:"none"};n.selectedCharacter=s}return{type:"full",command:i}},processCommand:function(e,t,n){switch(t.inputState.repeatOverride=n.repeatOverride,n.type){case"motion":this.processMotion(e,t,n);break;case"operator":this.processOperator(e,t,n);break;case"operatorMotion":this.processOperatorMotion(e,t,n);break;case"action":this.processAction(e,t,n);break;case"search":this.processSearch(e,t,n);break;case"ex":case"keyToEx":this.processEx(e,t,n)}},processMotion:function(e,t,n){t.inputState.motion=n.motion,t.inputState.motionArgs=Y(n.motionArgs),this.evalInput(e,t)},processOperator:function(e,t,n){var r=t.inputState;if(r.operator){if(r.operator==n.operator)return r.motion="expandToLine",r.motionArgs={linewise:!0},void this.evalInput(e,t);_(e)}r.operator=n.operator,r.operatorArgs=Y(n.operatorArgs),t.visualMode&&this.evalInput(e,t)},processOperatorMotion:function(e,t,n){var r=t.visualMode,i=Y(n.operatorMotionArgs);i&&r&&i.visualLine&&(t.visualLine=!0),this.processOperator(e,t,n),r||this.processMotion(e,t,n)},processAction:function(e,t,n){var r=t.inputState,i=r.getRepeat(),o=!!i,a=Y(n.actionArgs)||{};r.selectedCharacter&&(a.selectedCharacter=r.selectedCharacter),n.operator&&this.processOperator(e,t,n),n.motion&&this.processMotion(e,t,n),(n.motion||n.operator)&&this.evalInput(e,t),a.repeat=i||1,a.repeatIsExplicit=o,a.registerName=r.registerName,_(e),t.lastMotion=null,n.isEdit&&this.recordLastEdit(t,r,n),G[n.action](e,a,t)},processSearch:function(t,n,r){if(t.getSearchCursor){var i=r.searchArgs.forward,o=r.searchArgs.wholeWordOnly;Te(t).setReversed(!i);var a=i?"/":"?",l=Te(t).getQuery(),s=t.getScrollInfo();switch(r.searchArgs.querySrc){case"prompt":var c=P.macroModeState;if(c.isPlaying){var u=c.replaySearchQueries.shift();h(u,!0,!1)}else De(t,{onClose:function(e){t.scrollTo(s.left,s.top),h(e,!0,!0);var n=P.macroModeState;n.isRecording&&function(e,t){if(!e.isPlaying){var n=e.latestRegister,r=P.registerController.getRegister(n);r&&r.pushSearchQuery&&r.pushSearchQuery(t)}}(n,e)},prefix:a,desc:Be,onKeyUp:function(n,r,o){var a,l,c,u=e.keyName(n);"Up"==u||"Down"==u?(a="Up"==u,l=n.target?n.target.selectionEnd:0,r=P.searchHistoryController.nextMatch(r,a)||"",o(r),l&&n.target&&(n.target.selectionEnd=n.target.selectionStart=Math.min(l,n.target.value.length))):"Left"!=u&&"Right"!=u&&"Ctrl"!=u&&"Alt"!=u&&"Shift"!=u&&P.searchHistoryController.reset();try{c=Fe(t,r,!0,!0)}catch(n){}c?t.scrollIntoView(ze(t,!i,c),30):(_e(t),t.scrollTo(s.left,s.top))},onKeyDown:function(n,r,i){var o=e.keyName(n);"Esc"==o||"Ctrl-C"==o||"Ctrl-["==o||"Backspace"==o&&""==r?(P.searchHistoryController.pushInput(r),P.searchHistoryController.reset(),Fe(t,l),_e(t),t.scrollTo(s.left,s.top),e.e_stop(n),_(t),i(),t.focus()):"Up"==o||"Down"==o?e.e_stop(n):"Ctrl-U"==o&&(e.e_stop(n),i(""))}});break;case"wordUnderCursor":var f=ge(t,!1,0,!1,!0),d=!0;if(f||(f=ge(t,!1,0,!1,!1),d=!1),!f)return;var u=t.getLine(f.start.line).substring(f.start.ch,f.end.ch);u=d&&o?"\\b"+u+"\\b":u.replace(/([.?*+$\[\]\/\\(){}|\-])/g,"\\$1"),P.jumpList.cachedCursor=t.getCursor(),t.setCursor(f.start),h(u,!0,!1)}}function h(e,i,o){P.searchHistoryController.pushInput(e),P.searchHistoryController.reset();try{Fe(t,e,i,o)}catch(n){return Re(t,"Invalid regex: "+e),void _(t)}U.processMotion(t,n,{type:"motion",motion:"findNext",motionArgs:{forward:!0,toJumplist:r.searchArgs.toJumplist}})}},processEx:function(t,n,r){function i(e){P.exCommandHistoryController.pushInput(e),P.exCommandHistoryController.reset(),Ve.processCommand(t,e)}function o(n,r,i){var o,a,l=e.keyName(n);("Esc"==l||"Ctrl-C"==l||"Ctrl-["==l||"Backspace"==l&&""==r)&&(P.exCommandHistoryController.pushInput(r),P.exCommandHistoryController.reset(),e.e_stop(n),_(t),i(),t.focus()),"Up"==l||"Down"==l?(e.e_stop(n),o="Up"==l,a=n.target?n.target.selectionEnd:0,r=P.exCommandHistoryController.nextMatch(r,o)||"",i(r),a&&n.target&&(n.target.selectionEnd=n.target.selectionStart=Math.min(a,n.target.value.length))):"Ctrl-U"==l?(e.e_stop(n),i("")):"Left"!=l&&"Right"!=l&&"Ctrl"!=l&&"Alt"!=l&&"Shift"!=l&&P.exCommandHistoryController.reset()}"keyToEx"==r.type?Ve.processCommand(t,r.exArgs.input):n.visualMode?De(t,{onClose:i,prefix:":",value:"'<,'>",onKeyDown:o,selectValueOnOpen:!1}):De(t,{onClose:i,prefix:":",onKeyDown:o})},evalInput:function(e,t){var n,i,o,a=t.inputState,l=a.motion,s=a.motionArgs||{},c=a.operator,u=a.operatorArgs||{},f=a.registerName,d=t.sel,h=ee(t.visualMode?X(e,d.head):e.getCursor("head")),p=ee(t.visualMode?X(e,d.anchor):e.getCursor("anchor")),m=ee(h),g=ee(p);if(c&&this.recordLastEdit(t,a),(o=void 0!==a.repeatOverride?a.repeatOverride:a.getRepeat())>0&&s.explicitRepeat?s.repeatIsExplicit=!0:(s.noRepeat||!s.explicitRepeat&&0===o)&&(o=1,s.repeatIsExplicit=!1),a.selectedCharacter&&(s.selectedCharacter=u.selectedCharacter=a.selectedCharacter),s.repeat=o,_(e),l){var v=V[l](e,h,s,t);if(t.lastMotion=V[l],!v)return;if(s.toJumplist){var y=P.jumpList,b=y.cachedCursor;b?(ve(e,b,v),delete y.cachedCursor):ve(e,h,v)}v instanceof Array?(i=v[0],n=v[1]):n=v,n||(n=ee(h)),t.visualMode?(t.visualBlock&&n.ch===1/0||(n=X(e,n,t.visualBlock)),i&&(i=X(e,i,!0)),i=i||g,d.anchor=i,d.head=n,de(e),Ce(e,t,"<",ne(i,n)?i:n),Ce(e,t,">",ne(i,n)?n:i)):c||(n=X(e,n),e.setCursor(n.line,n.ch))}if(c){if(u.lastSel){i=g;var w=u.lastSel,x=Math.abs(w.head.line-w.anchor.line),k=Math.abs(w.head.ch-w.anchor.ch);n=w.visualLine?r(g.line+x,g.ch):w.visualBlock?r(g.line+x,g.ch+k):w.head.line==w.anchor.line?r(g.line,g.ch+k):r(g.line+x,g.ch),t.visualMode=!0,t.visualLine=w.visualLine,t.visualBlock=w.visualBlock,d=t.sel={anchor:i,head:n},de(e)}else t.visualMode&&(u.lastSel={anchor:ee(d.anchor),head:ee(d.head),visualBlock:t.visualBlock,visualLine:t.visualLine});var C,L,M,T,A;if(t.visualMode){if(C=re(d.head,d.anchor),L=ie(d.head,d.anchor),M=t.visualLine||u.linewise,T=t.visualBlock?"block":M?"line":"char",A=he(e,{anchor:C,head:L},T),M){var O=A.ranges;if("block"==T)for(var E=0;E0&&o&&S(o);o=i.pop())n.line--,n.ch=0;o?(n.line--,n.ch=ae(e,n.line)):n.ch=0}}(e,C,L),T="char";var I=!s.inclusive||M;A=he(e,{anchor:C,head:L},T,I)}e.setSelections(A.ranges,A.primary),t.lastMotion=null,u.repeat=o,u.registerName=f,u.linewise=M;var R=$[c](e,u,A.ranges,g,n);t.visualMode&&pe(e,null!=R),R&&e.setCursor(R)}},recordLastEdit:function(e,t,n){var r=P.macroModeState;r.isPlaying||(e.lastEditInputState=t,e.lastEditActionCommand=n,r.lastInsertModeChanges.changes=[],r.lastInsertModeChanges.expectCursorActivityForChange=!1)}},V={moveToTopLine:function(e,t,n){var i=He(e).top+n.repeat-1;return r(i,me(e.getLine(i)))},moveToMiddleLine:function(e){var t=He(e),n=Math.floor(.5*(t.top+t.bottom));return r(n,me(e.getLine(n)))},moveToBottomLine:function(e,t,n){var i=He(e).bottom-n.repeat+1;return r(i,me(e.getLine(i)))},expandToLine:function(e,t,n){var i=t;return r(i.line+n.repeat-1,1/0)},findNext:function(e,t,n){var r=Te(e),i=r.getQuery();if(i){var o=!n.forward;return o=r.isReversed()?!o:o,We(e,i),ze(e,o,i,n.repeat)}},goToMark:function(e,t,n,r){var i=Ke(e,r,n.selectedCharacter);return i?n.linewise?{line:i.line,ch:me(e.getLine(i.line))}:i:null},moveToOtherHighlightedEnd:function(e,t,n,i){if(i.visualBlock&&n.sameLine){var o=i.sel;return[X(e,r(o.anchor.line,o.head.ch)),X(e,r(o.head.line,o.anchor.ch))]}return[i.sel.head,i.sel.anchor]},jumpToMark:function(e,t,n,i){for(var o=t,a=0;au&&o.line==u?this.moveToEol(e,t,n,i):(n.toFirstChar&&(a=me(e.getLine(s)),i.lastHPos=a),i.lastHSPos=e.charCoords(r(s,a),"div").left,r(s,a))},moveByDisplayLines:function(e,t,n,i){var o=t;switch(i.lastMotion){case this.moveByDisplayLines:case this.moveByScroll:case this.moveByLines:case this.moveToColumn:case this.moveToEol:break;default:i.lastHSPos=e.charCoords(o,"div").left}var a=n.repeat,l=e.findPosV(o,n.forward?a:-a,"line",i.lastHSPos);if(l.hitSide)if(n.forward)var s=e.charCoords(l,"div"),c={top:s.top+8,left:i.lastHSPos},l=e.coordsChar(c,"div");else{var u=e.charCoords(r(e.firstLine(),0),"div");u.left=i.lastHSPos,l=e.coordsChar(u,"div")}return i.lastHPos=l.ch,l},moveByPage:function(e,t,n){var r=t,i=n.repeat;return e.findPosV(r,n.forward?i:-i,"page")},moveByParagraph:function(e,t,n){var r=n.forward?1:-1;return Le(e,t,n.repeat,r)},moveBySentence:function(e,t,n){var i=n.forward?1:-1;return function(e,t,n,i){function o(e,t){if(t.pos+t.dir<0||t.pos+t.dir>=t.line.length){if(t.ln+=t.dir,!x(e,t.ln))return t.line=null,t.ln=null,void(t.pos=null);t.line=e.getLine(t.ln),t.pos=t.dir>0?0:t.line.length-1}else t.pos+=t.dir}function a(e,t,n,r){var i=e.getLine(t),a=""===i,l={line:i,ln:t,pos:n,dir:r},s={ln:l.ln,pos:l.pos},c=""===l.line;for(o(e,l);null!==l.line;){if(s.ln=l.ln,s.pos=l.pos,""===l.line&&!c)return{ln:l.ln,pos:l.pos};if(a&&""!==l.line&&!S(l.line[l.pos]))return{ln:l.ln,pos:l.pos};!L(l.line[l.pos])||a||l.pos!==l.line.length-1&&!S(l.line[l.pos+1])||(a=!0),o(e,l)}var i=e.getLine(s.ln);s.pos=0;for(var u=i.length-1;u>=0;--u)if(!S(i[u])){s.pos=u;break}return s}function l(e,t,n,r){var i=e.getLine(t),a={line:i,ln:t,pos:n,dir:r},l={ln:a.ln,pos:null},s=""===a.line;for(o(e,a);null!==a.line;){if(""===a.line&&!s)return null!==l.pos?l:{ln:a.ln,pos:a.pos};if(L(a.line[a.pos])&&null!==l.pos&&(a.ln!==l.ln||a.pos+1!==l.pos))return l;""===a.line||S(a.line[a.pos])||(s=!1,l={ln:a.ln,pos:a.pos}),o(e,a)}var i=e.getLine(l.ln);l.pos=0;for(var c=0;c0;)s=i<0?l(e,s.ln,s.pos,i):a(e,s.ln,s.pos,i),n--;return r(s.ln,s.pos)}(e,t,n.repeat,i)},moveByScroll:function(e,t,n,r){var i=e.getScrollInfo(),o=null,a=n.repeat;a||(a=i.clientHeight/(2*e.defaultTextHeight()));var l=e.charCoords(t,"local");n.repeat=a;var o=V.moveByDisplayLines(e,t,n,r);if(!o)return null;var s=e.charCoords(o,"local");return e.scrollTo(null,i.top+s.top-l.top),o},moveByWords:function(e,t,n){return function(e,t,n,i,o,a){var l=ee(t),s=[];(i&&!o||!i&&o)&&n++;for(var c=!(i&&o),u=0;u0)f.index=0;else{var m=f.lineText.length;f.index=m>0?m-1:0}f.nextCh=f.lineText.charAt(f.index)}p(f)&&(o.line=c,o.ch=f.index,t--)}return f.nextCh||f.curMoveThrough?r(c,f.index):o}(e,i,n.forward,n.selectedCharacter)||t},moveToColumn:function(e,t,n,i){var o=n.repeat;return i.lastHPos=o-1,i.lastHSPos=e.charCoords(t,"div").left,function(e,t){var n=e.getCursor().line;return X(e,r(n,t-1))}(e,o)},moveToEol:function(e,t,n,i){var o=t;i.lastHPos=1/0;var a=r(o.line+n.repeat-1,1/0),l=e.clipPos(a);return l.ch--,i.lastHSPos=e.charCoords(l,"div").left,a},moveToFirstNonWhiteSpaceCharacter:function(e,t){var n=t;return r(n.line,me(e.getLine(n.line)))},moveToMatchedSymbol:function(e,t){for(var n,i=t,o=i.line,a=i.ch,l=e.getLine(o);aa.ch||o.line>a.line){var f=o;o=a,a=f}return i?a.ch+=1:o.ch+=1,{start:o,end:a}}(e,t,o,l);else if({"'":!0,'"':!0}[o])a=function(e,t,n,i){var o,a,l,s,c=ee(t),u=e.getLine(c.line).split(""),f=u.indexOf(n);if(c.ch-1&&!o;l--)u[l]==n&&(o=l+1);else o=c.ch+1;if(o&&!a)for(l=o,s=u.length;lt.lastLine()&&n.linewise&&!p?t.replaceRange("",h,u):t.replaceRange("",c,u),n.linewise&&(p||(t.setCursor(h),e.commands.newlineAndIndent(t)),c.ch=Number.MAX_VALUE),o=c}P.registerController.pushText(n.registerName,"change",a,n.linewise,i.length>1),G.enterInsertMode(t,{head:o},t.state.vim)},delete:function(e,t,n){var i,o,a=e.state.vim;if(a.visualBlock){o=e.getSelection();var l=q("",n.length);e.replaceSelections(l),i=n[0].anchor}else{var s=n[0].anchor,c=n[0].head;t.linewise&&c.line!=e.firstLine()&&s.line==e.lastLine()&&s.line==c.line-1&&(s.line==e.firstLine()?s.ch=0:s=r(s.line-1,ae(e,s.line-1))),o=e.getRange(s,c),e.replaceRange("",s,c),i=s,t.linewise&&(i=V.moveToFirstNonWhiteSpaceCharacter(e,s))}P.registerController.pushText(t.registerName,"delete",o,t.linewise,a.visualBlock);var u=a.insertMode;return X(e,i,u)},indent:function(e,t,n){var r=e.state.vim,i=n[0].anchor.line,o=r.visualBlock?n[n.length-1].anchor.line:n[0].head.line,a=r.visualMode?t.repeat:1;t.linewise&&o--;for(var l=i;l<=o;l++)for(var s=0;sc.top?(s.line+=(l-c.top)/i,s.line=Math.ceil(s.line),e.setCursor(s),c=e.charCoords(s,"local"),e.scrollTo(null,c.top)):e.scrollTo(null,l);else{var u=l+e.getScrollInfo().clientHeight;u=a.anchor.line?J(a.head,0,1):r(a.anchor.line,0);else if("inplace"==o&&i.visualMode)return;t.setOption("disableInput",!1),n&&n.replace?(t.toggleOverwrite(!0),t.setOption("keyMap","vim-replace"),e.signal(t,"vim-mode-change",{mode:"replace"})):(t.toggleOverwrite(!1),t.setOption("keyMap","vim-insert"),e.signal(t,"vim-mode-change",{mode:"insert"})),P.macroModeState.isPlaying||(t.on("change",Xe),e.on(t.getInputField(),"keydown",Ze)),i.visualMode&&pe(t),ue(t,l,s)}},toggleVisualMode:function(t,n,i){var o,a=n.repeat,l=t.getCursor();i.visualMode?i.visualLine^n.linewise||i.visualBlock^n.blockwise?(i.visualLine=!!n.linewise,i.visualBlock=!!n.blockwise,e.signal(t,"vim-mode-change",{mode:"visual",subMode:i.visualLine?"linewise":i.visualBlock?"blockwise":""}),de(t)):pe(t):(i.visualMode=!0,i.visualLine=!!n.linewise,i.visualBlock=!!n.blockwise,o=X(t,r(l.line,l.ch+a-1),!0),i.sel={anchor:l,head:o},e.signal(t,"vim-mode-change",{mode:"visual",subMode:i.visualLine?"linewise":i.visualBlock?"blockwise":""}),de(t),Ce(t,i,"<",re(l,o)),Ce(t,i,">",ie(l,o)))},reselectLastSelection:function(t,n,r){var i=r.lastSelection;if(r.visualMode&&fe(t,r),i){var o=i.anchorMark.find(),a=i.headMark.find();if(!o||!a)return;r.sel={anchor:o,head:a},r.visualMode=!0,r.visualLine=i.visualLine,r.visualBlock=i.visualBlock,de(t),Ce(t,r,"<",re(o,a)),Ce(t,r,">",ie(o,a)),e.signal(t,"vim-mode-change",{mode:"visual",subMode:r.visualLine?"linewise":r.visualBlock?"blockwise":""})}},joinLines:function(e,t,n){var i,o;if(n.visualMode){if(i=e.getCursor("anchor"),ne(o=e.getCursor("head"),i)){var a=o;o=i,i=a}o.ch=ae(e,o.line)-1}else{var l=Math.max(t.repeat,2);i=e.getCursor(),o=X(e,r(i.line+l-1,1/0))}for(var s=0,c=i.line;c1)var a=Array(t.repeat+1).join(a);var p,m,g=o.linewise,v=o.blockwise;if(g)n.visualMode?a=n.visualLine?a.slice(0,-1):"\n"+a.slice(0,a.length-1)+"\n":t.after?(a="\n"+a.slice(0,a.length-1),i.ch=ae(e,i.line)):i.ch=0;else{if(v){a=a.split("\n");for(var y=0;ye.lastLine()&&e.replaceRange("\n",r(M,0));var T=ae(e,M);Tu.length&&(o=u.length),a=r(s.line,o)}if("\n"==l)i.visualMode||t.replaceRange("",s,a),(e.commands.newlineAndIndentContinueComment||e.commands.newlineAndIndent)(t);else{var f=t.getRange(s,a);if(f=f.replace(/[^\n]/g,l),i.visualBlock){var d=new Array(t.getOption("tabSize")+1).join(" ");f=(f=t.getSelection()).replace(/\t/g,d).replace(/[^\n]/g,l).split("\n"),t.replaceSelections(f)}else t.replaceRange(f,s,a);i.visualMode?(s=ne(c[0].anchor,c[0].head)?c[0].anchor:c[0].head,t.setCursor(s),pe(t,!1)):t.setCursor(J(a,0,-1))}},incrementNumberToken:function(e,t){for(var n,i,o,a,l=e.getCursor(),s=e.getLine(l.line),c=/(-?)(?:(0x)([\da-f]+)|(0b|0|)(\d+))/gi;null!==(n=c.exec(s))&&(i=n.index,o=i+n[0].length,!(l.ch"==t.slice(-11)){var n=t.length-11,r=e.slice(0,n),i=t.slice(0,n);return r==i&&e.length>n?"full":0==i.indexOf(r)&&"partial"}return e==t?"full":0==t.indexOf(e)&&"partial"}function Z(e,t,n){return function(){for(var r=0;r2&&(t=re.apply(void 0,Array.prototype.slice.call(arguments,1))),ne(e,t)?e:t}function ie(e,t){return arguments.length>2&&(t=ie.apply(void 0,Array.prototype.slice.call(arguments,1))),ne(e,t)?t:e}function oe(e,t,n){var r=ne(e,t),i=ne(t,n);return r&&i}function ae(e,t){return e.getLine(t).length}function le(e){return e.trim?e.trim():e.replace(/^\s+|\s+$/g,"")}function se(e,t,n){var i=ae(e,t),o=new Array(n-i+1).join(" ");e.setCursor(r(t,i)),e.replaceRange(o,e.getCursor())}function ce(e,t){var n=[],i=e.listSelections(),o=ee(e.clipPos(t)),a=!te(t,o),l=e.getCursor("head"),s=function(e,t,n){for(var r=0;rs?u:0,d=i[f].anchor,h=Math.min(d.line,o.line),p=Math.max(d.line,o.line),m=d.ch,g=o.ch,v=i[f].head.ch-m,y=g-m;v>0&&y<=0?(m++,a||g--):v<0&&y>=0?(m--,c||g++):v<0&&-1==y&&(m--,g++);for(var b=h;b<=p;b++){var w={anchor:new r(b,m),head:new r(b,g)};n.push(w)}return e.setSelections(n),t.ch=g,d.ch=m,d}function ue(e,t,n){for(var r=[],i=0;ic&&(o.line=c),o.ch=ae(e,o.line)}return{ranges:[{anchor:a,head:o}],primary:0}}if("block"==n){for(var u=Math.min(a.line,o.line),f=Math.min(a.ch,o.ch),d=Math.max(a.line,o.line),h=Math.max(a.ch,o.ch)+1,p=d-u+1,m=o.line==u?0:p-1,g=[],v=0;v=l.length)return null;i?c=p[0]:(c=h[0])(l.charAt(s))||(c=h[1]);for(var u=s,f=s;c(l.charAt(u))&&u=0;)f--;if(f++,t){for(var d=u;/\s/.test(l.charAt(u))&&u0;)f--;f||(f=m)}}return{start:r(a.line,f),end:r(a.line,u)}}function ve(e,t,n){te(t,n)||P.jumpList.add(e,t,n)}function ye(e,t){P.lastCharacterSearch.increment=e,P.lastCharacterSearch.forward=t.forward,P.lastCharacterSearch.selectedCharacter=t.selectedCharacter}var be={"(":"bracket",")":"bracket","{":"bracket","}":"bracket","[":"section","]":"section","*":"comment","/":"comment",m:"method",M:"method","#":"preprocess"},we={bracket:{isComplete:function(e){if(e.nextCh===e.symb){if(e.depth++,e.depth>=1)return!0}else e.nextCh===e.reverseSymb&&e.depth--;return!1}},section:{init:function(e){e.curMoveThrough=!0,e.symb=(e.forward?"]":"[")===e.symb?"{":"}"},isComplete:function(e){return 0===e.index&&e.nextCh===e.symb}},comment:{isComplete:function(e){var t="*"===e.lastCh&&"/"===e.nextCh;return e.lastCh=e.nextCh,t}},method:{init:function(e){e.symb="m"===e.symb?"{":"}",e.reverseSymb="{"===e.symb?"}":"{"},isComplete:function(e){return e.nextCh===e.symb}},preprocess:{init:function(e){e.index=0},isComplete:function(e){if("#"===e.nextCh){var t=e.lineText.match(/#(\w+)/)[1];if("endif"===t){if(e.forward&&0===e.depth)return!0;e.depth++}else if("if"===t){if(!e.forward&&0===e.depth)return!0;e.depth--}if("else"===t&&0===e.depth)return!0}return!1}}};function xe(e,t,n,r,i){var o=t.line,a=t.ch,l=e.getLine(o),s=n?1:-1,c=r?p:h;if(i&&""==l){if(o+=s,l=e.getLine(o),!x(e,o))return null;a=n?0:l.length}for(;;){if(i&&""==l)return{from:0,to:0,line:o};for(var u=s>0?l.length:-1,f=u,d=u;a!=u;){for(var m=!1,g=0;g0?0:l.length}}function ke(e,t,n,i){for(var o,a=e.getCursor(),l=a.ch,s=0;s0;)d(u,i)&&n--,u+=i;return new r(u,0)}var h=e.state.vim;if(h.visualLine&&d(l,1,!0)){var p=h.sel.anchor;d(p.line,-1,!0)&&(o&&p.line==l||(l+=1))}var m=f(l);for(u=l;u<=c&&n;u++)d(u,1,!0)&&(o&&f(u)==m||n--);for(a=new r(u,0),u>c&&!m?m=!0:o=!1,u=l;u>s&&(o&&f(u)!=m&&u!=l||!d(u,-1,!0));u--);return{start:new r(u,0),end:a}}function Me(){}function Te(e){var t=e.state.vim;return t.searchState_||(t.searchState_=new Me)}function Ae(e,t,n,r,i){e.openDialog?e.openDialog(t,r,{bottom:!0,value:i.value,onKeyDown:i.onKeyDown,onKeyUp:i.onKeyUp,selectValueOnOpen:!1}):r(prompt(n,""))}function Oe(e,t){var n=Ee(e,t)||[];if(!n.length)return[];var r=[];if(0===n[0]){for(var i=0;i'+t+"",{bottom:!0,duration:5e3}):alert(t)}var Be="(Javascript regexp)";function De(e,t){var n,r,i,o=(t.prefix||"")+" "+(t.desc||""),a=(n=t.prefix,r=t.desc,i=''+(n||"")+'',r&&(i+=' '+r+""),i);Ae(e,a,o,t.onClose,t)}function Fe(e,t,n,r){if(t){var i=Te(e),o=Ie(t,!!n,!!r);if(o)return We(e,o),function(e,t){if(e instanceof RegExp&&t instanceof RegExp){for(var n=["global","multiline","ignoreCase","source"],r=0;r0;t--){var n=e.substring(0,t);if(this.commandMap_[n]){var r=this.commandMap_[n];if(0===r.name.indexOf(e))return r}}return null},buildCommandMap_:function(){this.commandMap_={};for(var e=0;e
";if(n){n=n.join("");for(var o=0;o"}}else for(var l in r){var s=r[l].toString();s.length&&(i+='"'+l+" "+s+"
")}Re(e,i)},sort:function(t,n){var i,o,a,l,s,c=function(){if(n.argString){var t=new e.StringStream(n.argString);if(t.eat("!")&&(i=!0),t.eol())return;if(!t.eatSpace())return"Invalid arguments";var r=t.match(/([dinuox]+)?\s*(\/.+\/)?\s*/);if(!r&&!t.eol())return"Invalid arguments";if(r[1]){o=-1!=r[1].indexOf("i"),a=-1!=r[1].indexOf("u");var c=-1!=r[1].indexOf("d")||-1!=r[1].indexOf("n")&&1,u=-1!=r[1].indexOf("x")&&1,f=-1!=r[1].indexOf("o")&&1;if(c+u+f>1)return"Invalid arguments";l=(c?"decimal":u&&"hex")||f&&"octal"}r[2]&&(s=new RegExp(r[2].substr(1,r[2].length-2),o?"i":""))}}();if(c)Re(t,c+": "+n.argString);else{var u=n.line||t.firstLine(),f=n.lineEnd||n.line||t.lastLine();if(u!=f){var d=r(u,0),h=r(f,ae(t,f)),p=t.getRange(d,h).split("\n"),m=s||("decimal"==l?/(-?)([\d]+)/:"hex"==l?/(-?)(?:0x)?([0-9a-f]+)/i:"octal"==l?/([0-7]+)/:null),g="decimal"==l?10:"hex"==l?16:"octal"==l?8:null,v=[],y=[];if(l||s)for(var b=0;b")}if(r){var h=0,p=function(){if(h=n&&e<=l:e==n);)if(r||!f||a.from().line!=f.line)return t.scrollIntoView(a.from(),30),t.setSelection(a.from(),a.to()),f=a.from(),void(u=!1);var e,n,l;u=!0}function m(e){if(e&&e(),t.focus(),f){t.setCursor(f);var n=t.state.vim;n.exMode=!1,n.lastHPos=n.lastHSPos=f.ch}c&&c()}if(p(),!u)return n?void De(t,{prefix:"replace with "+s+" (y/n/a/q/l)",onKeyDown:function(n,r,i){switch(e.e_stop(n),e.keyName(n)){case"Y":h(),p();break;case"N":p();break;case"A":var o=c;c=void 0,t.operation(d),c=o;break;case"L":h();case"Q":case"Esc":case"Ctrl-C":case"Ctrl-[":m(i)}return u&&m(i),!0}}):(d(),void(c&&c()));Re(t,"No matches for "+l.source)}(t,f,h,g,v,b,m,u,n.callback)}else Re(t,"No previous substitute regular expression")},redo:e.commands.redo,undo:e.commands.undo,write:function(t){e.commands.save?e.commands.save(t):t.save&&t.save()},nohlsearch:function(e){_e(e)},yank:function(e){var t=ee(e.getCursor()),n=t.line,r=e.getLine(n);P.registerController.pushText("0","yank",r,!0,!0)},delmarks:function(t,n){if(n.argString&&le(n.argString))for(var r=t.state.vim,i=new e.StringStream(le(n.argString));!i.eol();){i.eatSpace();var o=i.pos;if(!i.match(/[a-zA-Z]/,!1))return void Re(t,"Invalid argument: "+n.argString.substring(o));var a=i.next();if(i.match("-",!0)){if(!i.match(/[a-zA-Z]/,!1))return void Re(t,"Invalid argument: "+n.argString.substring(o));var l=a,s=i.next();if(!(k(l)&&k(s)||C(l)&&C(s)))return void Re(t,"Invalid argument: "+l+"-");var c=l.charCodeAt(0),u=s.charCodeAt(0);if(c>=u)return void Re(t,"Invalid argument: "+n.argString.substring(o));for(var f=0;f<=u-c;f++){var d=String.fromCharCode(c+f);delete r.marks[d]}}else delete r.marks[a]}else Re(t,"Argument required")}},Ve=new je;function qe(t){var n=t.state.vim,r=P.macroModeState,i=P.registerController.getRegister("."),o=r.isPlaying,a=r.lastInsertModeChanges,l=[];if(!o){for(var s=a.inVisualBlock&&n.lastSelection?n.lastSelection.visualBlock.height:1,c=a.changes,l=[],u=0;u1&&(et(t,n,n.insertModeRepeat-1,!0),n.lastEditInputState.repeatOverride=n.insertModeRepeat),delete n.insertModeRepeat,n.insertMode=!1,t.setCursor(t.getCursor().line,t.getCursor().ch-1),t.setOption("keyMap","vim"),t.setOption("disableInput",!0),t.toggleOverwrite(!1),i.setText(a.changes.join("")),e.signal(t,"vim-mode-change",{mode:"normal"}),r.isRecording&&function(e){if(!e.isPlaying){var t=e.latestRegister,n=P.registerController.getRegister(t);n&&n.pushInsertModeChanges&&n.pushInsertModeChanges(e.lastInsertModeChanges)}}(r)}function $e(e){t.unshift(e)}function Ge(t,n,r,i){var o=P.registerController.getRegister(i);if(":"==i)return o.keyBuffer[0]&&Ve.processCommand(t,o.keyBuffer[0]),void(r.isPlaying=!1);var a=o.keyBuffer,l=0;r.isPlaying=!0,r.replaySearchQueries=o.searchQueries.slice(0);for(var s=0;s|<\w+>|./.exec(f),u=c[0],f=f.substring(c.index+u.length),e.Vim.handleKey(t,u,"macro"),n.insertMode){var d=o.insertModeChanges[l++].changes;P.macroModeState.lastInsertModeChanges.changes=d,tt(t,d,1),qe(t)}r.isPlaying=!1}function Xe(e,t){var n=P.macroModeState,r=n.lastInsertModeChanges;if(!n.isPlaying)for(;t;){if(r.expectCursorActivityForChange=!0,"+input"==t.origin||"paste"==t.origin||void 0===t.origin){var i=t.text.join("\n");r.maybeReset&&(r.changes=[],r.maybeReset=!1),e.state.overwrite&&!/\n/.test(i)?r.changes.push([i]):r.changes.push(i)}t=t.next}}function Ye(t){var n=t.state.vim;if(n.insertMode){var r=P.macroModeState;if(r.isPlaying)return;var i=r.lastInsertModeChanges;i.expectCursorActivityForChange?i.expectCursorActivityForChange=!1:i.maybeReset=!0}else t.curOp.isVimOp||function(t,n){var r=t.getCursor("anchor"),i=t.getCursor("head");if(n.visualMode&&!t.somethingSelected()?pe(t,!1):n.visualMode||n.insertMode||!t.somethingSelected()||(n.visualMode=!0,n.visualLine=!1,e.signal(t,"vim-mode-change",{mode:"visual"})),n.visualMode){var o=ne(i,r)?0:-1,a=ne(i,r)?-1:0;i=J(i,0,o),r=J(r,0,a),n.sel={anchor:r,head:i},Ce(t,n,"<",re(i,r)),Ce(t,n,">",ie(i,r))}else n.insertMode||(n.lastHPos=t.getCursor().ch)}(t,n);n.visualMode&&Je(t)}function Je(e){var t=e.state.vim,n=X(e,ee(t.sel.head)),r=J(n,0,1);t.fakeCursor&&t.fakeCursor.clear(),t.fakeCursor=e.markText(n,r,{className:"cm-animate-fat-cursor"})}function Qe(e){this.keyName=e}function Ze(t){var n=P.macroModeState,r=n.lastInsertModeChanges,i=e.keyName(t);i&&(-1==i.indexOf("Delete")&&-1==i.indexOf("Backspace")||e.lookupKey(i,"vim-insert",function(){return r.maybeReset&&(r.changes=[],r.maybeReset=!1),r.changes.push(new Qe(i)),!0}))}function et(e,t,n,r){var i=P.macroModeState;i.isPlaying=!0;var o=!!t.lastEditActionCommand,a=t.inputState;function l(){o?U.processAction(e,t,t.lastEditActionCommand):U.evalInput(e,t)}function s(n){if(i.lastInsertModeChanges.changes.length>0){n=t.lastEditActionCommand?n:1;var r=i.lastInsertModeChanges;tt(e,r.changes,n)}}if(t.inputState=t.lastEditInputState,o&&t.lastEditActionCommand.interlaceInsertRepeat)for(var c=0;c50&&r.shift()}function o(e){return r[r.length-(e?Math.min(e,1):1)]||""}var a=null;function l(e,t,o,l,s){null==s&&(s=e.getRange(t,o)),"grow"==l&&a&&a.cm==e&&n(t,a.pos)&&e.isClean(a.gen)?function(e){if(!r.length)return i(e);r[r.length-1]+=e}(s):!1!==l&&i(s),e.replaceRange("",t,o,"+delete"),a="grow"==l?{cm:e,pos:t,gen:e.changeGeneration()}:null}function s(e,t,n){return e.findPosH(t,n,"char",!0)}function c(e,t,n){return e.findPosH(t,n,"word",!0)}function u(e,t,n){return e.findPosV(t,n,"line",e.doc.sel.goalColumn)}function f(e,t,n){return e.findPosV(t,n,"page",e.doc.sel.goalColumn)}function d(e,n,r){for(var i=n.line,o=e.getLine(i),a=/\S/.test(r<0?o.slice(0,n.ch):o.slice(n.ch)),l=e.firstLine(),s=e.lastLine();;){if((i+=r)s)return e.clipPos(t(i-r,r<0?0:null));o=e.getLine(i);var c=/\S/.test(o);if(c)a=!0;else if(a)return t(i,0)}}function h(e,n,r){for(var i=n.line,o=n.ch,a=e.getLine(n.line),l=!1;;){var s=a.charAt(o+(r<0?-1:0));if(s){if(l&&/[!?.]/.test(s))return t(i,o+(r>0?1:0));l||(l=/\w/.test(s)),o+=r}else{if(i==(r<0?e.firstLine():e.lastLine()))return t(i,o);if(a=e.getLine(i+r),!/\S/.test(a))return t(i,o);i+=r,o=r<0?a.length:0}}}function p(e,r,i){var o;if(e.findMatchingBracket&&(o=e.findMatchingBracket(r,{strict:!0}))&&o.match&&(o.forward?1:-1)==i)return i>0?t(o.to.line,o.to.ch+1):o.to;for(var a=!0;;a=!1){var l=e.getTokenAt(r),s=t(r.line,i<0?l.start:l.end);if(!(a&&i>0&&l.end==r.ch)&&/\w/.test(l.string))return s;var c=e.findPosH(s,i,"char");if(n(s,c))return r;r=c}}function m(e,t){var n=e.state.emacsPrefix;return n?(S(e),"-"==n?-1:Number(n)):t?null:1}function g(e){var t="string"==typeof e?function(t){t.execCommand(e)}:e;return function(e){var n=m(e);t(e);for(var r=1;r1&&"+input"==t.origin){for(var r=t.text.join("\n"),i="",o=1;o1&&r.pop(),o()),"around","paste")},"Ctrl-Space":T,"Ctrl-Shift-2":T,"Ctrl-F":y(s,1),"Ctrl-B":y(s,-1),Right:y(s,1),Left:y(s,-1),"Ctrl-D":function(e){b(e,s,1,!1)},Delete:function(e){w(e,!1)||b(e,s,1,!1)},"Ctrl-H":function(e){b(e,s,-1,!1)},Backspace:function(e){w(e,!1)||b(e,s,-1,!1)},"Alt-F":y(c,1),"Alt-B":y(c,-1),"Alt-Right":y(c,1),"Alt-Left":y(c,-1),"Alt-D":function(e){b(e,c,1,"grow")},"Alt-Backspace":function(e){b(e,c,-1,"grow")},"Ctrl-N":y(u,1),"Ctrl-P":y(u,-1),Down:y(u,1),Up:y(u,-1),"Ctrl-A":"goLineStart","Ctrl-E":"goLineEnd",End:"goLineEnd",Home:"goLineStart","Alt-V":y(f,-1),"Ctrl-V":y(f,1),PageUp:y(f,-1),PageDown:y(f,1),"Ctrl-Up":y(d,-1),"Ctrl-Down":y(d,1),"Alt-A":y(h,-1),"Alt-E":y(h,1),"Alt-K":function(e){b(e,h,1,"grow")},"Ctrl-Alt-K":function(e){b(e,p,1,"grow")},"Ctrl-Alt-Backspace":function(e){b(e,p,-1,"grow")},"Ctrl-Alt-F":y(p,1),"Ctrl-Alt-B":y(p,-1),"Shift-Ctrl-Alt-2":function(e){var t=e.getCursor();e.setSelection(v(e,t,p,1),t)},"Ctrl-Alt-T":function(e){var t=p(e,e.getCursor(),-1),n=p(e,t,1),r=p(e,n,1),i=p(e,r,-1);e.replaceRange(e.getRange(i,r)+e.getRange(n,i)+e.getRange(t,n),t,r)},"Ctrl-Alt-U":g(function(e){for(var n=e.getCursor(),r=n.line,i=n.ch,o=[];r>=e.firstLine();){for(var a=e.getLine(r),l=null==i?a.length:i;l>0;){var i=a.charAt(--l);if(")"==i)o.push("(");else if("]"==i)o.push("[");else if("}"==i)o.push("{");else if(/[\(\{\[]/.test(i)&&(!o.length||o.pop()!=i))return e.extendSelection(t(r,l))}--r,i=null}}),"Alt-Space":function(e){for(var n=e.getCursor(),r=n.ch,i=n.ch,o=e.getLine(n.line);r&&/\s/.test(o.charAt(r-1));)--r;for(;i0)return e.setCursor(t-1);!function(e,t,n){e.openDialog?e.openDialog(t+': ',n,{bottom:!0}):n(prompt(t,""))}(e,"Goto line",function(t){var n;t&&!isNaN(n=Number(t))&&n==(0|n)&&n>0&&e.setCursor(n-1)})},"Ctrl-X Tab":function(e){e.indentSelection(m(e,!0)||e.getOption("indentUnit"))},"Ctrl-X Ctrl-X":function(e){e.setSelection(e.getCursor("head"),e.getCursor("anchor"))},"Ctrl-X Ctrl-S":"save","Ctrl-X Ctrl-W":"save","Ctrl-X S":"saveAll","Ctrl-X F":"open","Ctrl-X U":g("undo"),"Ctrl-X K":"close","Ctrl-X Delete":function(e){l(e,e.getCursor(),h(e,e.getCursor(),1),"grow")},"Ctrl-X H":"selectAll","Ctrl-Q Tab":g("insertTab"),"Ctrl-U":function(e){e.state.emacsPrefixMap=!0,e.addKeyMap(P),e.on("keyHandled",M),e.on("inputRead",M)}}),P={"Ctrl-G":S};function N(e){P[e]=function(t){x(t,e)},E["Ctrl-"+e]=function(t){x(t,e)},k["Ctrl-"+e]=!0}for(var I=0;I<10;++I)N(String(I));N("-")}(n(0))},function(e,t,n){var r;(r=n(0)).defineOption("showTrailingSpace",!1,function(e,t,n){n==r.Init&&(n=!1),n&&!t?e.removeOverlay("trailingspace"):!n&&t&&e.addOverlay({token:function(e){for(var t=e.string.length,n=t;n&&/\s/.test(e.string.charAt(n-1));--n);return n>e.pos?(e.pos=n,null):(e.pos=t,"trailingspace")},name:"trailingspace"})})},function(e,t,n){!function(e){"use strict";var t="CodeMirror-activeline",n="CodeMirror-activeline-background",r="CodeMirror-activeline-gutter";function i(e){for(var i=0;i>u",">>s",">=","<=","==","!=","=s",">=u",">s",">u","<",">","=","&","|","^","!"]);function l(e,t){var n;for(t.commentDepth=1;null!=(n=e.next());){if("*"===n&&e.eat("/")&&0==--t.commentDepth)return t.tokenize=null,"comment";"/"===n&&e.eat("*")&&t.commentDepth++}return"comment"}function s(e,t){for(var n,r=t.commentState;null!=(n=e.next());)if(0===r&&"t"===n)r=1;else if(1===r&&":"===n)return t.tokenize=null,t.commentState=0,r=2,"comment";return t.commentState=r,"comment"}return{startState:function(){return{tokenize:null,commentState:0,commentDepth:0}},token:function(n,c){if(n.eatSpace())return null;var u=(c.tokenize||function(n,c){var u,f=n.next();if("$"===f)return n.eatWhile(t),"variable";if("@"===f)return n.eatWhile(t),"meta";if('"'===f)return c.tokenize=(u=f,function(e,t){for(var n,r=!1;null!=(n=e.next());){if(n==u&&!r)return t.tokenize=null,"string";r=!r&&"\\"===n}return"string"}),c.tokenize(n,c);if("/"==f){if(n.eat("*"))return c.tokenize=l,l(n,c);if(n.eat("/"))return n.skipToEnd(),"comment"}if(/\d/.test(f)||("-"===f||"+"===f)&&/\d/.test(n.peek()))return n.eatWhile(/[\w\._\-+]/),"number";if(/[\[\]\(\)\{\},:]/.test(f))return null;if(o.test(f))return"operator";n.eatWhile(t);var d=n.current();if(d in a)return"operator";if(d in e)return"keyword";if(d in i){if(!n.eat(":"))return"builtin";n.eatWhile(t),d=n.current()}return d in r?"builtin":"Temporary"===d?(c.tokenize=s,c.tokenize(n,c)):null})(n,c);return u}}}),e.registerHelper("wordChars","wasm",t),e.defineMIME("text/wasm","wasm")})?r.apply(t,i):r)||(e.exports=o)},function(e,t,n){!function(e){"use strict";function t(e,t,n,r,i,o){this.indented=e,this.column=t,this.type=n,this.info=r,this.align=i,this.prev=o}function n(e,n,r,i){var o=e.indented;return e.context&&"statement"==e.context.type&&"statement"!=r&&(o=e.context.indented),e.context=new t(o,n,r,i,null,e.context)}function r(e){var t=e.context.type;return")"!=t&&"]"!=t&&"}"!=t||(e.indented=e.context.indented),e.context=e.context.prev}function i(e,t,n){return"variable"==t.prevToken||"type"==t.prevToken||!!/\S(?:[^- ]>|[*\]])\s*$|\*$/.test(e.string.slice(0,n))||!(!t.typeAtEndOfLine||e.column()!=e.indentation())||void 0}function o(e){for(;;){if(!e||"top"==e.type)return!0;if("}"==e.type&&"namespace"!=e.prev.info)return!1;e=e.prev}}function a(e){for(var t={},n=e.split(" "),r=0;r!?|\/]/,O=s.isIdentifierChar||/[\w\$_\xa1-\uffff]/;function E(e,t){var n,r=e.next();if(w[r]){var i=w[r](e,t);if(!1!==i)return i}if('"'==r||"'"==r)return t.tokenize=(n=r,function(e,t){for(var r,i=!1,o=!1;null!=(r=e.next());){if(r==n&&!i){o=!0;break}i=!i&&"\\"==r}return(o||!i&&!x)&&(t.tokenize=null),"string"}),t.tokenize(e,t);if(L.test(r))return c=r,null;if(M.test(r)){if(e.backUp(1),e.match(T))return"number";e.next()}if("/"==r){if(e.eat("*"))return t.tokenize=P,P(e,t);if(e.eat("/"))return e.skipToEnd(),"comment"}if(A.test(r)){for(;!e.match(/^\/[\/*]/,!1)&&e.eat(A););return"operator"}if(e.eatWhile(O),S)for(;e.match(S);)e.eatWhile(O);var o=e.current();return l(p,o)?(l(v,o)&&(c="newstatement"),l(y,o)&&(u=!0),"keyword"):l(m,o)?"type":l(g,o)?(l(v,o)&&(c="newstatement"),"builtin"):l(b,o)?"atom":"variable"}function P(e,t){for(var n,r=!1;n=e.next();){if("/"==n&&r){t.tokenize=null;break}r="*"==n}return"comment"}function N(e,t){s.typeFirstDefinitions&&e.eol()&&o(t.context)&&(t.typeAtEndOfLine=i(e,t,e.pos))}return{startState:function(e){return{tokenize:null,context:new t((e||0)-f,0,"top",null,!1),indented:0,startOfLine:!0,prevToken:null}},token:function(e,t){var a=t.context;if(e.sol()&&(null==a.align&&(a.align=!1),t.indented=e.indentation(),t.startOfLine=!0),e.eatSpace())return N(e,t),null;c=u=null;var l=(t.tokenize||E)(e,t);if("comment"==l||"meta"==l)return l;if(null==a.align&&(a.align=!0),";"==c||":"==c||","==c&&e.match(/^\s*(?:\/\/.*)?$/,!1))for(;"statement"==t.context.type;)r(t);else if("{"==c)n(t,e.column(),"}");else if("["==c)n(t,e.column(),"]");else if("("==c)n(t,e.column(),")");else if("}"==c){for(;"statement"==a.type;)a=r(t);for("}"==a.type&&(a=r(t));"statement"==a.type;)a=r(t)}else c==a.type?r(t):k&&(("}"==a.type||"top"==a.type)&&";"!=c||"statement"==a.type&&"newstatement"==c)&&n(t,e.column(),"statement",e.current());if("variable"==l&&("def"==t.prevToken||s.typeFirstDefinitions&&i(e,t,e.start)&&o(t.context)&&e.match(/^\s*\(/,!1))&&(l="def"),w.token){var f=w.token(e,t,l);void 0!==f&&(l=f)}return"def"==l&&!1===s.styleDefs&&(l="variable"),t.startOfLine=!1,t.prevToken=u?"def":l||c,N(e,t),l},indent:function(t,n){if(t.tokenize!=E&&null!=t.tokenize||t.typeAtEndOfLine)return e.Pass;var r=t.context,i=n&&n.charAt(0);if("statement"==r.type&&"}"==i&&(r=r.prev),s.dontIndentStatements)for(;"statement"==r.type&&s.dontIndentStatements.test(r.info);)r=r.prev;if(w.indent){var o=w.indent(t,r,n);if("number"==typeof o)return o}var a=i==r.type,l=r.prev&&"switch"==r.prev.info;if(s.allmanIndentation&&/[{(]/.test(i)){for(;"top"!=r.type&&"}"!=r.type;)r=r.prev;return r.indented}return"statement"==r.type?r.indented+("{"==i?0:d):!r.align||h&&")"==r.type?")"!=r.type||a?r.indented+(a?0:f)+(a||!l||/^(?:case|default)\b/.test(n)?0:f):r.indented+d:r.column+(a?0:1)},electricInput:C?/^\s*(?:case .*?:|default:|\{\}?|\})$/:/^\s*[{}]$/,blockCommentStart:"/*",blockCommentEnd:"*/",blockCommentContinue:" * ",lineComment:"//",fold:"brace"}});var s="auto if break case register continue return default do sizeof static else struct switch extern typedef union for goto while enum const volatile",c="int long char short double float unsigned signed void size_t ptrdiff_t";function u(e,t){if(!t.startOfLine)return!1;for(var n,r=null;n=e.peek();){if("\\"==n&&e.match(/^.$/)){r=u;break}if("/"==n&&e.match(/^\/[\/\*]/,!1))break;e.next()}return t.tokenize=r,"meta"}function f(e,t){return"type"==t.prevToken&&"type"}function d(e){return e.eatWhile(/[\w\.']/),"number"}function h(e,t){if(e.backUp(1),e.match(/(R|u8R|uR|UR|LR)/)){var n=e.match(/"([^\s\\()]{0,16})\(/);return!!n&&(t.cpp11RawStringDelim=n[1],t.tokenize=m,m(e,t))}return e.match(/(u8|u|U|L)/)?!!e.match(/["']/,!1)&&"string":(e.next(),!1)}function p(e,t){for(var n;null!=(n=e.next());)if('"'==n&&!e.eat('"')){t.tokenize=null;break}return"string"}function m(e,t){var n=t.cpp11RawStringDelim.replace(/[^\w\s]/g,"\\$&"),r=e.match(new RegExp(".*?\\)"+n+'"'));return r?t.tokenize=null:e.skipToEnd(),"string"}function g(t,n){"string"==typeof t&&(t=[t]);var r=[];function i(e){if(e)for(var t in e)e.hasOwnProperty(t)&&r.push(t)}i(n.keywords),i(n.types),i(n.builtin),i(n.atoms),r.length&&(n.helperType=t[0],e.registerHelper("hintWords",t[0],r));for(var o=0;o!?|\/#:@]/,hooks:{"@":function(e){return e.eatWhile(/[\w\$_]/),"meta"},'"':function(e,t){return!!e.match('""')&&(t.tokenize=v,t.tokenize(e,t))},"'":function(e){return e.eatWhile(/[\w\$_\xa1-\uffff]/),"atom"},"=":function(e,n){var r=n.context;return!("}"!=r.type||!r.align||!e.eat(">"))&&(n.context=new t(r.indented,r.column,r.type,r.info,null,r.prev),"operator")},"/":function(e,t){return!!e.eat("*")&&(t.tokenize=function e(t){return function(n,r){for(var i;i=n.next();){if("*"==i&&n.eat("/")){if(1==t){r.tokenize=null;break}return r.tokenize=e(t-1),r.tokenize(n,r)}if("/"==i&&n.eat("*"))return r.tokenize=e(t+1),r.tokenize(n,r)}return"comment"}}(1),t.tokenize(e,t))}},modeProps:{closeBrackets:{triples:'"'}}}),g("text/x-kotlin",{name:"clike",keywords:a("package as typealias class interface this super val operator var fun for is in This throw return annotation break continue object if else while do try when !in !is as? file import where by get set abstract enum open inner override private public internal protected catch finally out final vararg reified dynamic companion constructor init sealed field property receiver param sparam lateinit data inline noinline tailrec external annotation crossinline const operator infix suspend actual expect setparam"),types:a("Boolean Byte Character CharSequence Class ClassLoader Cloneable Comparable Compiler Double Exception Float Integer Long Math Number Object Package Pair Process Runtime Runnable SecurityManager Short StackTraceElement StrictMath String StringBuffer System Thread ThreadGroup ThreadLocal Throwable Triple Void Annotation Any BooleanArray ByteArray Char CharArray DeprecationLevel DoubleArray Enum FloatArray Function Int IntArray Lazy LazyThreadSafetyMode LongArray Nothing ShortArray Unit"),intendSwitch:!1,indentStatements:!1,multiLineStrings:!0,number:/^(?:0x[a-f\d_]+|0b[01_]+|(?:[\d_]+(\.\d+)?|\.\d+)(?:e[-+]?[\d_]+)?)(u|ll?|l|f)?/i,blockKeywords:a("catch class do else finally for if where try while enum"),defKeywords:a("class val var object interface fun"),atoms:a("true false null this"),hooks:{"@":function(e){return e.eatWhile(/[\w\$_]/),"meta"},'"':function(e,t){var n;return t.tokenize=(n=e.match('""'),function(e,t){for(var r,i=!1,o=!1;!e.eol();){if(!n&&!i&&e.match('"')){o=!0;break}if(n&&e.match('"""')){o=!0;break}r=e.next(),!i&&"$"==r&&e.match("{")&&e.skipTo("}"),i=!i&&"\\"==r&&!n}return!o&&n||(t.tokenize=null),"string"}),t.tokenize(e,t)}},modeProps:{closeBrackets:{triples:'"'}}}),g(["x-shader/x-vertex","x-shader/x-fragment"],{name:"clike",keywords:a("sampler1D sampler2D sampler3D samplerCube sampler1DShadow sampler2DShadow const attribute uniform varying break continue discard return for while do if else struct in out inout"),types:a("float int bool void vec2 vec3 vec4 ivec2 ivec3 ivec4 bvec2 bvec3 bvec4 mat2 mat3 mat4"),blockKeywords:a("for while do if else struct"),builtin:a("radians degrees sin cos tan asin acos atan pow exp log exp2 sqrt inversesqrt abs sign floor ceil fract mod min max clamp mix step smoothstep length distance dot cross normalize ftransform faceforward reflect refract matrixCompMult lessThan lessThanEqual greaterThan greaterThanEqual equal notEqual any all not texture1D texture1DProj texture1DLod texture1DProjLod texture2D texture2DProj texture2DLod texture2DProjLod texture3D texture3DProj texture3DLod texture3DProjLod textureCube textureCubeLod shadow1D shadow2D shadow1DProj shadow2DProj shadow1DLod shadow2DLod shadow1DProjLod shadow2DProjLod dFdx dFdy fwidth noise1 noise2 noise3 noise4"),atoms:a("true false gl_FragColor gl_SecondaryColor gl_Normal gl_Vertex gl_MultiTexCoord0 gl_MultiTexCoord1 gl_MultiTexCoord2 gl_MultiTexCoord3 gl_MultiTexCoord4 gl_MultiTexCoord5 gl_MultiTexCoord6 gl_MultiTexCoord7 gl_FogCoord gl_PointCoord gl_Position gl_PointSize gl_ClipVertex gl_FrontColor gl_BackColor gl_FrontSecondaryColor gl_BackSecondaryColor gl_TexCoord gl_FogFragCoord gl_FragCoord gl_FrontFacing gl_FragData gl_FragDepth gl_ModelViewMatrix gl_ProjectionMatrix gl_ModelViewProjectionMatrix gl_TextureMatrix gl_NormalMatrix gl_ModelViewMatrixInverse gl_ProjectionMatrixInverse gl_ModelViewProjectionMatrixInverse gl_TexureMatrixTranspose gl_ModelViewMatrixInverseTranspose gl_ProjectionMatrixInverseTranspose gl_ModelViewProjectionMatrixInverseTranspose gl_TextureMatrixInverseTranspose gl_NormalScale gl_DepthRange gl_ClipPlane gl_Point gl_FrontMaterial gl_BackMaterial gl_LightSource gl_LightModel gl_FrontLightModelProduct gl_BackLightModelProduct gl_TextureColor gl_EyePlaneS gl_EyePlaneT gl_EyePlaneR gl_EyePlaneQ gl_FogParameters gl_MaxLights gl_MaxClipPlanes gl_MaxTextureUnits gl_MaxTextureCoords gl_MaxVertexAttribs gl_MaxVertexUniformComponents gl_MaxVaryingFloats gl_MaxVertexTextureImageUnits gl_MaxTextureImageUnits gl_MaxFragmentUniformComponents gl_MaxCombineTextureImageUnits gl_MaxDrawBuffers"),indentSwitch:!1,hooks:{"#":u},modeProps:{fold:["brace","include"]}}),g("text/x-nesc",{name:"clike",keywords:a(s+"as atomic async call command component components configuration event generic implementation includes interface module new norace nx_struct nx_union post provides signal task uses abstract extends"),types:a(c),blockKeywords:a("case do else for if switch while struct"),atoms:a("null true false"),hooks:{"#":u},modeProps:{fold:["brace","include"]}}),g("text/x-objectivec",{name:"clike",keywords:a(s+"inline restrict _Bool _Complex _Imaginary BOOL Class bycopy byref id IMP in inout nil oneway out Protocol SEL self super atomic nonatomic retain copy readwrite readonly"),types:a(c),atoms:a("YES NO NULL NILL ON OFF true false"),hooks:{"@":function(e){return e.eatWhile(/[\w\$]/),"keyword"},"#":u,indent:function(e,t,n){if("statement"==t.type&&/^@\w/.test(n))return t.indented}},modeProps:{fold:"brace"}}),g("text/x-squirrel",{name:"clike",keywords:a("base break clone continue const default delete enum extends function in class foreach local resume return this throw typeof yield constructor instanceof static"),types:a(c),blockKeywords:a("case catch class else for foreach if switch try while"),defKeywords:a("function local class"),typeFirstDefinitions:!0,atoms:a("true false null"),hooks:{"#":u},modeProps:{fold:["brace","include"]}});var y=null;g("text/x-ceylon",{name:"clike",keywords:a("abstracts alias assembly assert assign break case catch class continue dynamic else exists extends finally for function given if import in interface is let module new nonempty object of out outer package return satisfies super switch then this throw try value void while"),types:function(e){var t=e.charAt(0);return t===t.toUpperCase()&&t!==t.toLowerCase()},blockKeywords:a("case catch class dynamic else finally for function if interface module new object switch try while"),defKeywords:a("class dynamic function interface module object package value"),builtin:a("abstract actual aliased annotation by default deprecated doc final formal late license native optional sealed see serializable shared suppressWarnings tagged throws variable"),isPunctuationChar:/[\[\]{}\(\),;\:\.`]/,isOperatorChar:/[+\-*&%=<>!?|^~:\/]/,numberStart:/[\d#$]/,number:/^(?:#[\da-fA-F_]+|\$[01_]+|[\d_]+[kMGTPmunpf]?|[\d_]+\.[\d_]+(?:[eE][-+]?\d+|[kMGTPmunpf]|)|)/i,multiLineStrings:!0,typeFirstDefinitions:!0,atoms:a("true false null larger smaller equal empty finished"),indentSwitch:!1,styleDefs:!1,hooks:{"@":function(e){return e.eatWhile(/[\w\$_]/),"meta"},'"':function(e,t){return t.tokenize=function e(t){return function(n,r){for(var i,o=!1,a=!1;!n.eol();){if(!o&&n.match('"')&&("single"==t||n.match('""'))){a=!0;break}if(!o&&n.match("``")){y=e(t),a=!0;break}i=n.next(),o="single"==t&&!o&&"\\"==i}return a&&(r.tokenize=null),"string"}}(e.match('""')?"triple":"single"),t.tokenize(e,t)},"`":function(e,t){return!(!y||!e.match("`"))&&(t.tokenize=y,y=null,t.tokenize(e,t))},"'":function(e){return e.eatWhile(/[\w\$_\xa1-\uffff]/),"atom"},token:function(e,t,n){if(("variable"==n||"type"==n)&&"."==t.prevToken)return"variable-2"}},modeProps:{fold:["brace","import"],closeBrackets:{triples:'"'}}})}(n(0))},function(e,t,n){!function(e){"use strict";e.defineMode("elm",function(){function e(e,t,n){return t(n),n(e,t)}var t=/[a-z_]/,n=/[A-Z]/,r=/[0-9]/,i=/[0-9A-Fa-f]/,o=/[0-7]/,a=/[a-z_A-Z0-9\']/,l=/[-!#$%&*+.\/<=>?@\\^|~:\u03BB\u2192]/,s=/[(),;[\]`{}]/,c=/[ \t\v\f]/;function u(){return function(d,h){if(d.eatWhile(c))return null;var p=d.next();if(s.test(p)){if("{"==p&&d.eat("-")){var m="comment";return d.eat("#")&&(m="meta"),e(d,h,function e(t,n){return 0==n?u():function(r,i){for(var o=n;!r.eol();){var a=r.next();if("{"==a&&r.eat("-"))++o;else if("-"==a&&r.eat("}")&&0==--o)return i(u()),t}return i(e(t,o)),t}}(m,1))}return null}if("'"==p)return d.eat("\\"),d.next(),d.eat("'")?"string":"error";if('"'==p)return e(d,h,f);if(n.test(p))return d.eatWhile(a),d.eat(".")?"qualifier":"variable-2";if(t.test(p)){var g=1===d.pos;return d.eatWhile(a),g?"type":"variable"}if(r.test(p)){if("0"==p){if(d.eat(/[xX]/))return d.eatWhile(i),"integer";if(d.eat(/[oO]/))return d.eatWhile(o),"number"}d.eatWhile(r);var m="number";return d.eat(".")&&(m="number",d.eatWhile(r)),d.eat(/[eE]/)&&(m="number",d.eat(/[-+]/),d.eatWhile(r)),m}return l.test(p)?"-"==p&&d.eat(/-/)&&(d.eatWhile(/-/),!d.eat(l))?(d.skipToEnd(),"comment"):(d.eatWhile(l),"builtin"):"error"}}function f(e,t){for(;!e.eol();){var n=e.next();if('"'==n)return t(u()),"string";if("\\"==n){if(e.eol()||e.eat(c))return t(d),"string";e.eat("&")||e.next()}}return t(u()),"error"}function d(t,n){return t.eat("\\")?e(t,n,f):(t.next(),n(u()),"error")}var h=function(){for(var e={},t=["case","of","as","if","then","else","let","in","infix","infixl","infixr","type","alias","input","output","foreign","loopback","module","where","import","exposing","_","..","|",":","=","\\",'"',"->","<-"],n=t.length;n--;)e[t[n]]="keyword";return e}();return{startState:function(){return{f:u()}},copyState:function(e){return{f:e.f}},token:function(e,t){var n=t.f(e,function(e){t.f=e}),r=e.current();return h.hasOwnProperty(r)?h[r]:n}}}),e.defineMIME("text/x-elm","elm")}(n(0))},function(e,t,n){!function(e){"use strict";e.defineMode("coffeescript",function(e,t){var n="error";function r(e){return new RegExp("^(("+e.join(")|(")+"))\\b")}var i=/^(?:->|=>|\+[+=]?|-[\-=]?|\*[\*=]?|\/[\/=]?|[=!]=|<[><]?=?|>>?=?|%=?|&=?|\|=?|\^=?|\~|!|\?|(or|and|\|\||&&|\?)=)/,o=/^(?:[()\[\]{},:`=;]|\.\.?\.?)/,a=/^[_A-Za-z$][_A-Za-z$0-9]*/,l=/^@[_A-Za-z$][_A-Za-z$0-9]*/,s=r(["and","or","not","is","isnt","in","instanceof","typeof"]),c=["for","while","loop","if","unless","else","switch","try","catch","finally","class"],u=r(c.concat(["break","by","continue","debugger","delete","do","in","of","new","return","then","this","@","throw","when","until","extends"]));c=r(c);var f=/^('{3}|\"{3}|['\"])/,d=/^(\/{3}|\/)/,h=r(["Infinity","NaN","undefined","null","true","false","on","off","yes","no"]);function p(e,t){if(e.sol()){null===t.scope.align&&(t.scope.align=!1);var r=t.scope.offset;if(e.eatSpace()){var c=e.indentation();return c>r&&"coffee"==t.scope.type?"indent":c0&&y(e,t)}if(e.eatSpace())return null;var p=e.peek();if(e.match("####"))return e.skipToEnd(),"comment";if(e.match("###"))return t.tokenize=g,t.tokenize(e,t);if("#"===p)return e.skipToEnd(),"comment";if(e.match(/^-?[0-9\.]/,!1)){var v=!1;if(e.match(/^-?\d*\.\d+(e[\+\-]?\d+)?/i)&&(v=!0),e.match(/^-?\d+\.\d*/)&&(v=!0),e.match(/^-?\.\d+/)&&(v=!0),v)return"."==e.peek()&&e.backUp(1),"number";var b=!1;if(e.match(/^-?0x[0-9a-f]+/i)&&(b=!0),e.match(/^-?[1-9]\d*(e[\+\-]?\d+)?/)&&(b=!0),e.match(/^-?0(?![\dx])/i)&&(b=!0),b)return"number"}if(e.match(f))return t.tokenize=m(e.current(),!1,"string"),t.tokenize(e,t);if(e.match(d)){if("/"!=e.current()||e.match(/^.*\//,!1))return t.tokenize=m(e.current(),!0,"string-2"),t.tokenize(e,t);e.backUp(1)}return e.match(i)||e.match(s)?"operator":e.match(o)?"punctuation":e.match(h)?"atom":e.match(l)||t.prop&&e.match(a)?"property":e.match(u)?"keyword":e.match(a)?"variable":(e.next(),n)}function m(e,r,i){return function(o,a){for(;!o.eol();)if(o.eatWhile(/[^'"\/\\]/),o.eat("\\")){if(o.next(),r&&o.eol())return i}else{if(o.match(e))return a.tokenize=p,i;o.eat(/['"\/]/)}return r&&(t.singleLineStringErrors?i=n:a.tokenize=p),i}}function g(e,t){for(;!e.eol();){if(e.eatWhile(/[^#]/),e.match("###")){t.tokenize=p;break}e.eatWhile("#")}return"comment"}function v(t,n,r){r=r||"coffee";for(var i=0,o=!1,a=null,l=n.scope;l;l=l.prev)if("coffee"===l.type||"}"==l.type){i=l.offset+e.indentUnit;break}"coffee"!==r?(o=null,a=t.column()+t.current().length):n.scope.align&&(n.scope.align=!1),n.scope={offset:i,type:r,prev:n.scope,align:o,alignOffset:a}}function y(e,t){if(t.scope.prev){if("coffee"===t.scope.type){for(var n=e.indentation(),r=!1,i=t.scope;i;i=i.prev)if(n===i.offset){r=!0;break}if(!r)return!0;for(;t.scope.prev&&t.scope.offset!==n;)t.scope=t.scope.prev;return!1}return t.scope=t.scope.prev,!1}}var b={startState:function(e){return{tokenize:p,scope:{offset:e||0,type:"coffee",prev:null,align:!1},prop:!1,dedent:0}},token:function(e,t){var r=null===t.scope.align&&t.scope;r&&e.sol()&&(r.align=!1);var i=function(e,t){var r=t.tokenize(e,t),i=e.current();"return"===i&&(t.dedent=!0),(("->"===i||"=>"===i)&&e.eol()||"indent"===r)&&v(e,t);var o="[({".indexOf(i);if(-1!==o&&v(e,t,"])}".slice(o,o+1)),c.exec(i)&&v(e,t),"then"==i&&y(e,t),"dedent"===r&&y(e,t))return n;if(-1!==(o="])}".indexOf(i))){for(;"coffee"==t.scope.type&&t.scope.prev;)t.scope=t.scope.prev;t.scope.type==i&&(t.scope=t.scope.prev)}return t.dedent&&e.eol()&&("coffee"==t.scope.type&&t.scope.prev&&(t.scope=t.scope.prev),t.dedent=!1),r}(e,t);return i&&"comment"!=i&&(r&&(r.align=!0),t.prop="punctuation"==i&&"."==e.current()),i},indent:function(e,t){if(e.tokenize!=p)return 0;var n=e.scope,r=t&&"])}".indexOf(t.charAt(0))>-1;if(r)for(;"coffee"==n.type&&n.prev;)n=n.prev;var i=r&&n.type===t.charAt(0);return n.align?n.alignOffset-(i?1:0):(i?n.prev:n).offset},lineComment:"#",fold:"indent"};return b}),e.defineMIME("application/vnd.coffeescript","coffeescript"),e.defineMIME("text/x-coffeescript","coffeescript"),e.defineMIME("text/coffeescript","coffeescript")}(n(0))},function(e,t,n){!function(e){"use strict";function t(e,t,n,r){this.state=e,this.mode=t,this.depth=n,this.prev=r}e.defineMode("jsx",function(n,r){var i=e.getMode(n,{name:"xml",allowMissing:!0,multilineTagIndentPastTag:!1,allowMissingTagName:!0}),o=e.getMode(n,r&&r.base||"javascript");function a(e){var t=e.tagName;e.tagName=null;var n=i.indent(e,"");return e.tagName=t,n}function l(r,s){return s.context.mode==i?function(r,s,c){if(2==c.depth)return r.match(/^.*?\*\//)?c.depth=1:r.skipToEnd(),"comment";if("{"==r.peek()){i.skipAttribute(c.state);var u=a(c.state),f=c.state.context;if(f&&r.match(/^[^>]*>\s*$/,!1)){for(;f.prev&&!f.startOfLine;)f=f.prev;f.startOfLine?u-=n.indentUnit:c.prev.state.lexical&&(u=c.prev.state.lexical.indented)}else 1==c.depth&&(u+=n.indentUnit);return s.context=new t(e.startState(o,u),o,0,s.context),null}if(1==c.depth){if("<"==r.peek())return i.skipAttribute(c.state),s.context=new t(e.startState(i,a(c.state)),i,0,s.context),null;if(r.match("//"))return r.skipToEnd(),"comment";if(r.match("/*"))return c.depth=2,l(r,s)}var d,h=i.token(r,c.state),p=r.current();return/\btag\b/.test(h)?/>$/.test(p)?c.state.context?c.depth=0:s.context=s.context.prev:/^-1&&r.backUp(p.length-d),h}(r,s,s.context):function(n,r,a){if("<"==n.peek()&&o.expressionAllowed(n,a.state))return o.skipExpression(a.state),r.context=new t(e.startState(i,o.indent(a.state,"")),i,0,r.context),null;var l=o.token(n,a.state);if(!l&&null!=a.depth){var s=n.current();"{"==s?a.depth++:"}"==s&&0==--a.depth&&(r.context=r.context.prev)}return l}(r,s,s.context)}return{startState:function(){return{context:new t(e.startState(o),o)}},copyState:function(n){return{context:function n(r){return new t(e.copyState(r.mode,r.state),r.mode,r.depth,r.prev&&n(r.prev))}(n.context)}},token:l,indent:function(e,t,n){return e.context.mode.indent(e.context.state,t,n)},innerMode:function(e){return e.context}}},"xml","javascript"),e.defineMIME("text/jsx","jsx"),e.defineMIME("text/typescript-jsx",{name:"jsx",base:{name:"javascript",typescript:!0}})}(n(0),n(2),n(3))},function(e,t,n){!function(e){"use strict";var t={script:[["lang",/(javascript|babel)/i,"javascript"],["type",/^(?:text|application)\/(?:x-)?(?:java|ecma)script$|^module$|^$/i,"javascript"],["type",/./,"text/plain"],[null,null,"javascript"]],style:[["lang",/^css$/i,"css"],["type",/^(text\/)?(x-)?(stylesheet|css)$/i,"css"],["type",/./,"text/plain"],[null,null,"css"]]},n={};function r(e,t){var r=e.match(function(e){var t=n[e];return t||(n[e]=new RegExp("\\s+"+e+"\\s*=\\s*('|\")?([^'\"]+)('|\")?\\s*"))}(t));return r?/^\s*(.*?)\s*$/.exec(r[2])[1]:""}function i(e,t){return new RegExp((t?"^":"")+"","i")}function o(e,t){for(var n in e)for(var r=t[n]||(t[n]=[]),i=e[n],o=i.length-1;o>=0;o--)r.unshift(i[o])}e.defineMode("htmlmixed",function(n,a){var l=e.getMode(n,{name:"xml",htmlMode:!0,multilineTagIndentFactor:a.multilineTagIndentFactor,multilineTagIndentPastTag:a.multilineTagIndentPastTag}),s={},c=a&&a.tags,u=a&&a.scriptTypes;if(o(t,s),c&&o(c,s),u)for(var f=u.length-1;f>=0;f--)s.script.unshift(["type",u[f].matches,u[f].mode]);function d(t,o){var a,c=l.token(t,o.htmlState),u=/\btag\b/.test(c);if(u&&!/[<>\s\/]/.test(t.current())&&(a=o.htmlState.tagName&&o.htmlState.tagName.toLowerCase())&&s.hasOwnProperty(a))o.inTag=a+" ";else if(o.inTag&&u&&/>$/.test(t.current())){var f=/^([\S]+) (.*)/.exec(o.inTag);o.inTag=null;var h=">"==t.current()&&function(e,t){for(var n=0;n-1?e.backUp(r.length-i):r.match(/<\/?$/)&&(e.backUp(r.length),e.match(t,!1)||e.match(r)),n}(e,g,t.localMode.token(e,t.localState))},o.localMode=p,o.localState=e.startState(p,l.indent(o.htmlState,""))}else o.inTag&&(o.inTag+=t.current(),t.eol()&&(o.inTag+=" "));return c}return{startState:function(){var t=e.startState(l);return{token:d,inTag:null,localMode:null,localState:null,htmlState:t}},copyState:function(t){var n;return t.localState&&(n=e.copyState(t.localMode,t.localState)),{token:t.token,inTag:t.inTag,localMode:t.localMode,localState:n,htmlState:e.copyState(l,t.htmlState)}},token:function(e,t){return t.token(e,t)},indent:function(t,n,r){return!t.localMode||/^\s*<\//.test(n)?l.indent(t.htmlState,n):t.localMode.indent?t.localMode.indent(t.localState,n,r):e.Pass},innerMode:function(e){return{state:e.localState||e.htmlState,mode:e.localMode||l}}}},"xml","javascript","css"),e.defineMIME("text/html","htmlmixed")}(n(0),n(2),n(3),n(7))},function(e,t,n){!function(e){"use strict";var t={},n=/[^\s\u00a0]/,r=e.Pos;function i(e){var t=e.search(n);return-1==t?0:t}function o(e,t){var n=e.getMode();return!1!==n.useInnerComments&&n.innerMode?e.getModeAt(t):n}e.commands.toggleComment=function(e){e.toggleComment()},e.defineExtension("toggleComment",function(e){e||(e=t);for(var n=1/0,i=this.listSelections(),o=null,a=i.length-1;a>=0;a--){var l=i[a].from(),s=i[a].to();l.line>=n||(s.line>=n&&(s=r(n,0)),n=l.line,null==o?this.uncomment(l,s,e)?o="un":(this.lineComment(l,s,e),o="line"):"un"==o?this.uncomment(l,s,e):this.lineComment(l,s,e))}}),e.defineExtension("lineComment",function(e,a,l){l||(l=t);var s=this,c=o(s,e),u=s.getLine(e.line);if(null!=u&&(f=e,d=u,!/\bstring\b/.test(s.getTokenTypeAt(r(f.line,0)))||/^[\'\"\`]/.test(d))){var f,d,h=l.lineComment||c.lineComment;if(h){var p=Math.min(0!=a.ch||a.line==e.line?a.line+1:a.line,s.lastLine()+1),m=null==l.padding?" ":l.padding,g=l.commentBlankLines||e.line==a.line;s.operation(function(){if(l.indent){for(var t=null,o=e.line;oc.length)&&(t=c)}for(var o=e.line;of||l.operation(function(){if(0!=a.fullLines){var t=n.test(l.getLine(f));l.replaceRange(d+u,r(f)),l.replaceRange(c+d,r(e.line,0));var o=a.blockCommentLead||s.blockCommentLead;if(null!=o)for(var h=e.line+1;h<=f;++h)(h!=f||t)&&l.replaceRange(o+d,r(h,0))}else l.replaceRange(u,i),l.replaceRange(c,e)})}}else(a.lineComment||s.lineComment)&&0!=a.fullLines&&l.lineComment(e,i,a)}),e.defineExtension("uncomment",function(e,i,a){a||(a=t);var l,s=this,c=o(s,e),u=Math.min(0!=i.ch||i.line==e.line?i.line:i.line-1,s.lastLine()),f=Math.min(e.line,u),d=a.lineComment||c.lineComment,h=[],p=null==a.padding?" ":a.padding;e:if(d){for(var m=f;m<=u;++m){var g=s.getLine(m),v=g.indexOf(d);if(v>-1&&!/comment/.test(s.getTokenTypeAt(r(m,v+1)))&&(v=-1),-1==v&&n.test(g))break e;if(v>-1&&n.test(g.slice(0,v)))break e;h.push(g)}if(s.operation(function(){for(var e=f;e<=u;++e){var t=h[e-f],n=t.indexOf(d),i=n+d.length;n<0||(t.slice(i,i+p.length)==p&&(i+=p.length),l=!0,s.replaceRange("",r(e,n),r(e,i)))}}),l)return!0}var y=a.blockCommentStart||c.blockCommentStart,b=a.blockCommentEnd||c.blockCommentEnd;if(!y||!b)return!1;var w=a.blockCommentLead||c.blockCommentLead,x=s.getLine(f),k=x.indexOf(y);if(-1==k)return!1;var C=u==f?x:s.getLine(u),S=C.indexOf(b,u==f?k+y.length:0),L=r(f,k+1),M=r(u,S+1);if(-1==S||!/comment/.test(s.getTokenTypeAt(L))||!/comment/.test(s.getTokenTypeAt(M))||s.getRange(L,M,"\n").indexOf(b)>-1)return!1;var T=x.lastIndexOf(y,e.ch),A=-1==T?-1:x.slice(0,e.ch).indexOf(b,T+y.length);if(-1!=T&&-1!=A&&A+b.length!=e.ch)return!1;A=C.indexOf(b,i.ch);var O=C.slice(i.ch).lastIndexOf(y,A-i.ch);return T=-1==A||-1==O?-1:i.ch+O,(-1==A||-1==T||T==i.ch)&&(s.operation(function(){s.replaceRange("",r(u,S-(p&&C.slice(S-p.length,S)==p?p.length:0)),r(u,S+b.length));var e=k+y.length;if(p&&x.slice(e,e+p.length)==p&&(e+=p.length),s.replaceRange("",r(f,k),r(f,e)),w)for(var t=f+1;t<=u;++t){var i=s.getLine(t),o=i.indexOf(w);if(-1!=o&&!n.test(i.slice(0,o))){var a=o+w.length;p&&i.slice(a,a+p.length)==p&&(a+=p.length),s.replaceRange("",r(t,o),r(t,a))}}}),!0)})}(n(0))},function(e,t,n){!function(e){var t={pairs:"()[]{}''\"\"",triples:"",explode:"[]{}"},n=e.Pos;function r(e,n){return"pairs"==n&&"string"==typeof e?e:"object"==typeof e&&null!=e[n]?e[n]:t[n]}e.defineOption("autoCloseBrackets",!1,function(t,n,a){a&&a!=e.Init&&(t.removeKeyMap(i),t.state.closeBrackets=null),n&&(o(r(n,"pairs")),t.state.closeBrackets=n,t.addKeyMap(i))});var i={Backspace:function(t){var i=l(t);if(!i||t.getOption("disableInput"))return e.Pass;for(var o=r(i,"pairs"),a=t.listSelections(),s=0;s=0;s--){var f=a[s].head;t.replaceRange("",n(f.line,f.ch-1),n(f.line,f.ch+1),"+delete")}},Enter:function(t){var n=l(t),i=n&&r(n,"explode");if(!i||t.getOption("disableInput"))return e.Pass;for(var o=t.listSelections(),a=0;a1&&d.indexOf(i)>=0&&t.getRange(n(b.line,b.ch-2),b)==i+i){if(b.ch>2&&/\bstring/.test(t.getTokenTypeAt(n(b.line,b.ch-2))))return e.Pass;v="addFour"}else if(h){var x=0==b.ch?" ":t.getRange(n(b.line,b.ch-1),b);if(e.isWordChar(w)||x==i||e.isWordChar(x))return e.Pass;v="both"}else{if(!m||t.getLine(b.line).length!=b.ch&&!s(w,a)&&!/\s/.test(w))return e.Pass;v="both"}else v=h&&u(t,b)?"both":d.indexOf(i)>=0&&t.getRange(b,n(b.line,b.ch+3))==i+i+i?"skipThree":"skip";if(f){if(f!=v)return e.Pass}else f=v}var k=c%2?a.charAt(c-1):i,C=c%2?i:a.charAt(c+1);t.operation(function(){if("skip"==f)t.execCommand("goCharRight");else if("skipThree"==f)for(var r=0;r<3;r++)t.execCommand("goCharRight");else if("surround"==f){for(var i=t.getSelections(),r=0;r0,{anchor:new n(o.anchor.line,o.anchor.ch+(a?-1:1)),head:new n(o.head.line,o.head.ch+(a?1:-1))});t.setSelections(i)}else"both"==f?(t.replaceSelection(k+C,null),t.triggerElectric(k+C),t.execCommand("goCharLeft")):"addFour"==f&&(t.replaceSelection(k+k+k+k,"before"),t.execCommand("goCharRight"));var o,a})}(i,t)}}function l(e){var t=e.state.closeBrackets;if(!t||t.override)return t;var n=e.getModeAt(e.getCursor());return n.closeBrackets||t}function s(e,t){var n=t.lastIndexOf(e);return n>-1&&n%2==1}function c(e,t){var r=e.getRange(n(t.line,t.ch-1),n(t.line,t.ch+1));return 2==r.length?r:null}function u(e,t){var r=e.getTokenAt(n(t.line,t.ch+1));return/\bstring/.test(r.type)&&r.start==t.ch&&(0==t.ch||!/\bstring/.test(e.getTokenTypeAt(t)))}o(t.pairs+"`")}(n(0))},function(e,t,n){!function(e){"use strict";function t(e){return e.state.search||(e.state.search=new function(){this.posFrom=this.posTo=this.lastQuery=this.query=null,this.overlay=null})}function n(e){return"string"==typeof e&&e==e.toLowerCase()}function r(e,t,r){return e.getSearchCursor(t,r,{caseFold:n(t),multiline:!0})}function i(e,t,n,r,i){e.openDialog?e.openDialog(t,i,{value:r,selectValueOnOpen:!0}):i(prompt(n,r))}function o(e){return e.replace(/\\(.)/g,function(e,t){return"n"==t?"\n":"r"==t?"\r":t})}function a(e){var t=e.match(/^\/(.*)\/([a-z]*)$/);if(t)try{e=new RegExp(t[1],-1==t[2].indexOf("i")?"":"i")}catch(e){}else e=o(e);return("string"==typeof e?""==e:e.test(""))&&(e=/x^/),e}var l;function s(e,t,r){t.queryText=r,t.query=a(r),e.removeOverlay(t.overlay,n(t.query)),t.overlay=function(e,t){return"string"==typeof e?e=new RegExp(e.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g,"\\$&"),t?"gi":"g"):e.global||(e=new RegExp(e.source,e.ignoreCase?"gi":"g")),{token:function(t){e.lastIndex=t.pos;var n=e.exec(t.string);if(n&&n.index==t.pos)return t.pos+=n[0].length||1,"searching";n?t.pos=n.index:t.skipToEnd()}}}(t.query,n(t.query)),e.addOverlay(t.overlay),e.showMatchesOnScrollbar&&(t.annotate&&(t.annotate.clear(),t.annotate=null),t.annotate=e.showMatchesOnScrollbar(t.query,n(t.query)))}function c(n,r,o,a){if(!l){let e=n.getWrapperElement().ownerDocument,t=e.createElement("input");t.type="search",t.placeholder=n.l10n("findCmd.promptMessage"),t.style.marginInlineStart="1em",t.style.marginInlineEnd="1em",t.style.flexGrow="1",t.addEventListener("focus",()=>t.select()),(l=e.createElement("div")).appendChild(t),l.style.display="flex"}var c=t(n);if(c.query)return u(n,r);var d=n.getSelection()||c.lastQuery;if(d instanceof RegExp&&"x^"==d.source&&(d=null),o&&n.openDialog){var h=null,p=function(t,r){e.e_stop(r),t&&(t!=c.queryText&&(s(n,c,t),c.posFrom=c.posTo=n.getCursor()),h&&(h.style.opacity=1),u(n,r.shiftKey,function(e,t){var r;t.line<3&&document.querySelector&&(r=n.display.wrapper.querySelector(".CodeMirror-dialog"))&&r.getBoundingClientRect().bottom-4>n.cursorCoords(t,"window").top&&((h=r).style.opacity=.4)}))};!function(e,t,n,r,i){e.openDialog(t,r,{value:n,selectValueOnOpen:!0,closeOnEnter:!1,onClose:function(){f(e)},onKeyDown:i})}(n,l,d,p,function(r,i){var o=e.keyName(r),a=n.getOption("extraKeys"),l=a&&a[o]||e.keyMap[n.getOption("keyMap")][o];"findNext"==l||"findPrev"==l||"findPersistentNext"==l||"findPersistentPrev"==l?(e.e_stop(r),s(n,t(n),i),n.execCommand(l)):"find"!=l&&"findPersistent"!=l||(e.e_stop(r),p(i,r))}),a&&d&&(s(n,c,d),u(n,r))}else i(n,l,"Search for:",d,function(e){e&&!c.query&&n.operation(function(){s(n,c,e),c.posFrom=c.posTo=n.getCursor(),u(n,r)})})}function u(n,i,o){n.operation(function(){var a=t(n),l=r(n,a.query,i?a.posFrom:a.posTo);(l.find(i)||(l=r(n,a.query,i?e.Pos(n.lastLine()):e.Pos(n.firstLine(),0))).find(i))&&(n.setSelection(l.from(),l.to()),n.scrollIntoView({from:l.from(),to:l.to()},20),a.posFrom=l.from(),a.posTo=l.to(),o&&o(l.from(),l.to()))})}function f(e){e.operation(function(){var n=t(e);n.lastQuery=n.query,n.query&&(n.query=n.queryText=null,e.removeOverlay(n.overlay),n.annotate&&(n.annotate.clear(),n.annotate=null))})}function d(e,t,n){e.operation(function(){for(var i=r(e,t);i.findNext();)if("string"!=typeof t){var o=e.getRange(i.from(),i.to()).match(t);i.replace(n.replace(/\$(\d)/g,function(e,t){return o[t]}))}else i.replace(n)})}function h(e,n){if(e.getOption("readOnly"))return;var l=e.getSelection()||t(e).lastQuery;let s=e.getWrapperElement().ownerDocument,c=s.createElement("span");c.classList.add("CodeMirror-search-label"),c.textContent=n?"Replace all:":"Replace:";let u=s.createDocumentFragment();u.appendChild(c.cloneNode(!0));let h=s.createElement("input");h.setAttribute("type","text"),h.setAttribute("style","width: 10em"),h.classList.add("CodeMirror-search-field"),u.appendChild(h);let p=s.createElement("span");p.setAttribute("style","color: #888"),p.classList.add("CodeMirror-search-hint"),p.textContent="(Use /re/ syntax for regexp search)",u.appendChild(p),i(e,u,c,l,function(t){if(!t)return;t=a(t);let l=s.createDocumentFragment(),u=c.cloneNode(!1);u.textContent="With:",l.appendChild(u);let h=s.createElement("input");h.setAttribute("type","text"),h.setAttribute("style","width: 10em"),h.classList.add("CodeMirror-search-field"),l.appendChild(h),i(e,l,"Replace with:","",function(i){if(i=o(i),n)d(e,t,i);else{f(e);var a=r(e,t,e.getCursor("from")),l=function(){var n,o=a.from();if(!(n=a.findNext())&&(a=r(e,t),!(n=a.findNext())||o&&a.from().line==o.line&&a.from().ch==o.ch))return;e.setSelection(a.from(),a.to()),e.scrollIntoView({from:a.from(),to:a.to()});let f=s.createDocumentFragment(),h=c.cloneNode(!1);h.textContent="Replace?",f.appendChild(h);let p=s.createElement("button");p.textContent="Yes",f.appendChild(p);let m=s.createElement("button");m.textContent="No",f.appendChild(m);let g=s.createElement("button");g.textContent="All",f.appendChild(g);let v=s.createElement("button");v.textContent="Stop",f.appendChild(v),function(e,t,n,r){e.openConfirm?e.openConfirm(t,r):confirm(n)&&r[0]()}(e,f,"Replace?",[function(){u(n)},l,function(){d(e,t,i)}])},u=function(e){a.replace("string"==typeof t?i:i.replace(/\$(\d)/g,function(t,n){return e[n]})),l()};l()}})})}e.commands.find=function(e){f(e),c(e)},e.commands.findPersistent=function(e){f(e),c(e,!1,!0)},e.commands.findPersistentNext=function(e){c(e,!1,!0,!0)},e.commands.findPersistentPrev=function(e){c(e,!0,!0,!0)},e.commands.findNext=c,e.commands.findPrev=function(e){c(e,!0)},e.commands.clearSearch=f,e.commands.replace=h,e.commands.replaceAll=function(e){h(e,!0)}}(n(0),n(1),n(5))},function(e,t,n){n(5),n(1),n(25),n(4),n(24),n(23),n(3),n(2),n(7),n(22),n(21),n(20),n(19),n(18),n(17),n(16),n(15),n(14),n(13),n(12),n(6),n(11),n(10),n(9),n(8),e.exports=n(0)}]); \ No newline at end of file +var CodeMirror = +/******/ (function(modules) { // webpackBootstrap +/******/ // The module cache +/******/ var installedModules = {}; + +/******/ // The require function +/******/ function __webpack_require__(moduleId) { + +/******/ // Check if module is in cache +/******/ if(installedModules[moduleId]) +/******/ return installedModules[moduleId].exports; + +/******/ // Create a new module (and put it into the cache) +/******/ var module = installedModules[moduleId] = { +/******/ exports: {}, +/******/ id: moduleId, +/******/ loaded: false +/******/ }; + +/******/ // Execute the module function +/******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__); + +/******/ // Flag the module as loaded +/******/ module.loaded = true; + +/******/ // Return the exports of the module +/******/ return module.exports; +/******/ } + + +/******/ // expose the modules object (__webpack_modules__) +/******/ __webpack_require__.m = modules; + +/******/ // expose the module cache +/******/ __webpack_require__.c = installedModules; + +/******/ // __webpack_public_path__ +/******/ __webpack_require__.p = ""; + +/******/ // Load entry module and return exports +/******/ return __webpack_require__(0); +/******/ }) +/************************************************************************/ +/******/ ([ +/* 0 */ +/***/ (function(module, exports, __webpack_require__) { + + __webpack_require__(1); + __webpack_require__(3); + __webpack_require__(4); + __webpack_require__(5); + __webpack_require__(6); + __webpack_require__(7); + __webpack_require__(8); + __webpack_require__(9); + __webpack_require__(10); + __webpack_require__(11); + __webpack_require__(12); + __webpack_require__(13); + __webpack_require__(14); + __webpack_require__(15); + __webpack_require__(16); + __webpack_require__(17); + __webpack_require__(18); + __webpack_require__(19); + __webpack_require__(20); + __webpack_require__(21); + __webpack_require__(22); + __webpack_require__(23); + __webpack_require__(24); + __webpack_require__(25); + __webpack_require__(26); + __webpack_require__(27); + module.exports = __webpack_require__(2); + + +/***/ }), +/* 1 */ +/***/ (function(module, exports, __webpack_require__) { + + // CodeMirror, copyright (c) by Marijn Haverbeke and others + // Distributed under an MIT license: http://codemirror.net/LICENSE + + // Open simple dialogs on top of an editor. Relies on dialog.css. + + (function(mod) { + if (true) // CommonJS + mod(__webpack_require__(2)); + else if (typeof define == "function" && define.amd) // AMD + define(["../../lib/codemirror"], mod); + else // Plain browser env + mod(CodeMirror); + })(function(CodeMirror) { + function dialogDiv(cm, template, bottom) { + var wrap = cm.getWrapperElement(); + var dialog; + dialog = wrap.appendChild(document.createElement("div")); + if (bottom) + dialog.className = "CodeMirror-dialog CodeMirror-dialog-bottom"; + else + dialog.className = "CodeMirror-dialog CodeMirror-dialog-top"; + + if (typeof template == "string") { + dialog.innerHTML = template; + } else { // Assuming it's a detached DOM element. + dialog.appendChild(template); + } + return dialog; + } + + function closeNotification(cm, newVal) { + if (cm.state.currentNotificationClose) + cm.state.currentNotificationClose(); + cm.state.currentNotificationClose = newVal; + } + + CodeMirror.defineExtension("openDialog", function(template, callback, options) { + if (!options) options = {}; + + closeNotification(this, null); + + var dialog = dialogDiv(this, template, options.bottom); + var closed = false, me = this; + function close(newVal) { + if (typeof newVal == 'string') { + inp.value = newVal; + } else { + if (closed) return; + closed = true; + dialog.parentNode.removeChild(dialog); + me.focus(); + + if (options.onClose) options.onClose(dialog); + } + } + + var inp = dialog.getElementsByTagName("input")[0], button; + if (inp) { + inp.focus(); + + if (options.value) { + inp.value = options.value; + if (options.selectValueOnOpen !== false) { + inp.select(); + } + } + + if (options.onInput) + CodeMirror.on(inp, "input", function(e) { options.onInput(e, inp.value, close);}); + if (options.onKeyUp) + CodeMirror.on(inp, "keyup", function(e) {options.onKeyUp(e, inp.value, close);}); + + CodeMirror.on(inp, "keydown", function(e) { + if (options && options.onKeyDown && options.onKeyDown(e, inp.value, close)) { return; } + if (e.keyCode == 27 || (options.closeOnEnter !== false && e.keyCode == 13)) { + inp.blur(); + CodeMirror.e_stop(e); + close(); + } + if (e.keyCode == 13) callback(inp.value, e); + }); + + if (options.closeOnBlur !== false) CodeMirror.on(inp, "blur", close); + } else if (button = dialog.getElementsByTagName("button")[0]) { + CodeMirror.on(button, "click", function() { + close(); + me.focus(); + }); + + if (options.closeOnBlur !== false) CodeMirror.on(button, "blur", close); + + button.focus(); + } + return close; + }); + + CodeMirror.defineExtension("openConfirm", function(template, callbacks, options) { + closeNotification(this, null); + var dialog = dialogDiv(this, template, options && options.bottom); + var buttons = dialog.getElementsByTagName("button"); + var closed = false, me = this, blurring = 1; + function close() { + if (closed) return; + closed = true; + dialog.parentNode.removeChild(dialog); + me.focus(); + } + buttons[0].focus(); + for (var i = 0; i < buttons.length; ++i) { + var b = buttons[i]; + (function(callback) { + CodeMirror.on(b, "click", function(e) { + CodeMirror.e_preventDefault(e); + close(); + if (callback) callback(me); + }); + })(callbacks[i]); + CodeMirror.on(b, "blur", function() { + --blurring; + setTimeout(function() { if (blurring <= 0) close(); }, 200); + }); + CodeMirror.on(b, "focus", function() { ++blurring; }); + } + }); + + /* + * openNotification + * Opens a notification, that can be closed with an optional timer + * (default 5000ms timer) and always closes on click. + * + * If a notification is opened while another is opened, it will close the + * currently opened one and open the new one immediately. + */ + CodeMirror.defineExtension("openNotification", function(template, options) { + closeNotification(this, close); + var dialog = dialogDiv(this, template, options && options.bottom); + var closed = false, doneTimer; + var duration = options && typeof options.duration !== "undefined" ? options.duration : 5000; + + function close() { + if (closed) return; + closed = true; + clearTimeout(doneTimer); + dialog.parentNode.removeChild(dialog); + } + + CodeMirror.on(dialog, 'click', function(e) { + CodeMirror.e_preventDefault(e); + close(); + }); + + if (duration) + doneTimer = setTimeout(close, duration); + + return close; + }); + }); + + +/***/ }), +/* 2 */ +/***/ (function(module, exports, __webpack_require__) { + + // CodeMirror, copyright (c) by Marijn Haverbeke and others + // Distributed under an MIT license: http://codemirror.net/LICENSE + + // This is CodeMirror (http://codemirror.net), a code editor + // implemented in JavaScript on top of the browser's DOM. + // + // You can find some technical background for some of the code below + // at http://marijnhaverbeke.nl/blog/#cm-internals . + + (function (global, factory) { + true ? module.exports = factory() : + typeof define === 'function' && define.amd ? define(factory) : + (global.CodeMirror = factory()); + }(this, (function () { 'use strict'; + + // Kludges for bugs and behavior differences that can't be feature + // detected are enabled based on userAgent etc sniffing. + var userAgent = navigator.userAgent + var platform = navigator.platform + + var gecko = /gecko\/\d/i.test(userAgent) + var ie_upto10 = /MSIE \d/.test(userAgent) + var ie_11up = /Trident\/(?:[7-9]|\d{2,})\..*rv:(\d+)/.exec(userAgent) + var edge = /Edge\/(\d+)/.exec(userAgent) + var ie = ie_upto10 || ie_11up || edge + var ie_version = ie && (ie_upto10 ? document.documentMode || 6 : +(edge || ie_11up)[1]) + var webkit = !edge && /WebKit\//.test(userAgent) + var qtwebkit = webkit && /Qt\/\d+\.\d+/.test(userAgent) + var chrome = !edge && /Chrome\//.test(userAgent) + var presto = /Opera\//.test(userAgent) + var safari = /Apple Computer/.test(navigator.vendor) + var mac_geMountainLion = /Mac OS X 1\d\D([8-9]|\d\d)\D/.test(userAgent) + var phantom = /PhantomJS/.test(userAgent) + + var ios = !edge && /AppleWebKit/.test(userAgent) && /Mobile\/\w+/.test(userAgent) + var android = /Android/.test(userAgent) + // This is woefully incomplete. Suggestions for alternative methods welcome. + var mobile = ios || android || /webOS|BlackBerry|Opera Mini|Opera Mobi|IEMobile/i.test(userAgent) + var mac = ios || /Mac/.test(platform) + var chromeOS = /\bCrOS\b/.test(userAgent) + var windows = /win/i.test(platform) + + var presto_version = presto && userAgent.match(/Version\/(\d*\.\d*)/) + if (presto_version) { presto_version = Number(presto_version[1]) } + if (presto_version && presto_version >= 15) { presto = false; webkit = true } + // Some browsers use the wrong event properties to signal cmd/ctrl on OS X + var flipCtrlCmd = mac && (qtwebkit || presto && (presto_version == null || presto_version < 12.11)) + var captureRightClick = gecko || (ie && ie_version >= 9) + + function classTest(cls) { return new RegExp("(^|\\s)" + cls + "(?:$|\\s)\\s*") } + + var rmClass = function(node, cls) { + var current = node.className + var match = classTest(cls).exec(current) + if (match) { + var after = current.slice(match.index + match[0].length) + node.className = current.slice(0, match.index) + (after ? match[1] + after : "") + } + } + + function removeChildren(e) { + for (var count = e.childNodes.length; count > 0; --count) + { e.removeChild(e.firstChild) } + return e + } + + function removeChildrenAndAdd(parent, e) { + return removeChildren(parent).appendChild(e) + } + + function elt(tag, content, className, style) { + var e = document.createElement(tag) + if (className) { e.className = className } + if (style) { e.style.cssText = style } + if (typeof content == "string") { e.appendChild(document.createTextNode(content)) } + else if (content) { for (var i = 0; i < content.length; ++i) { e.appendChild(content[i]) } } + return e + } + // wrapper for elt, which removes the elt from the accessibility tree + function eltP(tag, content, className, style) { + var e = elt(tag, content, className, style) + e.setAttribute("role", "presentation") + return e + } + + var range + if (document.createRange) { range = function(node, start, end, endNode) { + var r = document.createRange() + r.setEnd(endNode || node, end) + r.setStart(node, start) + return r + } } + else { range = function(node, start, end) { + var r = document.body.createTextRange() + try { r.moveToElementText(node.parentNode) } + catch(e) { return r } + r.collapse(true) + r.moveEnd("character", end) + r.moveStart("character", start) + return r + } } + + function contains(parent, child) { + if (child.nodeType == 3) // Android browser always returns false when child is a textnode + { child = child.parentNode } + if (parent.contains) + { return parent.contains(child) } + do { + if (child.nodeType == 11) { child = child.host } + if (child == parent) { return true } + } while (child = child.parentNode) + } + + function activeElt() { + // IE and Edge may throw an "Unspecified Error" when accessing document.activeElement. + // IE < 10 will throw when accessed while the page is loading or in an iframe. + // IE > 9 and Edge will throw when accessed in an iframe if document.body is unavailable. + var activeElement + try { + activeElement = document.activeElement + } catch(e) { + activeElement = document.body || null + } + while (activeElement && activeElement.shadowRoot && activeElement.shadowRoot.activeElement) + { activeElement = activeElement.shadowRoot.activeElement } + return activeElement + } + + function addClass(node, cls) { + var current = node.className + if (!classTest(cls).test(current)) { node.className += (current ? " " : "") + cls } + } + function joinClasses(a, b) { + var as = a.split(" ") + for (var i = 0; i < as.length; i++) + { if (as[i] && !classTest(as[i]).test(b)) { b += " " + as[i] } } + return b + } + + var selectInput = function(node) { node.select() } + if (ios) // Mobile Safari apparently has a bug where select() is broken. + { selectInput = function(node) { node.selectionStart = 0; node.selectionEnd = node.value.length } } + else if (ie) // Suppress mysterious IE10 errors + { selectInput = function(node) { try { node.select() } catch(_e) {} } } + + function bind(f) { + var args = Array.prototype.slice.call(arguments, 1) + return function(){return f.apply(null, args)} + } + + function copyObj(obj, target, overwrite) { + if (!target) { target = {} } + for (var prop in obj) + { if (obj.hasOwnProperty(prop) && (overwrite !== false || !target.hasOwnProperty(prop))) + { target[prop] = obj[prop] } } + return target + } + + // Counts the column offset in a string, taking tabs into account. + // Used mostly to find indentation. + function countColumn(string, end, tabSize, startIndex, startValue) { + if (end == null) { + end = string.search(/[^\s\u00a0]/) + if (end == -1) { end = string.length } + } + for (var i = startIndex || 0, n = startValue || 0;;) { + var nextTab = string.indexOf("\t", i) + if (nextTab < 0 || nextTab >= end) + { return n + (end - i) } + n += nextTab - i + n += tabSize - (n % tabSize) + i = nextTab + 1 + } + } + + var Delayed = function() {this.id = null}; + Delayed.prototype.set = function (ms, f) { + clearTimeout(this.id) + this.id = setTimeout(f, ms) + }; + + function indexOf(array, elt) { + for (var i = 0; i < array.length; ++i) + { if (array[i] == elt) { return i } } + return -1 + } + + // Number of pixels added to scroller and sizer to hide scrollbar + var scrollerGap = 30 + + // Returned or thrown by various protocols to signal 'I'm not + // handling this'. + var Pass = {toString: function(){return "CodeMirror.Pass"}} + + // Reused option objects for setSelection & friends + var sel_dontScroll = {scroll: false}; + var sel_mouse = {origin: "*mouse"}; + var sel_move = {origin: "+move"}; + // The inverse of countColumn -- find the offset that corresponds to + // a particular column. + function findColumn(string, goal, tabSize) { + for (var pos = 0, col = 0;;) { + var nextTab = string.indexOf("\t", pos) + if (nextTab == -1) { nextTab = string.length } + var skipped = nextTab - pos + if (nextTab == string.length || col + skipped >= goal) + { return pos + Math.min(skipped, goal - col) } + col += nextTab - pos + col += tabSize - (col % tabSize) + pos = nextTab + 1 + if (col >= goal) { return pos } + } + } + + var spaceStrs = [""] + function spaceStr(n) { + while (spaceStrs.length <= n) + { spaceStrs.push(lst(spaceStrs) + " ") } + return spaceStrs[n] + } + + function lst(arr) { return arr[arr.length-1] } + + function map(array, f) { + var out = [] + for (var i = 0; i < array.length; i++) { out[i] = f(array[i], i) } + return out + } + + function insertSorted(array, value, score) { + var pos = 0, priority = score(value) + while (pos < array.length && score(array[pos]) <= priority) { pos++ } + array.splice(pos, 0, value) + } + + function nothing() {} + + function createObj(base, props) { + var inst + if (Object.create) { + inst = Object.create(base) + } else { + nothing.prototype = base + inst = new nothing() + } + if (props) { copyObj(props, inst) } + return inst + } + + var nonASCIISingleCaseWordChar = /[\u00df\u0587\u0590-\u05f4\u0600-\u06ff\u3040-\u309f\u30a0-\u30ff\u3400-\u4db5\u4e00-\u9fcc\uac00-\ud7af]/ + function isWordCharBasic(ch) { + return /\w/.test(ch) || ch > "\x80" && + (ch.toUpperCase() != ch.toLowerCase() || nonASCIISingleCaseWordChar.test(ch)) + } + function isWordChar(ch, helper) { + if (!helper) { return isWordCharBasic(ch) } + if (helper.source.indexOf("\\w") > -1 && isWordCharBasic(ch)) { return true } + return helper.test(ch) + } + + function isEmpty(obj) { + for (var n in obj) { if (obj.hasOwnProperty(n) && obj[n]) { return false } } + return true + } + + // Extending unicode characters. A series of a non-extending char + + // any number of extending chars is treated as a single unit as far + // as editing and measuring is concerned. This is not fully correct, + // since some scripts/fonts/browsers also treat other configurations + // of code points as a group. + var extendingChars = /[\u0300-\u036f\u0483-\u0489\u0591-\u05bd\u05bf\u05c1\u05c2\u05c4\u05c5\u05c7\u0610-\u061a\u064b-\u065e\u0670\u06d6-\u06dc\u06de-\u06e4\u06e7\u06e8\u06ea-\u06ed\u0711\u0730-\u074a\u07a6-\u07b0\u07eb-\u07f3\u0816-\u0819\u081b-\u0823\u0825-\u0827\u0829-\u082d\u0900-\u0902\u093c\u0941-\u0948\u094d\u0951-\u0955\u0962\u0963\u0981\u09bc\u09be\u09c1-\u09c4\u09cd\u09d7\u09e2\u09e3\u0a01\u0a02\u0a3c\u0a41\u0a42\u0a47\u0a48\u0a4b-\u0a4d\u0a51\u0a70\u0a71\u0a75\u0a81\u0a82\u0abc\u0ac1-\u0ac5\u0ac7\u0ac8\u0acd\u0ae2\u0ae3\u0b01\u0b3c\u0b3e\u0b3f\u0b41-\u0b44\u0b4d\u0b56\u0b57\u0b62\u0b63\u0b82\u0bbe\u0bc0\u0bcd\u0bd7\u0c3e-\u0c40\u0c46-\u0c48\u0c4a-\u0c4d\u0c55\u0c56\u0c62\u0c63\u0cbc\u0cbf\u0cc2\u0cc6\u0ccc\u0ccd\u0cd5\u0cd6\u0ce2\u0ce3\u0d3e\u0d41-\u0d44\u0d4d\u0d57\u0d62\u0d63\u0dca\u0dcf\u0dd2-\u0dd4\u0dd6\u0ddf\u0e31\u0e34-\u0e3a\u0e47-\u0e4e\u0eb1\u0eb4-\u0eb9\u0ebb\u0ebc\u0ec8-\u0ecd\u0f18\u0f19\u0f35\u0f37\u0f39\u0f71-\u0f7e\u0f80-\u0f84\u0f86\u0f87\u0f90-\u0f97\u0f99-\u0fbc\u0fc6\u102d-\u1030\u1032-\u1037\u1039\u103a\u103d\u103e\u1058\u1059\u105e-\u1060\u1071-\u1074\u1082\u1085\u1086\u108d\u109d\u135f\u1712-\u1714\u1732-\u1734\u1752\u1753\u1772\u1773\u17b7-\u17bd\u17c6\u17c9-\u17d3\u17dd\u180b-\u180d\u18a9\u1920-\u1922\u1927\u1928\u1932\u1939-\u193b\u1a17\u1a18\u1a56\u1a58-\u1a5e\u1a60\u1a62\u1a65-\u1a6c\u1a73-\u1a7c\u1a7f\u1b00-\u1b03\u1b34\u1b36-\u1b3a\u1b3c\u1b42\u1b6b-\u1b73\u1b80\u1b81\u1ba2-\u1ba5\u1ba8\u1ba9\u1c2c-\u1c33\u1c36\u1c37\u1cd0-\u1cd2\u1cd4-\u1ce0\u1ce2-\u1ce8\u1ced\u1dc0-\u1de6\u1dfd-\u1dff\u200c\u200d\u20d0-\u20f0\u2cef-\u2cf1\u2de0-\u2dff\u302a-\u302f\u3099\u309a\ua66f-\ua672\ua67c\ua67d\ua6f0\ua6f1\ua802\ua806\ua80b\ua825\ua826\ua8c4\ua8e0-\ua8f1\ua926-\ua92d\ua947-\ua951\ua980-\ua982\ua9b3\ua9b6-\ua9b9\ua9bc\uaa29-\uaa2e\uaa31\uaa32\uaa35\uaa36\uaa43\uaa4c\uaab0\uaab2-\uaab4\uaab7\uaab8\uaabe\uaabf\uaac1\uabe5\uabe8\uabed\udc00-\udfff\ufb1e\ufe00-\ufe0f\ufe20-\ufe26\uff9e\uff9f]/ + function isExtendingChar(ch) { return ch.charCodeAt(0) >= 768 && extendingChars.test(ch) } + + // Returns a number from the range [`0`; `str.length`] unless `pos` is outside that range. + function skipExtendingChars(str, pos, dir) { + while ((dir < 0 ? pos > 0 : pos < str.length) && isExtendingChar(str.charAt(pos))) { pos += dir } + return pos + } + + // Returns the value from the range [`from`; `to`] that satisfies + // `pred` and is closest to `from`. Assumes that at least `to` + // satisfies `pred`. Supports `from` being greater than `to`. + function findFirst(pred, from, to) { + // At any point we are certain `to` satisfies `pred`, don't know + // whether `from` does. + var dir = from > to ? -1 : 1 + for (;;) { + if (from == to) { return from } + var midF = (from + to) / 2, mid = dir < 0 ? Math.ceil(midF) : Math.floor(midF) + if (mid == from) { return pred(mid) ? from : to } + if (pred(mid)) { to = mid } + else { from = mid + dir } + } + } + + // The display handles the DOM integration, both for input reading + // and content drawing. It holds references to DOM nodes and + // display-related state. + + function Display(place, doc, input) { + var d = this + this.input = input + + // Covers bottom-right square when both scrollbars are present. + d.scrollbarFiller = elt("div", null, "CodeMirror-scrollbar-filler") + d.scrollbarFiller.setAttribute("cm-not-content", "true") + // Covers bottom of gutter when coverGutterNextToScrollbar is on + // and h scrollbar is present. + d.gutterFiller = elt("div", null, "CodeMirror-gutter-filler") + d.gutterFiller.setAttribute("cm-not-content", "true") + // Will contain the actual code, positioned to cover the viewport. + d.lineDiv = eltP("div", null, "CodeMirror-code") + // Elements are added to these to represent selection and cursors. + d.selectionDiv = elt("div", null, null, "position: relative; z-index: 1") + d.cursorDiv = elt("div", null, "CodeMirror-cursors") + // A visibility: hidden element used to find the size of things. + d.measure = elt("div", null, "CodeMirror-measure") + // When lines outside of the viewport are measured, they are drawn in this. + d.lineMeasure = elt("div", null, "CodeMirror-measure") + // Wraps everything that needs to exist inside the vertically-padded coordinate system + d.lineSpace = eltP("div", [d.measure, d.lineMeasure, d.selectionDiv, d.cursorDiv, d.lineDiv], + null, "position: relative; outline: none") + var lines = eltP("div", [d.lineSpace], "CodeMirror-lines") + // Moved around its parent to cover visible view. + d.mover = elt("div", [lines], null, "position: relative") + // Set to the height of the document, allowing scrolling. + d.sizer = elt("div", [d.mover], "CodeMirror-sizer") + d.sizerWidth = null + // Behavior of elts with overflow: auto and padding is + // inconsistent across browsers. This is used to ensure the + // scrollable area is big enough. + d.heightForcer = elt("div", null, null, "position: absolute; height: " + scrollerGap + "px; width: 1px;") + // Will contain the gutters, if any. + d.gutters = elt("div", null, "CodeMirror-gutters") + d.lineGutter = null + // Actual scrollable element. + d.scroller = elt("div", [d.sizer, d.heightForcer, d.gutters], "CodeMirror-scroll") + d.scroller.setAttribute("tabIndex", "-1") + // The element in which the editor lives. + d.wrapper = elt("div", [d.scrollbarFiller, d.gutterFiller, d.scroller], "CodeMirror") + + // Work around IE7 z-index bug (not perfect, hence IE7 not really being supported) + if (ie && ie_version < 8) { d.gutters.style.zIndex = -1; d.scroller.style.paddingRight = 0 } + if (!webkit && !(gecko && mobile)) { d.scroller.draggable = true } + + if (place) { + if (place.appendChild) { place.appendChild(d.wrapper) } + else { place(d.wrapper) } + } + + // Current rendered range (may be bigger than the view window). + d.viewFrom = d.viewTo = doc.first + d.reportedViewFrom = d.reportedViewTo = doc.first + // Information about the rendered lines. + d.view = [] + d.renderedView = null + // Holds info about a single rendered line when it was rendered + // for measurement, while not in view. + d.externalMeasured = null + // Empty space (in pixels) above the view + d.viewOffset = 0 + d.lastWrapHeight = d.lastWrapWidth = 0 + d.updateLineNumbers = null + + d.nativeBarWidth = d.barHeight = d.barWidth = 0 + d.scrollbarsClipped = false + + // Used to only resize the line number gutter when necessary (when + // the amount of lines crosses a boundary that makes its width change) + d.lineNumWidth = d.lineNumInnerWidth = d.lineNumChars = null + // Set to true when a non-horizontal-scrolling line widget is + // added. As an optimization, line widget aligning is skipped when + // this is false. + d.alignWidgets = false + + d.cachedCharWidth = d.cachedTextHeight = d.cachedPaddingH = null + + // Tracks the maximum line length so that the horizontal scrollbar + // can be kept static when scrolling. + d.maxLine = null + d.maxLineLength = 0 + d.maxLineChanged = false + + // Used for measuring wheel scrolling granularity + d.wheelDX = d.wheelDY = d.wheelStartX = d.wheelStartY = null + + // True when shift is held down. + d.shift = false + + // Used to track whether anything happened since the context menu + // was opened. + d.selForContextMenu = null + + d.activeTouch = null + + input.init(d) + } + + // Find the line object corresponding to the given line number. + function getLine(doc, n) { + n -= doc.first + if (n < 0 || n >= doc.size) { throw new Error("There is no line " + (n + doc.first) + " in the document.") } + var chunk = doc + while (!chunk.lines) { + for (var i = 0;; ++i) { + var child = chunk.children[i], sz = child.chunkSize() + if (n < sz) { chunk = child; break } + n -= sz + } + } + return chunk.lines[n] + } + + // Get the part of a document between two positions, as an array of + // strings. + function getBetween(doc, start, end) { + var out = [], n = start.line + doc.iter(start.line, end.line + 1, function (line) { + var text = line.text + if (n == end.line) { text = text.slice(0, end.ch) } + if (n == start.line) { text = text.slice(start.ch) } + out.push(text) + ++n + }) + return out + } + // Get the lines between from and to, as array of strings. + function getLines(doc, from, to) { + var out = [] + doc.iter(from, to, function (line) { out.push(line.text) }) // iter aborts when callback returns truthy value + return out + } + + // Update the height of a line, propagating the height change + // upwards to parent nodes. + function updateLineHeight(line, height) { + var diff = height - line.height + if (diff) { for (var n = line; n; n = n.parent) { n.height += diff } } + } + + // Given a line object, find its line number by walking up through + // its parent links. + function lineNo(line) { + if (line.parent == null) { return null } + var cur = line.parent, no = indexOf(cur.lines, line) + for (var chunk = cur.parent; chunk; cur = chunk, chunk = chunk.parent) { + for (var i = 0;; ++i) { + if (chunk.children[i] == cur) { break } + no += chunk.children[i].chunkSize() + } + } + return no + cur.first + } + + // Find the line at the given vertical position, using the height + // information in the document tree. + function lineAtHeight(chunk, h) { + var n = chunk.first + outer: do { + for (var i$1 = 0; i$1 < chunk.children.length; ++i$1) { + var child = chunk.children[i$1], ch = child.height + if (h < ch) { chunk = child; continue outer } + h -= ch + n += child.chunkSize() + } + return n + } while (!chunk.lines) + var i = 0 + for (; i < chunk.lines.length; ++i) { + var line = chunk.lines[i], lh = line.height + if (h < lh) { break } + h -= lh + } + return n + i + } + + function isLine(doc, l) {return l >= doc.first && l < doc.first + doc.size} + + function lineNumberFor(options, i) { + return String(options.lineNumberFormatter(i + options.firstLineNumber)) + } + + // A Pos instance represents a position within the text. + function Pos(line, ch, sticky) { + if ( sticky === void 0 ) sticky = null; + + if (!(this instanceof Pos)) { return new Pos(line, ch, sticky) } + this.line = line + this.ch = ch + this.sticky = sticky + } + + // Compare two positions, return 0 if they are the same, a negative + // number when a is less, and a positive number otherwise. + function cmp(a, b) { return a.line - b.line || a.ch - b.ch } + + function equalCursorPos(a, b) { return a.sticky == b.sticky && cmp(a, b) == 0 } + + function copyPos(x) {return Pos(x.line, x.ch)} + function maxPos(a, b) { return cmp(a, b) < 0 ? b : a } + function minPos(a, b) { return cmp(a, b) < 0 ? a : b } + + // Most of the external API clips given positions to make sure they + // actually exist within the document. + function clipLine(doc, n) {return Math.max(doc.first, Math.min(n, doc.first + doc.size - 1))} + function clipPos(doc, pos) { + if (pos.line < doc.first) { return Pos(doc.first, 0) } + var last = doc.first + doc.size - 1 + if (pos.line > last) { return Pos(last, getLine(doc, last).text.length) } + return clipToLen(pos, getLine(doc, pos.line).text.length) + } + function clipToLen(pos, linelen) { + var ch = pos.ch + if (ch == null || ch > linelen) { return Pos(pos.line, linelen) } + else if (ch < 0) { return Pos(pos.line, 0) } + else { return pos } + } + function clipPosArray(doc, array) { + var out = [] + for (var i = 0; i < array.length; i++) { out[i] = clipPos(doc, array[i]) } + return out + } + + // Optimize some code when these features are not used. + var sawReadOnlySpans = false; + var sawCollapsedSpans = false; + function seeReadOnlySpans() { + sawReadOnlySpans = true + } + + function seeCollapsedSpans() { + sawCollapsedSpans = true + } + + // TEXTMARKER SPANS + + function MarkedSpan(marker, from, to) { + this.marker = marker + this.from = from; this.to = to + } + + // Search an array of spans for a span matching the given marker. + function getMarkedSpanFor(spans, marker) { + if (spans) { for (var i = 0; i < spans.length; ++i) { + var span = spans[i] + if (span.marker == marker) { return span } + } } + } + // Remove a span from an array, returning undefined if no spans are + // left (we don't store arrays for lines without spans). + function removeMarkedSpan(spans, span) { + var r + for (var i = 0; i < spans.length; ++i) + { if (spans[i] != span) { (r || (r = [])).push(spans[i]) } } + return r + } + // Add a span to a line. + function addMarkedSpan(line, span) { + line.markedSpans = line.markedSpans ? line.markedSpans.concat([span]) : [span] + span.marker.attachLine(line) + } + + // Used for the algorithm that adjusts markers for a change in the + // document. These functions cut an array of spans at a given + // character position, returning an array of remaining chunks (or + // undefined if nothing remains). + function markedSpansBefore(old, startCh, isInsert) { + var nw + if (old) { for (var i = 0; i < old.length; ++i) { + var span = old[i], marker = span.marker + var startsBefore = span.from == null || (marker.inclusiveLeft ? span.from <= startCh : span.from < startCh) + if (startsBefore || span.from == startCh && marker.type == "bookmark" && (!isInsert || !span.marker.insertLeft)) { + var endsAfter = span.to == null || (marker.inclusiveRight ? span.to >= startCh : span.to > startCh) + ;(nw || (nw = [])).push(new MarkedSpan(marker, span.from, endsAfter ? null : span.to)) + } + } } + return nw + } + function markedSpansAfter(old, endCh, isInsert) { + var nw + if (old) { for (var i = 0; i < old.length; ++i) { + var span = old[i], marker = span.marker + var endsAfter = span.to == null || (marker.inclusiveRight ? span.to >= endCh : span.to > endCh) + if (endsAfter || span.from == endCh && marker.type == "bookmark" && (!isInsert || span.marker.insertLeft)) { + var startsBefore = span.from == null || (marker.inclusiveLeft ? span.from <= endCh : span.from < endCh) + ;(nw || (nw = [])).push(new MarkedSpan(marker, startsBefore ? null : span.from - endCh, + span.to == null ? null : span.to - endCh)) + } + } } + return nw + } + + // Given a change object, compute the new set of marker spans that + // cover the line in which the change took place. Removes spans + // entirely within the change, reconnects spans belonging to the + // same marker that appear on both sides of the change, and cuts off + // spans partially within the change. Returns an array of span + // arrays with one element for each line in (after) the change. + function stretchSpansOverChange(doc, change) { + if (change.full) { return null } + var oldFirst = isLine(doc, change.from.line) && getLine(doc, change.from.line).markedSpans + var oldLast = isLine(doc, change.to.line) && getLine(doc, change.to.line).markedSpans + if (!oldFirst && !oldLast) { return null } + + var startCh = change.from.ch, endCh = change.to.ch, isInsert = cmp(change.from, change.to) == 0 + // Get the spans that 'stick out' on both sides + var first = markedSpansBefore(oldFirst, startCh, isInsert) + var last = markedSpansAfter(oldLast, endCh, isInsert) + + // Next, merge those two ends + var sameLine = change.text.length == 1, offset = lst(change.text).length + (sameLine ? startCh : 0) + if (first) { + // Fix up .to properties of first + for (var i = 0; i < first.length; ++i) { + var span = first[i] + if (span.to == null) { + var found = getMarkedSpanFor(last, span.marker) + if (!found) { span.to = startCh } + else if (sameLine) { span.to = found.to == null ? null : found.to + offset } + } + } + } + if (last) { + // Fix up .from in last (or move them into first in case of sameLine) + for (var i$1 = 0; i$1 < last.length; ++i$1) { + var span$1 = last[i$1] + if (span$1.to != null) { span$1.to += offset } + if (span$1.from == null) { + var found$1 = getMarkedSpanFor(first, span$1.marker) + if (!found$1) { + span$1.from = offset + if (sameLine) { (first || (first = [])).push(span$1) } + } + } else { + span$1.from += offset + if (sameLine) { (first || (first = [])).push(span$1) } + } + } + } + // Make sure we didn't create any zero-length spans + if (first) { first = clearEmptySpans(first) } + if (last && last != first) { last = clearEmptySpans(last) } + + var newMarkers = [first] + if (!sameLine) { + // Fill gap with whole-line-spans + var gap = change.text.length - 2, gapMarkers + if (gap > 0 && first) + { for (var i$2 = 0; i$2 < first.length; ++i$2) + { if (first[i$2].to == null) + { (gapMarkers || (gapMarkers = [])).push(new MarkedSpan(first[i$2].marker, null, null)) } } } + for (var i$3 = 0; i$3 < gap; ++i$3) + { newMarkers.push(gapMarkers) } + newMarkers.push(last) + } + return newMarkers + } + + // Remove spans that are empty and don't have a clearWhenEmpty + // option of false. + function clearEmptySpans(spans) { + for (var i = 0; i < spans.length; ++i) { + var span = spans[i] + if (span.from != null && span.from == span.to && span.marker.clearWhenEmpty !== false) + { spans.splice(i--, 1) } + } + if (!spans.length) { return null } + return spans + } + + // Used to 'clip' out readOnly ranges when making a change. + function removeReadOnlyRanges(doc, from, to) { + var markers = null + doc.iter(from.line, to.line + 1, function (line) { + if (line.markedSpans) { for (var i = 0; i < line.markedSpans.length; ++i) { + var mark = line.markedSpans[i].marker + if (mark.readOnly && (!markers || indexOf(markers, mark) == -1)) + { (markers || (markers = [])).push(mark) } + } } + }) + if (!markers) { return null } + var parts = [{from: from, to: to}] + for (var i = 0; i < markers.length; ++i) { + var mk = markers[i], m = mk.find(0) + for (var j = 0; j < parts.length; ++j) { + var p = parts[j] + if (cmp(p.to, m.from) < 0 || cmp(p.from, m.to) > 0) { continue } + var newParts = [j, 1], dfrom = cmp(p.from, m.from), dto = cmp(p.to, m.to) + if (dfrom < 0 || !mk.inclusiveLeft && !dfrom) + { newParts.push({from: p.from, to: m.from}) } + if (dto > 0 || !mk.inclusiveRight && !dto) + { newParts.push({from: m.to, to: p.to}) } + parts.splice.apply(parts, newParts) + j += newParts.length - 3 + } + } + return parts + } + + // Connect or disconnect spans from a line. + function detachMarkedSpans(line) { + var spans = line.markedSpans + if (!spans) { return } + for (var i = 0; i < spans.length; ++i) + { spans[i].marker.detachLine(line) } + line.markedSpans = null + } + function attachMarkedSpans(line, spans) { + if (!spans) { return } + for (var i = 0; i < spans.length; ++i) + { spans[i].marker.attachLine(line) } + line.markedSpans = spans + } + + // Helpers used when computing which overlapping collapsed span + // counts as the larger one. + function extraLeft(marker) { return marker.inclusiveLeft ? -1 : 0 } + function extraRight(marker) { return marker.inclusiveRight ? 1 : 0 } + + // Returns a number indicating which of two overlapping collapsed + // spans is larger (and thus includes the other). Falls back to + // comparing ids when the spans cover exactly the same range. + function compareCollapsedMarkers(a, b) { + var lenDiff = a.lines.length - b.lines.length + if (lenDiff != 0) { return lenDiff } + var aPos = a.find(), bPos = b.find() + var fromCmp = cmp(aPos.from, bPos.from) || extraLeft(a) - extraLeft(b) + if (fromCmp) { return -fromCmp } + var toCmp = cmp(aPos.to, bPos.to) || extraRight(a) - extraRight(b) + if (toCmp) { return toCmp } + return b.id - a.id + } + + // Find out whether a line ends or starts in a collapsed span. If + // so, return the marker for that span. + function collapsedSpanAtSide(line, start) { + var sps = sawCollapsedSpans && line.markedSpans, found + if (sps) { for (var sp = (void 0), i = 0; i < sps.length; ++i) { + sp = sps[i] + if (sp.marker.collapsed && (start ? sp.from : sp.to) == null && + (!found || compareCollapsedMarkers(found, sp.marker) < 0)) + { found = sp.marker } + } } + return found + } + function collapsedSpanAtStart(line) { return collapsedSpanAtSide(line, true) } + function collapsedSpanAtEnd(line) { return collapsedSpanAtSide(line, false) } + + // Test whether there exists a collapsed span that partially + // overlaps (covers the start or end, but not both) of a new span. + // Such overlap is not allowed. + function conflictingCollapsedRange(doc, lineNo, from, to, marker) { + var line = getLine(doc, lineNo) + var sps = sawCollapsedSpans && line.markedSpans + if (sps) { for (var i = 0; i < sps.length; ++i) { + var sp = sps[i] + if (!sp.marker.collapsed) { continue } + var found = sp.marker.find(0) + var fromCmp = cmp(found.from, from) || extraLeft(sp.marker) - extraLeft(marker) + var toCmp = cmp(found.to, to) || extraRight(sp.marker) - extraRight(marker) + if (fromCmp >= 0 && toCmp <= 0 || fromCmp <= 0 && toCmp >= 0) { continue } + if (fromCmp <= 0 && (sp.marker.inclusiveRight && marker.inclusiveLeft ? cmp(found.to, from) >= 0 : cmp(found.to, from) > 0) || + fromCmp >= 0 && (sp.marker.inclusiveRight && marker.inclusiveLeft ? cmp(found.from, to) <= 0 : cmp(found.from, to) < 0)) + { return true } + } } + } + + // A visual line is a line as drawn on the screen. Folding, for + // example, can cause multiple logical lines to appear on the same + // visual line. This finds the start of the visual line that the + // given line is part of (usually that is the line itself). + function visualLine(line) { + var merged + while (merged = collapsedSpanAtStart(line)) + { line = merged.find(-1, true).line } + return line + } + + function visualLineEnd(line) { + var merged + while (merged = collapsedSpanAtEnd(line)) + { line = merged.find(1, true).line } + return line + } + + // Returns an array of logical lines that continue the visual line + // started by the argument, or undefined if there are no such lines. + function visualLineContinued(line) { + var merged, lines + while (merged = collapsedSpanAtEnd(line)) { + line = merged.find(1, true).line + ;(lines || (lines = [])).push(line) + } + return lines + } + + // Get the line number of the start of the visual line that the + // given line number is part of. + function visualLineNo(doc, lineN) { + var line = getLine(doc, lineN), vis = visualLine(line) + if (line == vis) { return lineN } + return lineNo(vis) + } + + // Get the line number of the start of the next visual line after + // the given line. + function visualLineEndNo(doc, lineN) { + if (lineN > doc.lastLine()) { return lineN } + var line = getLine(doc, lineN), merged + if (!lineIsHidden(doc, line)) { return lineN } + while (merged = collapsedSpanAtEnd(line)) + { line = merged.find(1, true).line } + return lineNo(line) + 1 + } + + // Compute whether a line is hidden. Lines count as hidden when they + // are part of a visual line that starts with another line, or when + // they are entirely covered by collapsed, non-widget span. + function lineIsHidden(doc, line) { + var sps = sawCollapsedSpans && line.markedSpans + if (sps) { for (var sp = (void 0), i = 0; i < sps.length; ++i) { + sp = sps[i] + if (!sp.marker.collapsed) { continue } + if (sp.from == null) { return true } + if (sp.marker.widgetNode) { continue } + if (sp.from == 0 && sp.marker.inclusiveLeft && lineIsHiddenInner(doc, line, sp)) + { return true } + } } + } + function lineIsHiddenInner(doc, line, span) { + if (span.to == null) { + var end = span.marker.find(1, true) + return lineIsHiddenInner(doc, end.line, getMarkedSpanFor(end.line.markedSpans, span.marker)) + } + if (span.marker.inclusiveRight && span.to == line.text.length) + { return true } + for (var sp = (void 0), i = 0; i < line.markedSpans.length; ++i) { + sp = line.markedSpans[i] + if (sp.marker.collapsed && !sp.marker.widgetNode && sp.from == span.to && + (sp.to == null || sp.to != span.from) && + (sp.marker.inclusiveLeft || span.marker.inclusiveRight) && + lineIsHiddenInner(doc, line, sp)) { return true } + } + } + + // Find the height above the given line. + function heightAtLine(lineObj) { + lineObj = visualLine(lineObj) + + var h = 0, chunk = lineObj.parent + for (var i = 0; i < chunk.lines.length; ++i) { + var line = chunk.lines[i] + if (line == lineObj) { break } + else { h += line.height } + } + for (var p = chunk.parent; p; chunk = p, p = chunk.parent) { + for (var i$1 = 0; i$1 < p.children.length; ++i$1) { + var cur = p.children[i$1] + if (cur == chunk) { break } + else { h += cur.height } + } + } + return h + } + + // Compute the character length of a line, taking into account + // collapsed ranges (see markText) that might hide parts, and join + // other lines onto it. + function lineLength(line) { + if (line.height == 0) { return 0 } + var len = line.text.length, merged, cur = line + while (merged = collapsedSpanAtStart(cur)) { + var found = merged.find(0, true) + cur = found.from.line + len += found.from.ch - found.to.ch + } + cur = line + while (merged = collapsedSpanAtEnd(cur)) { + var found$1 = merged.find(0, true) + len -= cur.text.length - found$1.from.ch + cur = found$1.to.line + len += cur.text.length - found$1.to.ch + } + return len + } + + // Find the longest line in the document. + function findMaxLine(cm) { + var d = cm.display, doc = cm.doc + d.maxLine = getLine(doc, doc.first) + d.maxLineLength = lineLength(d.maxLine) + d.maxLineChanged = true + doc.iter(function (line) { + var len = lineLength(line) + if (len > d.maxLineLength) { + d.maxLineLength = len + d.maxLine = line + } + }) + } + + // BIDI HELPERS + + function iterateBidiSections(order, from, to, f) { + if (!order) { return f(from, to, "ltr", 0) } + var found = false + for (var i = 0; i < order.length; ++i) { + var part = order[i] + if (part.from < to && part.to > from || from == to && part.to == from) { + f(Math.max(part.from, from), Math.min(part.to, to), part.level == 1 ? "rtl" : "ltr", i) + found = true + } + } + if (!found) { f(from, to, "ltr") } + } + + var bidiOther = null + function getBidiPartAt(order, ch, sticky) { + var found + bidiOther = null + for (var i = 0; i < order.length; ++i) { + var cur = order[i] + if (cur.from < ch && cur.to > ch) { return i } + if (cur.to == ch) { + if (cur.from != cur.to && sticky == "before") { found = i } + else { bidiOther = i } + } + if (cur.from == ch) { + if (cur.from != cur.to && sticky != "before") { found = i } + else { bidiOther = i } + } + } + return found != null ? found : bidiOther + } + + // Bidirectional ordering algorithm + // See http://unicode.org/reports/tr9/tr9-13.html for the algorithm + // that this (partially) implements. + + // One-char codes used for character types: + // L (L): Left-to-Right + // R (R): Right-to-Left + // r (AL): Right-to-Left Arabic + // 1 (EN): European Number + // + (ES): European Number Separator + // % (ET): European Number Terminator + // n (AN): Arabic Number + // , (CS): Common Number Separator + // m (NSM): Non-Spacing Mark + // b (BN): Boundary Neutral + // s (B): Paragraph Separator + // t (S): Segment Separator + // w (WS): Whitespace + // N (ON): Other Neutrals + + // Returns null if characters are ordered as they appear + // (left-to-right), or an array of sections ({from, to, level} + // objects) in the order in which they occur visually. + var bidiOrdering = (function() { + // Character types for codepoints 0 to 0xff + var lowTypes = "bbbbbbbbbtstwsbbbbbbbbbbbbbbssstwNN%%%NNNNNN,N,N1111111111NNNNNNNLLLLLLLLLLLLLLLLLLLLLLLLLLNNNNNNLLLLLLLLLLLLLLLLLLLLLLLLLLNNNNbbbbbbsbbbbbbbbbbbbbbbbbbbbbbbbbb,N%%%%NNNNLNNNNN%%11NLNNN1LNNNNNLLLLLLLLLLLLLLLLLLLLLLLNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLN" + // Character types for codepoints 0x600 to 0x6f9 + var arabicTypes = "nnnnnnNNr%%r,rNNmmmmmmmmmmmrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrmmmmmmmmmmmmmmmmmmmmmnnnnnnnnnn%nnrrrmrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrmmmmmmmnNmmmmmmrrmmNmmmmrr1111111111" + function charType(code) { + if (code <= 0xf7) { return lowTypes.charAt(code) } + else if (0x590 <= code && code <= 0x5f4) { return "R" } + else if (0x600 <= code && code <= 0x6f9) { return arabicTypes.charAt(code - 0x600) } + else if (0x6ee <= code && code <= 0x8ac) { return "r" } + else if (0x2000 <= code && code <= 0x200b) { return "w" } + else if (code == 0x200c) { return "b" } + else { return "L" } + } + + var bidiRE = /[\u0590-\u05f4\u0600-\u06ff\u0700-\u08ac]/ + var isNeutral = /[stwN]/, isStrong = /[LRr]/, countsAsLeft = /[Lb1n]/, countsAsNum = /[1n]/ + + function BidiSpan(level, from, to) { + this.level = level + this.from = from; this.to = to + } + + return function(str, direction) { + var outerType = direction == "ltr" ? "L" : "R" + + if (str.length == 0 || direction == "ltr" && !bidiRE.test(str)) { return false } + var len = str.length, types = [] + for (var i = 0; i < len; ++i) + { types.push(charType(str.charCodeAt(i))) } + + // W1. Examine each non-spacing mark (NSM) in the level run, and + // change the type of the NSM to the type of the previous + // character. If the NSM is at the start of the level run, it will + // get the type of sor. + for (var i$1 = 0, prev = outerType; i$1 < len; ++i$1) { + var type = types[i$1] + if (type == "m") { types[i$1] = prev } + else { prev = type } + } + + // W2. Search backwards from each instance of a European number + // until the first strong type (R, L, AL, or sor) is found. If an + // AL is found, change the type of the European number to Arabic + // number. + // W3. Change all ALs to R. + for (var i$2 = 0, cur = outerType; i$2 < len; ++i$2) { + var type$1 = types[i$2] + if (type$1 == "1" && cur == "r") { types[i$2] = "n" } + else if (isStrong.test(type$1)) { cur = type$1; if (type$1 == "r") { types[i$2] = "R" } } + } + + // W4. A single European separator between two European numbers + // changes to a European number. A single common separator between + // two numbers of the same type changes to that type. + for (var i$3 = 1, prev$1 = types[0]; i$3 < len - 1; ++i$3) { + var type$2 = types[i$3] + if (type$2 == "+" && prev$1 == "1" && types[i$3+1] == "1") { types[i$3] = "1" } + else if (type$2 == "," && prev$1 == types[i$3+1] && + (prev$1 == "1" || prev$1 == "n")) { types[i$3] = prev$1 } + prev$1 = type$2 + } + + // W5. A sequence of European terminators adjacent to European + // numbers changes to all European numbers. + // W6. Otherwise, separators and terminators change to Other + // Neutral. + for (var i$4 = 0; i$4 < len; ++i$4) { + var type$3 = types[i$4] + if (type$3 == ",") { types[i$4] = "N" } + else if (type$3 == "%") { + var end = (void 0) + for (end = i$4 + 1; end < len && types[end] == "%"; ++end) {} + var replace = (i$4 && types[i$4-1] == "!") || (end < len && types[end] == "1") ? "1" : "N" + for (var j = i$4; j < end; ++j) { types[j] = replace } + i$4 = end - 1 + } + } + + // W7. Search backwards from each instance of a European number + // until the first strong type (R, L, or sor) is found. If an L is + // found, then change the type of the European number to L. + for (var i$5 = 0, cur$1 = outerType; i$5 < len; ++i$5) { + var type$4 = types[i$5] + if (cur$1 == "L" && type$4 == "1") { types[i$5] = "L" } + else if (isStrong.test(type$4)) { cur$1 = type$4 } + } + + // N1. A sequence of neutrals takes the direction of the + // surrounding strong text if the text on both sides has the same + // direction. European and Arabic numbers act as if they were R in + // terms of their influence on neutrals. Start-of-level-run (sor) + // and end-of-level-run (eor) are used at level run boundaries. + // N2. Any remaining neutrals take the embedding direction. + for (var i$6 = 0; i$6 < len; ++i$6) { + if (isNeutral.test(types[i$6])) { + var end$1 = (void 0) + for (end$1 = i$6 + 1; end$1 < len && isNeutral.test(types[end$1]); ++end$1) {} + var before = (i$6 ? types[i$6-1] : outerType) == "L" + var after = (end$1 < len ? types[end$1] : outerType) == "L" + var replace$1 = before == after ? (before ? "L" : "R") : outerType + for (var j$1 = i$6; j$1 < end$1; ++j$1) { types[j$1] = replace$1 } + i$6 = end$1 - 1 + } + } + + // Here we depart from the documented algorithm, in order to avoid + // building up an actual levels array. Since there are only three + // levels (0, 1, 2) in an implementation that doesn't take + // explicit embedding into account, we can build up the order on + // the fly, without following the level-based algorithm. + var order = [], m + for (var i$7 = 0; i$7 < len;) { + if (countsAsLeft.test(types[i$7])) { + var start = i$7 + for (++i$7; i$7 < len && countsAsLeft.test(types[i$7]); ++i$7) {} + order.push(new BidiSpan(0, start, i$7)) + } else { + var pos = i$7, at = order.length + for (++i$7; i$7 < len && types[i$7] != "L"; ++i$7) {} + for (var j$2 = pos; j$2 < i$7;) { + if (countsAsNum.test(types[j$2])) { + if (pos < j$2) { order.splice(at, 0, new BidiSpan(1, pos, j$2)) } + var nstart = j$2 + for (++j$2; j$2 < i$7 && countsAsNum.test(types[j$2]); ++j$2) {} + order.splice(at, 0, new BidiSpan(2, nstart, j$2)) + pos = j$2 + } else { ++j$2 } + } + if (pos < i$7) { order.splice(at, 0, new BidiSpan(1, pos, i$7)) } + } + } + if (direction == "ltr") { + if (order[0].level == 1 && (m = str.match(/^\s+/))) { + order[0].from = m[0].length + order.unshift(new BidiSpan(0, 0, m[0].length)) + } + if (lst(order).level == 1 && (m = str.match(/\s+$/))) { + lst(order).to -= m[0].length + order.push(new BidiSpan(0, len - m[0].length, len)) + } + } + + return direction == "rtl" ? order.reverse() : order + } + })() + + // Get the bidi ordering for the given line (and cache it). Returns + // false for lines that are fully left-to-right, and an array of + // BidiSpan objects otherwise. + function getOrder(line, direction) { + var order = line.order + if (order == null) { order = line.order = bidiOrdering(line.text, direction) } + return order + } + + // EVENT HANDLING + + // Lightweight event framework. on/off also work on DOM nodes, + // registering native DOM handlers. + + var noHandlers = [] + + var on = function(emitter, type, f) { + if (emitter.addEventListener) { + emitter.addEventListener(type, f, false) + } else if (emitter.attachEvent) { + emitter.attachEvent("on" + type, f) + } else { + var map = emitter._handlers || (emitter._handlers = {}) + map[type] = (map[type] || noHandlers).concat(f) + } + } + + function getHandlers(emitter, type) { + return emitter._handlers && emitter._handlers[type] || noHandlers + } + + function off(emitter, type, f) { + if (emitter.removeEventListener) { + emitter.removeEventListener(type, f, false) + } else if (emitter.detachEvent) { + emitter.detachEvent("on" + type, f) + } else { + var map = emitter._handlers, arr = map && map[type] + if (arr) { + var index = indexOf(arr, f) + if (index > -1) + { map[type] = arr.slice(0, index).concat(arr.slice(index + 1)) } + } + } + } + + function signal(emitter, type /*, values...*/) { + var handlers = getHandlers(emitter, type) + if (!handlers.length) { return } + var args = Array.prototype.slice.call(arguments, 2) + for (var i = 0; i < handlers.length; ++i) { handlers[i].apply(null, args) } + } + + // The DOM events that CodeMirror handles can be overridden by + // registering a (non-DOM) handler on the editor for the event name, + // and preventDefault-ing the event in that handler. + function signalDOMEvent(cm, e, override) { + if (typeof e == "string") + { e = {type: e, preventDefault: function() { this.defaultPrevented = true }} } + signal(cm, override || e.type, cm, e) + return e_defaultPrevented(e) || e.codemirrorIgnore + } + + function signalCursorActivity(cm) { + var arr = cm._handlers && cm._handlers.cursorActivity + if (!arr) { return } + var set = cm.curOp.cursorActivityHandlers || (cm.curOp.cursorActivityHandlers = []) + for (var i = 0; i < arr.length; ++i) { if (indexOf(set, arr[i]) == -1) + { set.push(arr[i]) } } + } + + function hasHandler(emitter, type) { + return getHandlers(emitter, type).length > 0 + } + + // Add on and off methods to a constructor's prototype, to make + // registering events on such objects more convenient. + function eventMixin(ctor) { + ctor.prototype.on = function(type, f) {on(this, type, f)} + ctor.prototype.off = function(type, f) {off(this, type, f)} + } + + // Due to the fact that we still support jurassic IE versions, some + // compatibility wrappers are needed. + + function e_preventDefault(e) { + if (e.preventDefault) { e.preventDefault() } + else { e.returnValue = false } + } + function e_stopPropagation(e) { + if (e.stopPropagation) { e.stopPropagation() } + else { e.cancelBubble = true } + } + function e_defaultPrevented(e) { + return e.defaultPrevented != null ? e.defaultPrevented : e.returnValue == false + } + function e_stop(e) {e_preventDefault(e); e_stopPropagation(e)} + + function e_target(e) {return e.target || e.srcElement} + function e_button(e) { + var b = e.which + if (b == null) { + if (e.button & 1) { b = 1 } + else if (e.button & 2) { b = 3 } + else if (e.button & 4) { b = 2 } + } + if (mac && e.ctrlKey && b == 1) { b = 3 } + return b + } + + // Detect drag-and-drop + var dragAndDrop = function() { + // There is *some* kind of drag-and-drop support in IE6-8, but I + // couldn't get it to work yet. + if (ie && ie_version < 9) { return false } + var div = elt('div') + return "draggable" in div || "dragDrop" in div + }() + + var zwspSupported + function zeroWidthElement(measure) { + if (zwspSupported == null) { + var test = elt("span", "\u200b") + removeChildrenAndAdd(measure, elt("span", [test, document.createTextNode("x")])) + if (measure.firstChild.offsetHeight != 0) + { zwspSupported = test.offsetWidth <= 1 && test.offsetHeight > 2 && !(ie && ie_version < 8) } + } + var node = zwspSupported ? elt("span", "\u200b") : + elt("span", "\u00a0", null, "display: inline-block; width: 1px; margin-right: -1px") + node.setAttribute("cm-text", "") + return node + } + + // Feature-detect IE's crummy client rect reporting for bidi text + var badBidiRects + function hasBadBidiRects(measure) { + if (badBidiRects != null) { return badBidiRects } + var txt = removeChildrenAndAdd(measure, document.createTextNode("A\u062eA")) + var r0 = range(txt, 0, 1).getBoundingClientRect() + var r1 = range(txt, 1, 2).getBoundingClientRect() + removeChildren(measure) + if (!r0 || r0.left == r0.right) { return false } // Safari returns null in some cases (#2780) + return badBidiRects = (r1.right - r0.right < 3) + } + + // See if "".split is the broken IE version, if so, provide an + // alternative way to split lines. + var splitLinesAuto = "\n\nb".split(/\n/).length != 3 ? function (string) { + var pos = 0, result = [], l = string.length + while (pos <= l) { + var nl = string.indexOf("\n", pos) + if (nl == -1) { nl = string.length } + var line = string.slice(pos, string.charAt(nl - 1) == "\r" ? nl - 1 : nl) + var rt = line.indexOf("\r") + if (rt != -1) { + result.push(line.slice(0, rt)) + pos += rt + 1 + } else { + result.push(line) + pos = nl + 1 + } + } + return result + } : function (string) { return string.split(/\r\n?|\n/); } + + var hasSelection = window.getSelection ? function (te) { + try { return te.selectionStart != te.selectionEnd } + catch(e) { return false } + } : function (te) { + var range + try {range = te.ownerDocument.selection.createRange()} + catch(e) {} + if (!range || range.parentElement() != te) { return false } + return range.compareEndPoints("StartToEnd", range) != 0 + } + + var hasCopyEvent = (function () { + var e = elt("div") + if ("oncopy" in e) { return true } + e.setAttribute("oncopy", "return;") + return typeof e.oncopy == "function" + })() + + var badZoomedRects = null + function hasBadZoomedRects(measure) { + if (badZoomedRects != null) { return badZoomedRects } + var node = removeChildrenAndAdd(measure, elt("span", "x")) + var normal = node.getBoundingClientRect() + var fromRange = range(node, 0, 1).getBoundingClientRect() + return badZoomedRects = Math.abs(normal.left - fromRange.left) > 1 + } + + var modes = {}; + var mimeModes = {}; + // Extra arguments are stored as the mode's dependencies, which is + // used by (legacy) mechanisms like loadmode.js to automatically + // load a mode. (Preferred mechanism is the require/define calls.) + function defineMode(name, mode) { + if (arguments.length > 2) + { mode.dependencies = Array.prototype.slice.call(arguments, 2) } + modes[name] = mode + } + + function defineMIME(mime, spec) { + mimeModes[mime] = spec + } + + // Given a MIME type, a {name, ...options} config object, or a name + // string, return a mode config object. + function resolveMode(spec) { + if (typeof spec == "string" && mimeModes.hasOwnProperty(spec)) { + spec = mimeModes[spec] + } else if (spec && typeof spec.name == "string" && mimeModes.hasOwnProperty(spec.name)) { + var found = mimeModes[spec.name] + if (typeof found == "string") { found = {name: found} } + spec = createObj(found, spec) + spec.name = found.name + } else if (typeof spec == "string" && /^[\w\-]+\/[\w\-]+\+xml$/.test(spec)) { + return resolveMode("application/xml") + } else if (typeof spec == "string" && /^[\w\-]+\/[\w\-]+\+json$/.test(spec)) { + return resolveMode("application/json") + } + if (typeof spec == "string") { return {name: spec} } + else { return spec || {name: "null"} } + } + + // Given a mode spec (anything that resolveMode accepts), find and + // initialize an actual mode object. + function getMode(options, spec) { + spec = resolveMode(spec) + var mfactory = modes[spec.name] + if (!mfactory) { return getMode(options, "text/plain") } + var modeObj = mfactory(options, spec) + if (modeExtensions.hasOwnProperty(spec.name)) { + var exts = modeExtensions[spec.name] + for (var prop in exts) { + if (!exts.hasOwnProperty(prop)) { continue } + if (modeObj.hasOwnProperty(prop)) { modeObj["_" + prop] = modeObj[prop] } + modeObj[prop] = exts[prop] + } + } + modeObj.name = spec.name + if (spec.helperType) { modeObj.helperType = spec.helperType } + if (spec.modeProps) { for (var prop$1 in spec.modeProps) + { modeObj[prop$1] = spec.modeProps[prop$1] } } + + return modeObj + } + + // This can be used to attach properties to mode objects from + // outside the actual mode definition. + var modeExtensions = {} + function extendMode(mode, properties) { + var exts = modeExtensions.hasOwnProperty(mode) ? modeExtensions[mode] : (modeExtensions[mode] = {}) + copyObj(properties, exts) + } + + function copyState(mode, state) { + if (state === true) { return state } + if (mode.copyState) { return mode.copyState(state) } + var nstate = {} + for (var n in state) { + var val = state[n] + if (val instanceof Array) { val = val.concat([]) } + nstate[n] = val + } + return nstate + } + + // Given a mode and a state (for that mode), find the inner mode and + // state at the position that the state refers to. + function innerMode(mode, state) { + var info + while (mode.innerMode) { + info = mode.innerMode(state) + if (!info || info.mode == mode) { break } + state = info.state + mode = info.mode + } + return info || {mode: mode, state: state} + } + + function startState(mode, a1, a2) { + return mode.startState ? mode.startState(a1, a2) : true + } + + // STRING STREAM + + // Fed to the mode parsers, provides helper functions to make + // parsers more succinct. + + var StringStream = function(string, tabSize, lineOracle) { + this.pos = this.start = 0 + this.string = string + this.tabSize = tabSize || 8 + this.lastColumnPos = this.lastColumnValue = 0 + this.lineStart = 0 + this.lineOracle = lineOracle + }; + + StringStream.prototype.eol = function () {return this.pos >= this.string.length}; + StringStream.prototype.sol = function () {return this.pos == this.lineStart}; + StringStream.prototype.peek = function () {return this.string.charAt(this.pos) || undefined}; + StringStream.prototype.next = function () { + if (this.pos < this.string.length) + { return this.string.charAt(this.pos++) } + }; + StringStream.prototype.eat = function (match) { + var ch = this.string.charAt(this.pos) + var ok + if (typeof match == "string") { ok = ch == match } + else { ok = ch && (match.test ? match.test(ch) : match(ch)) } + if (ok) {++this.pos; return ch} + }; + StringStream.prototype.eatWhile = function (match) { + var start = this.pos + while (this.eat(match)){} + return this.pos > start + }; + StringStream.prototype.eatSpace = function () { + var this$1 = this; + + var start = this.pos + while (/[\s\u00a0]/.test(this.string.charAt(this.pos))) { ++this$1.pos } + return this.pos > start + }; + StringStream.prototype.skipToEnd = function () {this.pos = this.string.length}; + StringStream.prototype.skipTo = function (ch) { + var found = this.string.indexOf(ch, this.pos) + if (found > -1) {this.pos = found; return true} + }; + StringStream.prototype.backUp = function (n) {this.pos -= n}; + StringStream.prototype.column = function () { + if (this.lastColumnPos < this.start) { + this.lastColumnValue = countColumn(this.string, this.start, this.tabSize, this.lastColumnPos, this.lastColumnValue) + this.lastColumnPos = this.start + } + return this.lastColumnValue - (this.lineStart ? countColumn(this.string, this.lineStart, this.tabSize) : 0) + }; + StringStream.prototype.indentation = function () { + return countColumn(this.string, null, this.tabSize) - + (this.lineStart ? countColumn(this.string, this.lineStart, this.tabSize) : 0) + }; + StringStream.prototype.match = function (pattern, consume, caseInsensitive) { + if (typeof pattern == "string") { + var cased = function (str) { return caseInsensitive ? str.toLowerCase() : str; } + var substr = this.string.substr(this.pos, pattern.length) + if (cased(substr) == cased(pattern)) { + if (consume !== false) { this.pos += pattern.length } + return true + } + } else { + var match = this.string.slice(this.pos).match(pattern) + if (match && match.index > 0) { return null } + if (match && consume !== false) { this.pos += match[0].length } + return match + } + }; + StringStream.prototype.current = function (){return this.string.slice(this.start, this.pos)}; + StringStream.prototype.hideFirstChars = function (n, inner) { + this.lineStart += n + try { return inner() } + finally { this.lineStart -= n } + }; + StringStream.prototype.lookAhead = function (n) { + var oracle = this.lineOracle + return oracle && oracle.lookAhead(n) + }; + StringStream.prototype.baseToken = function () { + var oracle = this.lineOracle + return oracle && oracle.baseToken(this.pos) + }; + + var SavedContext = function(state, lookAhead) { + this.state = state + this.lookAhead = lookAhead + }; + + var Context = function(doc, state, line, lookAhead) { + this.state = state + this.doc = doc + this.line = line + this.maxLookAhead = lookAhead || 0 + this.baseTokens = null + this.baseTokenPos = 1 + }; + + Context.prototype.lookAhead = function (n) { + var line = this.doc.getLine(this.line + n) + if (line != null && n > this.maxLookAhead) { this.maxLookAhead = n } + return line + }; + + Context.prototype.baseToken = function (n) { + var this$1 = this; + + if (!this.baseTokens) { return null } + while (this.baseTokens[this.baseTokenPos] <= n) + { this$1.baseTokenPos += 2 } + var type = this.baseTokens[this.baseTokenPos + 1] + return {type: type && type.replace(/( |^)overlay .*/, ""), + size: this.baseTokens[this.baseTokenPos] - n} + }; + + Context.prototype.nextLine = function () { + this.line++ + if (this.maxLookAhead > 0) { this.maxLookAhead-- } + }; + + Context.fromSaved = function (doc, saved, line) { + if (saved instanceof SavedContext) + { return new Context(doc, copyState(doc.mode, saved.state), line, saved.lookAhead) } + else + { return new Context(doc, copyState(doc.mode, saved), line) } + }; + + Context.prototype.save = function (copy) { + var state = copy !== false ? copyState(this.doc.mode, this.state) : this.state + return this.maxLookAhead > 0 ? new SavedContext(state, this.maxLookAhead) : state + }; + + + // Compute a style array (an array starting with a mode generation + // -- for invalidation -- followed by pairs of end positions and + // style strings), which is used to highlight the tokens on the + // line. + function highlightLine(cm, line, context, forceToEnd) { + // A styles array always starts with a number identifying the + // mode/overlays that it is based on (for easy invalidation). + var st = [cm.state.modeGen], lineClasses = {} + // Compute the base array of styles + runMode(cm, line.text, cm.doc.mode, context, function (end, style) { return st.push(end, style); }, + lineClasses, forceToEnd) + var state = context.state + + // Run overlays, adjust style array. + var loop = function ( o ) { + context.baseTokens = st + var overlay = cm.state.overlays[o], i = 1, at = 0 + context.state = true + runMode(cm, line.text, overlay.mode, context, function (end, style) { + var start = i + // Ensure there's a token end at the current position, and that i points at it + while (at < end) { + var i_end = st[i] + if (i_end > end) + { st.splice(i, 1, end, st[i+1], i_end) } + i += 2 + at = Math.min(end, i_end) + } + if (!style) { return } + if (overlay.opaque) { + st.splice(start, i - start, end, "overlay " + style) + i = start + 2 + } else { + for (; start < i; start += 2) { + var cur = st[start+1] + st[start+1] = (cur ? cur + " " : "") + "overlay " + style + } + } + }, lineClasses) + context.state = state + context.baseTokens = null + context.baseTokenPos = 1 + }; + + for (var o = 0; o < cm.state.overlays.length; ++o) loop( o ); + + return {styles: st, classes: lineClasses.bgClass || lineClasses.textClass ? lineClasses : null} + } + + function getLineStyles(cm, line, updateFrontier) { + if (!line.styles || line.styles[0] != cm.state.modeGen) { + var context = getContextBefore(cm, lineNo(line)) + var resetState = line.text.length > cm.options.maxHighlightLength && copyState(cm.doc.mode, context.state) + var result = highlightLine(cm, line, context) + if (resetState) { context.state = resetState } + line.stateAfter = context.save(!resetState) + line.styles = result.styles + if (result.classes) { line.styleClasses = result.classes } + else if (line.styleClasses) { line.styleClasses = null } + if (updateFrontier === cm.doc.highlightFrontier) + { cm.doc.modeFrontier = Math.max(cm.doc.modeFrontier, ++cm.doc.highlightFrontier) } + } + return line.styles + } + + function getContextBefore(cm, n, precise) { + var doc = cm.doc, display = cm.display + if (!doc.mode.startState) { return new Context(doc, true, n) } + var start = findStartLine(cm, n, precise) + var saved = start > doc.first && getLine(doc, start - 1).stateAfter + var context = saved ? Context.fromSaved(doc, saved, start) : new Context(doc, startState(doc.mode), start) + + doc.iter(start, n, function (line) { + processLine(cm, line.text, context) + var pos = context.line + line.stateAfter = pos == n - 1 || pos % 5 == 0 || pos >= display.viewFrom && pos < display.viewTo ? context.save() : null + context.nextLine() + }) + if (precise) { doc.modeFrontier = context.line } + return context + } + + // Lightweight form of highlight -- proceed over this line and + // update state, but don't save a style array. Used for lines that + // aren't currently visible. + function processLine(cm, text, context, startAt) { + var mode = cm.doc.mode + var stream = new StringStream(text, cm.options.tabSize, context) + stream.start = stream.pos = startAt || 0 + if (text == "") { callBlankLine(mode, context.state) } + while (!stream.eol()) { + readToken(mode, stream, context.state) + stream.start = stream.pos + } + } + + function callBlankLine(mode, state) { + if (mode.blankLine) { return mode.blankLine(state) } + if (!mode.innerMode) { return } + var inner = innerMode(mode, state) + if (inner.mode.blankLine) { return inner.mode.blankLine(inner.state) } + } + + function readToken(mode, stream, state, inner) { + for (var i = 0; i < 10; i++) { + if (inner) { inner[0] = innerMode(mode, state).mode } + var style = mode.token(stream, state) + if (stream.pos > stream.start) { return style } + } + throw new Error("Mode " + mode.name + " failed to advance stream.") + } + + var Token = function(stream, type, state) { + this.start = stream.start; this.end = stream.pos + this.string = stream.current() + this.type = type || null + this.state = state + }; + + // Utility for getTokenAt and getLineTokens + function takeToken(cm, pos, precise, asArray) { + var doc = cm.doc, mode = doc.mode, style + pos = clipPos(doc, pos) + var line = getLine(doc, pos.line), context = getContextBefore(cm, pos.line, precise) + var stream = new StringStream(line.text, cm.options.tabSize, context), tokens + if (asArray) { tokens = [] } + while ((asArray || stream.pos < pos.ch) && !stream.eol()) { + stream.start = stream.pos + style = readToken(mode, stream, context.state) + if (asArray) { tokens.push(new Token(stream, style, copyState(doc.mode, context.state))) } + } + return asArray ? tokens : new Token(stream, style, context.state) + } + + function extractLineClasses(type, output) { + if (type) { for (;;) { + var lineClass = type.match(/(?:^|\s+)line-(background-)?(\S+)/) + if (!lineClass) { break } + type = type.slice(0, lineClass.index) + type.slice(lineClass.index + lineClass[0].length) + var prop = lineClass[1] ? "bgClass" : "textClass" + if (output[prop] == null) + { output[prop] = lineClass[2] } + else if (!(new RegExp("(?:^|\s)" + lineClass[2] + "(?:$|\s)")).test(output[prop])) + { output[prop] += " " + lineClass[2] } + } } + return type + } + + // Run the given mode's parser over a line, calling f for each token. + function runMode(cm, text, mode, context, f, lineClasses, forceToEnd) { + var flattenSpans = mode.flattenSpans + if (flattenSpans == null) { flattenSpans = cm.options.flattenSpans } + var curStart = 0, curStyle = null + var stream = new StringStream(text, cm.options.tabSize, context), style + var inner = cm.options.addModeClass && [null] + if (text == "") { extractLineClasses(callBlankLine(mode, context.state), lineClasses) } + while (!stream.eol()) { + if (stream.pos > cm.options.maxHighlightLength) { + flattenSpans = false + if (forceToEnd) { processLine(cm, text, context, stream.pos) } + stream.pos = text.length + style = null + } else { + style = extractLineClasses(readToken(mode, stream, context.state, inner), lineClasses) + } + if (inner) { + var mName = inner[0].name + if (mName) { style = "m-" + (style ? mName + " " + style : mName) } + } + if (!flattenSpans || curStyle != style) { + while (curStart < stream.start) { + curStart = Math.min(stream.start, curStart + 5000) + f(curStart, curStyle) + } + curStyle = style + } + stream.start = stream.pos + } + while (curStart < stream.pos) { + // Webkit seems to refuse to render text nodes longer than 57444 + // characters, and returns inaccurate measurements in nodes + // starting around 5000 chars. + var pos = Math.min(stream.pos, curStart + 5000) + f(pos, curStyle) + curStart = pos + } + } + + // Finds the line to start with when starting a parse. Tries to + // find a line with a stateAfter, so that it can start with a + // valid state. If that fails, it returns the line with the + // smallest indentation, which tends to need the least context to + // parse correctly. + function findStartLine(cm, n, precise) { + var minindent, minline, doc = cm.doc + var lim = precise ? -1 : n - (cm.doc.mode.innerMode ? 1000 : 100) + for (var search = n; search > lim; --search) { + if (search <= doc.first) { return doc.first } + var line = getLine(doc, search - 1), after = line.stateAfter + if (after && (!precise || search + (after instanceof SavedContext ? after.lookAhead : 0) <= doc.modeFrontier)) + { return search } + var indented = countColumn(line.text, null, cm.options.tabSize) + if (minline == null || minindent > indented) { + minline = search - 1 + minindent = indented + } + } + return minline + } + + function retreatFrontier(doc, n) { + doc.modeFrontier = Math.min(doc.modeFrontier, n) + if (doc.highlightFrontier < n - 10) { return } + var start = doc.first + for (var line = n - 1; line > start; line--) { + var saved = getLine(doc, line).stateAfter + // change is on 3 + // state on line 1 looked ahead 2 -- so saw 3 + // test 1 + 2 < 3 should cover this + if (saved && (!(saved instanceof SavedContext) || line + saved.lookAhead < n)) { + start = line + 1 + break + } + } + doc.highlightFrontier = Math.min(doc.highlightFrontier, start) + } + + // LINE DATA STRUCTURE + + // Line objects. These hold state related to a line, including + // highlighting info (the styles array). + var Line = function(text, markedSpans, estimateHeight) { + this.text = text + attachMarkedSpans(this, markedSpans) + this.height = estimateHeight ? estimateHeight(this) : 1 + }; + + Line.prototype.lineNo = function () { return lineNo(this) }; + eventMixin(Line) + + // Change the content (text, markers) of a line. Automatically + // invalidates cached information and tries to re-estimate the + // line's height. + function updateLine(line, text, markedSpans, estimateHeight) { + line.text = text + if (line.stateAfter) { line.stateAfter = null } + if (line.styles) { line.styles = null } + if (line.order != null) { line.order = null } + detachMarkedSpans(line) + attachMarkedSpans(line, markedSpans) + var estHeight = estimateHeight ? estimateHeight(line) : 1 + if (estHeight != line.height) { updateLineHeight(line, estHeight) } + } + + // Detach a line from the document tree and its markers. + function cleanUpLine(line) { + line.parent = null + detachMarkedSpans(line) + } + + // Convert a style as returned by a mode (either null, or a string + // containing one or more styles) to a CSS style. This is cached, + // and also looks for line-wide styles. + var styleToClassCache = {}; + var styleToClassCacheWithMode = {}; + function interpretTokenStyle(style, options) { + if (!style || /^\s*$/.test(style)) { return null } + var cache = options.addModeClass ? styleToClassCacheWithMode : styleToClassCache + return cache[style] || + (cache[style] = style.replace(/\S+/g, "cm-$&")) + } + + // Render the DOM representation of the text of a line. Also builds + // up a 'line map', which points at the DOM nodes that represent + // specific stretches of text, and is used by the measuring code. + // The returned object contains the DOM node, this map, and + // information about line-wide styles that were set by the mode. + function buildLineContent(cm, lineView) { + // The padding-right forces the element to have a 'border', which + // is needed on Webkit to be able to get line-level bounding + // rectangles for it (in measureChar). + var content = eltP("span", null, null, webkit ? "padding-right: .1px" : null) + var builder = {pre: eltP("pre", [content], "CodeMirror-line"), content: content, + col: 0, pos: 0, cm: cm, + trailingSpace: false, + splitSpaces: (ie || webkit) && cm.getOption("lineWrapping")} + lineView.measure = {} + + // Iterate over the logical lines that make up this visual line. + for (var i = 0; i <= (lineView.rest ? lineView.rest.length : 0); i++) { + var line = i ? lineView.rest[i - 1] : lineView.line, order = (void 0) + builder.pos = 0 + builder.addToken = buildToken + // Optionally wire in some hacks into the token-rendering + // algorithm, to deal with browser quirks. + if (hasBadBidiRects(cm.display.measure) && (order = getOrder(line, cm.doc.direction))) + { builder.addToken = buildTokenBadBidi(builder.addToken, order) } + builder.map = [] + var allowFrontierUpdate = lineView != cm.display.externalMeasured && lineNo(line) + insertLineContent(line, builder, getLineStyles(cm, line, allowFrontierUpdate)) + if (line.styleClasses) { + if (line.styleClasses.bgClass) + { builder.bgClass = joinClasses(line.styleClasses.bgClass, builder.bgClass || "") } + if (line.styleClasses.textClass) + { builder.textClass = joinClasses(line.styleClasses.textClass, builder.textClass || "") } + } + + // Ensure at least a single node is present, for measuring. + if (builder.map.length == 0) + { builder.map.push(0, 0, builder.content.appendChild(zeroWidthElement(cm.display.measure))) } + + // Store the map and a cache object for the current logical line + if (i == 0) { + lineView.measure.map = builder.map + lineView.measure.cache = {} + } else { + ;(lineView.measure.maps || (lineView.measure.maps = [])).push(builder.map) + ;(lineView.measure.caches || (lineView.measure.caches = [])).push({}) + } + } + + // See issue #2901 + if (webkit) { + var last = builder.content.lastChild + if (/\bcm-tab\b/.test(last.className) || (last.querySelector && last.querySelector(".cm-tab"))) + { builder.content.className = "cm-tab-wrap-hack" } + } + + signal(cm, "renderLine", cm, lineView.line, builder.pre) + if (builder.pre.className) + { builder.textClass = joinClasses(builder.pre.className, builder.textClass || "") } + + return builder + } + + function defaultSpecialCharPlaceholder(ch) { + var token = elt("span", "\u2022", "cm-invalidchar") + token.title = "\\u" + ch.charCodeAt(0).toString(16) + token.setAttribute("aria-label", token.title) + return token + } + + // Build up the DOM representation for a single token, and add it to + // the line map. Takes care to render special characters separately. + function buildToken(builder, text, style, startStyle, endStyle, title, css) { + if (!text) { return } + var displayText = builder.splitSpaces ? splitSpaces(text, builder.trailingSpace) : text + var special = builder.cm.state.specialChars, mustWrap = false + var content + if (!special.test(text)) { + builder.col += text.length + content = document.createTextNode(displayText) + builder.map.push(builder.pos, builder.pos + text.length, content) + if (ie && ie_version < 9) { mustWrap = true } + builder.pos += text.length + } else { + content = document.createDocumentFragment() + var pos = 0 + while (true) { + special.lastIndex = pos + var m = special.exec(text) + var skipped = m ? m.index - pos : text.length - pos + if (skipped) { + var txt = document.createTextNode(displayText.slice(pos, pos + skipped)) + if (ie && ie_version < 9) { content.appendChild(elt("span", [txt])) } + else { content.appendChild(txt) } + builder.map.push(builder.pos, builder.pos + skipped, txt) + builder.col += skipped + builder.pos += skipped + } + if (!m) { break } + pos += skipped + 1 + var txt$1 = (void 0) + if (m[0] == "\t") { + var tabSize = builder.cm.options.tabSize, tabWidth = tabSize - builder.col % tabSize + txt$1 = content.appendChild(elt("span", spaceStr(tabWidth), "cm-tab")) + txt$1.setAttribute("role", "presentation") + txt$1.setAttribute("cm-text", "\t") + builder.col += tabWidth + } else if (m[0] == "\r" || m[0] == "\n") { + txt$1 = content.appendChild(elt("span", m[0] == "\r" ? "\u240d" : "\u2424", "cm-invalidchar")) + txt$1.setAttribute("cm-text", m[0]) + builder.col += 1 + } else { + txt$1 = builder.cm.options.specialCharPlaceholder(m[0]) + txt$1.setAttribute("cm-text", m[0]) + if (ie && ie_version < 9) { content.appendChild(elt("span", [txt$1])) } + else { content.appendChild(txt$1) } + builder.col += 1 + } + builder.map.push(builder.pos, builder.pos + 1, txt$1) + builder.pos++ + } + } + builder.trailingSpace = displayText.charCodeAt(text.length - 1) == 32 + if (style || startStyle || endStyle || mustWrap || css) { + var fullStyle = style || "" + if (startStyle) { fullStyle += startStyle } + if (endStyle) { fullStyle += endStyle } + var token = elt("span", [content], fullStyle, css) + if (title) { token.title = title } + return builder.content.appendChild(token) + } + builder.content.appendChild(content) + } + + function splitSpaces(text, trailingBefore) { + if (text.length > 1 && !/ /.test(text)) { return text } + var spaceBefore = trailingBefore, result = "" + for (var i = 0; i < text.length; i++) { + var ch = text.charAt(i) + if (ch == " " && spaceBefore && (i == text.length - 1 || text.charCodeAt(i + 1) == 32)) + { ch = "\u00a0" } + result += ch + spaceBefore = ch == " " + } + return result + } + + // Work around nonsense dimensions being reported for stretches of + // right-to-left text. + function buildTokenBadBidi(inner, order) { + return function (builder, text, style, startStyle, endStyle, title, css) { + style = style ? style + " cm-force-border" : "cm-force-border" + var start = builder.pos, end = start + text.length + for (;;) { + // Find the part that overlaps with the start of this text + var part = (void 0) + for (var i = 0; i < order.length; i++) { + part = order[i] + if (part.to > start && part.from <= start) { break } + } + if (part.to >= end) { return inner(builder, text, style, startStyle, endStyle, title, css) } + inner(builder, text.slice(0, part.to - start), style, startStyle, null, title, css) + startStyle = null + text = text.slice(part.to - start) + start = part.to + } + } + } + + function buildCollapsedSpan(builder, size, marker, ignoreWidget) { + var widget = !ignoreWidget && marker.widgetNode + if (widget) { builder.map.push(builder.pos, builder.pos + size, widget) } + if (!ignoreWidget && builder.cm.display.input.needsContentAttribute) { + if (!widget) + { widget = builder.content.appendChild(document.createElement("span")) } + widget.setAttribute("cm-marker", marker.id) + } + if (widget) { + builder.cm.display.input.setUneditable(widget) + builder.content.appendChild(widget) + } + builder.pos += size + builder.trailingSpace = false + } + + // Outputs a number of spans to make up a line, taking highlighting + // and marked text into account. + function insertLineContent(line, builder, styles) { + var spans = line.markedSpans, allText = line.text, at = 0 + if (!spans) { + for (var i$1 = 1; i$1 < styles.length; i$1+=2) + { builder.addToken(builder, allText.slice(at, at = styles[i$1]), interpretTokenStyle(styles[i$1+1], builder.cm.options)) } + return + } + + var len = allText.length, pos = 0, i = 1, text = "", style, css + var nextChange = 0, spanStyle, spanEndStyle, spanStartStyle, title, collapsed + for (;;) { + if (nextChange == pos) { // Update current marker set + spanStyle = spanEndStyle = spanStartStyle = title = css = "" + collapsed = null; nextChange = Infinity + var foundBookmarks = [], endStyles = (void 0) + for (var j = 0; j < spans.length; ++j) { + var sp = spans[j], m = sp.marker + if (m.type == "bookmark" && sp.from == pos && m.widgetNode) { + foundBookmarks.push(m) + } else if (sp.from <= pos && (sp.to == null || sp.to > pos || m.collapsed && sp.to == pos && sp.from == pos)) { + if (sp.to != null && sp.to != pos && nextChange > sp.to) { + nextChange = sp.to + spanEndStyle = "" + } + if (m.className) { spanStyle += " " + m.className } + if (m.css) { css = (css ? css + ";" : "") + m.css } + if (m.startStyle && sp.from == pos) { spanStartStyle += " " + m.startStyle } + if (m.endStyle && sp.to == nextChange) { (endStyles || (endStyles = [])).push(m.endStyle, sp.to) } + if (m.title && !title) { title = m.title } + if (m.collapsed && (!collapsed || compareCollapsedMarkers(collapsed.marker, m) < 0)) + { collapsed = sp } + } else if (sp.from > pos && nextChange > sp.from) { + nextChange = sp.from + } + } + if (endStyles) { for (var j$1 = 0; j$1 < endStyles.length; j$1 += 2) + { if (endStyles[j$1 + 1] == nextChange) { spanEndStyle += " " + endStyles[j$1] } } } + + if (!collapsed || collapsed.from == pos) { for (var j$2 = 0; j$2 < foundBookmarks.length; ++j$2) + { buildCollapsedSpan(builder, 0, foundBookmarks[j$2]) } } + if (collapsed && (collapsed.from || 0) == pos) { + buildCollapsedSpan(builder, (collapsed.to == null ? len + 1 : collapsed.to) - pos, + collapsed.marker, collapsed.from == null) + if (collapsed.to == null) { return } + if (collapsed.to == pos) { collapsed = false } + } + } + if (pos >= len) { break } + + var upto = Math.min(len, nextChange) + while (true) { + if (text) { + var end = pos + text.length + if (!collapsed) { + var tokenText = end > upto ? text.slice(0, upto - pos) : text + builder.addToken(builder, tokenText, style ? style + spanStyle : spanStyle, + spanStartStyle, pos + tokenText.length == nextChange ? spanEndStyle : "", title, css) + } + if (end >= upto) {text = text.slice(upto - pos); pos = upto; break} + pos = end + spanStartStyle = "" + } + text = allText.slice(at, at = styles[i++]) + style = interpretTokenStyle(styles[i++], builder.cm.options) + } + } + } + + + // These objects are used to represent the visible (currently drawn) + // part of the document. A LineView may correspond to multiple + // logical lines, if those are connected by collapsed ranges. + function LineView(doc, line, lineN) { + // The starting line + this.line = line + // Continuing lines, if any + this.rest = visualLineContinued(line) + // Number of logical lines in this visual line + this.size = this.rest ? lineNo(lst(this.rest)) - lineN + 1 : 1 + this.node = this.text = null + this.hidden = lineIsHidden(doc, line) + } + + // Create a range of LineView objects for the given lines. + function buildViewArray(cm, from, to) { + var array = [], nextPos + for (var pos = from; pos < to; pos = nextPos) { + var view = new LineView(cm.doc, getLine(cm.doc, pos), pos) + nextPos = pos + view.size + array.push(view) + } + return array + } + + var operationGroup = null + + function pushOperation(op) { + if (operationGroup) { + operationGroup.ops.push(op) + } else { + op.ownsGroup = operationGroup = { + ops: [op], + delayedCallbacks: [] + } + } + } + + function fireCallbacksForOps(group) { + // Calls delayed callbacks and cursorActivity handlers until no + // new ones appear + var callbacks = group.delayedCallbacks, i = 0 + do { + for (; i < callbacks.length; i++) + { callbacks[i].call(null) } + for (var j = 0; j < group.ops.length; j++) { + var op = group.ops[j] + if (op.cursorActivityHandlers) + { while (op.cursorActivityCalled < op.cursorActivityHandlers.length) + { op.cursorActivityHandlers[op.cursorActivityCalled++].call(null, op.cm) } } + } + } while (i < callbacks.length) + } + + function finishOperation(op, endCb) { + var group = op.ownsGroup + if (!group) { return } + + try { fireCallbacksForOps(group) } + finally { + operationGroup = null + endCb(group) + } + } + + var orphanDelayedCallbacks = null + + // Often, we want to signal events at a point where we are in the + // middle of some work, but don't want the handler to start calling + // other methods on the editor, which might be in an inconsistent + // state or simply not expect any other events to happen. + // signalLater looks whether there are any handlers, and schedules + // them to be executed when the last operation ends, or, if no + // operation is active, when a timeout fires. + function signalLater(emitter, type /*, values...*/) { + var arr = getHandlers(emitter, type) + if (!arr.length) { return } + var args = Array.prototype.slice.call(arguments, 2), list + if (operationGroup) { + list = operationGroup.delayedCallbacks + } else if (orphanDelayedCallbacks) { + list = orphanDelayedCallbacks + } else { + list = orphanDelayedCallbacks = [] + setTimeout(fireOrphanDelayed, 0) + } + var loop = function ( i ) { + list.push(function () { return arr[i].apply(null, args); }) + }; + + for (var i = 0; i < arr.length; ++i) + loop( i ); + } + + function fireOrphanDelayed() { + var delayed = orphanDelayedCallbacks + orphanDelayedCallbacks = null + for (var i = 0; i < delayed.length; ++i) { delayed[i]() } + } + + // When an aspect of a line changes, a string is added to + // lineView.changes. This updates the relevant part of the line's + // DOM structure. + function updateLineForChanges(cm, lineView, lineN, dims) { + for (var j = 0; j < lineView.changes.length; j++) { + var type = lineView.changes[j] + if (type == "text") { updateLineText(cm, lineView) } + else if (type == "gutter") { updateLineGutter(cm, lineView, lineN, dims) } + else if (type == "class") { updateLineClasses(cm, lineView) } + else if (type == "widget") { updateLineWidgets(cm, lineView, dims) } + } + lineView.changes = null + } + + // Lines with gutter elements, widgets or a background class need to + // be wrapped, and have the extra elements added to the wrapper div + function ensureLineWrapped(lineView) { + if (lineView.node == lineView.text) { + lineView.node = elt("div", null, null, "position: relative") + if (lineView.text.parentNode) + { lineView.text.parentNode.replaceChild(lineView.node, lineView.text) } + lineView.node.appendChild(lineView.text) + if (ie && ie_version < 8) { lineView.node.style.zIndex = 2 } + } + return lineView.node + } + + function updateLineBackground(cm, lineView) { + var cls = lineView.bgClass ? lineView.bgClass + " " + (lineView.line.bgClass || "") : lineView.line.bgClass + if (cls) { cls += " CodeMirror-linebackground" } + if (lineView.background) { + if (cls) { lineView.background.className = cls } + else { lineView.background.parentNode.removeChild(lineView.background); lineView.background = null } + } else if (cls) { + var wrap = ensureLineWrapped(lineView) + lineView.background = wrap.insertBefore(elt("div", null, cls), wrap.firstChild) + cm.display.input.setUneditable(lineView.background) + } + } + + // Wrapper around buildLineContent which will reuse the structure + // in display.externalMeasured when possible. + function getLineContent(cm, lineView) { + var ext = cm.display.externalMeasured + if (ext && ext.line == lineView.line) { + cm.display.externalMeasured = null + lineView.measure = ext.measure + return ext.built + } + return buildLineContent(cm, lineView) + } + + // Redraw the line's text. Interacts with the background and text + // classes because the mode may output tokens that influence these + // classes. + function updateLineText(cm, lineView) { + var cls = lineView.text.className + var built = getLineContent(cm, lineView) + if (lineView.text == lineView.node) { lineView.node = built.pre } + lineView.text.parentNode.replaceChild(built.pre, lineView.text) + lineView.text = built.pre + if (built.bgClass != lineView.bgClass || built.textClass != lineView.textClass) { + lineView.bgClass = built.bgClass + lineView.textClass = built.textClass + updateLineClasses(cm, lineView) + } else if (cls) { + lineView.text.className = cls + } + } + + function updateLineClasses(cm, lineView) { + updateLineBackground(cm, lineView) + if (lineView.line.wrapClass) + { ensureLineWrapped(lineView).className = lineView.line.wrapClass } + else if (lineView.node != lineView.text) + { lineView.node.className = "" } + var textClass = lineView.textClass ? lineView.textClass + " " + (lineView.line.textClass || "") : lineView.line.textClass + lineView.text.className = textClass || "" + } + + function updateLineGutter(cm, lineView, lineN, dims) { + if (lineView.gutter) { + lineView.node.removeChild(lineView.gutter) + lineView.gutter = null + } + if (lineView.gutterBackground) { + lineView.node.removeChild(lineView.gutterBackground) + lineView.gutterBackground = null + } + if (lineView.line.gutterClass) { + var wrap = ensureLineWrapped(lineView) + lineView.gutterBackground = elt("div", null, "CodeMirror-gutter-background " + lineView.line.gutterClass, + ("left: " + (cm.options.fixedGutter ? dims.fixedPos : -dims.gutterTotalWidth) + "px; width: " + (dims.gutterTotalWidth) + "px")) + cm.display.input.setUneditable(lineView.gutterBackground) + wrap.insertBefore(lineView.gutterBackground, lineView.text) + } + var markers = lineView.line.gutterMarkers + if (cm.options.lineNumbers || markers) { + var wrap$1 = ensureLineWrapped(lineView) + var gutterWrap = lineView.gutter = elt("div", null, "CodeMirror-gutter-wrapper", ("left: " + (cm.options.fixedGutter ? dims.fixedPos : -dims.gutterTotalWidth) + "px")) + cm.display.input.setUneditable(gutterWrap) + wrap$1.insertBefore(gutterWrap, lineView.text) + if (lineView.line.gutterClass) + { gutterWrap.className += " " + lineView.line.gutterClass } + if (cm.options.lineNumbers && (!markers || !markers["CodeMirror-linenumbers"])) + { lineView.lineNumber = gutterWrap.appendChild( + elt("div", lineNumberFor(cm.options, lineN), + "CodeMirror-linenumber CodeMirror-gutter-elt", + ("left: " + (dims.gutterLeft["CodeMirror-linenumbers"]) + "px; width: " + (cm.display.lineNumInnerWidth) + "px"))) } + if (markers) { for (var k = 0; k < cm.options.gutters.length; ++k) { + var id = cm.options.gutters[k], found = markers.hasOwnProperty(id) && markers[id] + if (found) + { gutterWrap.appendChild(elt("div", [found], "CodeMirror-gutter-elt", + ("left: " + (dims.gutterLeft[id]) + "px; width: " + (dims.gutterWidth[id]) + "px"))) } + } } + } + } + + function updateLineWidgets(cm, lineView, dims) { + if (lineView.alignable) { lineView.alignable = null } + for (var node = lineView.node.firstChild, next = (void 0); node; node = next) { + next = node.nextSibling + if (node.className == "CodeMirror-linewidget") + { lineView.node.removeChild(node) } + } + insertLineWidgets(cm, lineView, dims) + } + + // Build a line's DOM representation from scratch + function buildLineElement(cm, lineView, lineN, dims) { + var built = getLineContent(cm, lineView) + lineView.text = lineView.node = built.pre + if (built.bgClass) { lineView.bgClass = built.bgClass } + if (built.textClass) { lineView.textClass = built.textClass } + + updateLineClasses(cm, lineView) + updateLineGutter(cm, lineView, lineN, dims) + insertLineWidgets(cm, lineView, dims) + return lineView.node + } + + // A lineView may contain multiple logical lines (when merged by + // collapsed spans). The widgets for all of them need to be drawn. + function insertLineWidgets(cm, lineView, dims) { + insertLineWidgetsFor(cm, lineView.line, lineView, dims, true) + if (lineView.rest) { for (var i = 0; i < lineView.rest.length; i++) + { insertLineWidgetsFor(cm, lineView.rest[i], lineView, dims, false) } } + } + + function insertLineWidgetsFor(cm, line, lineView, dims, allowAbove) { + if (!line.widgets) { return } + var wrap = ensureLineWrapped(lineView) + for (var i = 0, ws = line.widgets; i < ws.length; ++i) { + var widget = ws[i], node = elt("div", [widget.node], "CodeMirror-linewidget") + if (!widget.handleMouseEvents) { node.setAttribute("cm-ignore-events", "true") } + positionLineWidget(widget, node, lineView, dims) + cm.display.input.setUneditable(node) + if (allowAbove && widget.above) + { wrap.insertBefore(node, lineView.gutter || lineView.text) } + else + { wrap.appendChild(node) } + signalLater(widget, "redraw") + } + } + + function positionLineWidget(widget, node, lineView, dims) { + if (widget.noHScroll) { + ;(lineView.alignable || (lineView.alignable = [])).push(node) + var width = dims.wrapperWidth + node.style.left = dims.fixedPos + "px" + if (!widget.coverGutter) { + width -= dims.gutterTotalWidth + node.style.paddingLeft = dims.gutterTotalWidth + "px" + } + node.style.width = width + "px" + } + if (widget.coverGutter) { + node.style.zIndex = 5 + node.style.position = "relative" + if (!widget.noHScroll) { node.style.marginLeft = -dims.gutterTotalWidth + "px" } + } + } + + function widgetHeight(widget) { + if (widget.height != null) { return widget.height } + var cm = widget.doc.cm + if (!cm) { return 0 } + if (!contains(document.body, widget.node)) { + var parentStyle = "position: relative;" + if (widget.coverGutter) + { parentStyle += "margin-left: -" + cm.display.gutters.offsetWidth + "px;" } + if (widget.noHScroll) + { parentStyle += "width: " + cm.display.wrapper.clientWidth + "px;" } + removeChildrenAndAdd(cm.display.measure, elt("div", [widget.node], null, parentStyle)) + } + return widget.height = widget.node.parentNode.offsetHeight + } + + // Return true when the given mouse event happened in a widget + function eventInWidget(display, e) { + for (var n = e_target(e); n != display.wrapper; n = n.parentNode) { + if (!n || (n.nodeType == 1 && n.getAttribute("cm-ignore-events") == "true") || + (n.parentNode == display.sizer && n != display.mover)) + { return true } + } + } + + // POSITION MEASUREMENT + + function paddingTop(display) {return display.lineSpace.offsetTop} + function paddingVert(display) {return display.mover.offsetHeight - display.lineSpace.offsetHeight} + function paddingH(display) { + if (display.cachedPaddingH) { return display.cachedPaddingH } + var e = removeChildrenAndAdd(display.measure, elt("pre", "x")) + var style = window.getComputedStyle ? window.getComputedStyle(e) : e.currentStyle + var data = {left: parseInt(style.paddingLeft), right: parseInt(style.paddingRight)} + if (!isNaN(data.left) && !isNaN(data.right)) { display.cachedPaddingH = data } + return data + } + + function scrollGap(cm) { return scrollerGap - cm.display.nativeBarWidth } + function displayWidth(cm) { + return cm.display.scroller.clientWidth - scrollGap(cm) - cm.display.barWidth + } + function displayHeight(cm) { + return cm.display.scroller.clientHeight - scrollGap(cm) - cm.display.barHeight + } + + // Ensure the lineView.wrapping.heights array is populated. This is + // an array of bottom offsets for the lines that make up a drawn + // line. When lineWrapping is on, there might be more than one + // height. + function ensureLineHeights(cm, lineView, rect) { + var wrapping = cm.options.lineWrapping + var curWidth = wrapping && displayWidth(cm) + if (!lineView.measure.heights || wrapping && lineView.measure.width != curWidth) { + var heights = lineView.measure.heights = [] + if (wrapping) { + lineView.measure.width = curWidth + var rects = lineView.text.firstChild.getClientRects() + for (var i = 0; i < rects.length - 1; i++) { + var cur = rects[i], next = rects[i + 1] + if (Math.abs(cur.bottom - next.bottom) > 2) + { heights.push((cur.bottom + next.top) / 2 - rect.top) } + } + } + heights.push(rect.bottom - rect.top) + } + } + + // Find a line map (mapping character offsets to text nodes) and a + // measurement cache for the given line number. (A line view might + // contain multiple lines when collapsed ranges are present.) + function mapFromLineView(lineView, line, lineN) { + if (lineView.line == line) + { return {map: lineView.measure.map, cache: lineView.measure.cache} } + for (var i = 0; i < lineView.rest.length; i++) + { if (lineView.rest[i] == line) + { return {map: lineView.measure.maps[i], cache: lineView.measure.caches[i]} } } + for (var i$1 = 0; i$1 < lineView.rest.length; i$1++) + { if (lineNo(lineView.rest[i$1]) > lineN) + { return {map: lineView.measure.maps[i$1], cache: lineView.measure.caches[i$1], before: true} } } + } + + // Render a line into the hidden node display.externalMeasured. Used + // when measurement is needed for a line that's not in the viewport. + function updateExternalMeasurement(cm, line) { + line = visualLine(line) + var lineN = lineNo(line) + var view = cm.display.externalMeasured = new LineView(cm.doc, line, lineN) + view.lineN = lineN + var built = view.built = buildLineContent(cm, view) + view.text = built.pre + removeChildrenAndAdd(cm.display.lineMeasure, built.pre) + return view + } + + // Get a {top, bottom, left, right} box (in line-local coordinates) + // for a given character. + function measureChar(cm, line, ch, bias) { + return measureCharPrepared(cm, prepareMeasureForLine(cm, line), ch, bias) + } + + // Find a line view that corresponds to the given line number. + function findViewForLine(cm, lineN) { + if (lineN >= cm.display.viewFrom && lineN < cm.display.viewTo) + { return cm.display.view[findViewIndex(cm, lineN)] } + var ext = cm.display.externalMeasured + if (ext && lineN >= ext.lineN && lineN < ext.lineN + ext.size) + { return ext } + } + + // Measurement can be split in two steps, the set-up work that + // applies to the whole line, and the measurement of the actual + // character. Functions like coordsChar, that need to do a lot of + // measurements in a row, can thus ensure that the set-up work is + // only done once. + function prepareMeasureForLine(cm, line) { + var lineN = lineNo(line) + var view = findViewForLine(cm, lineN) + if (view && !view.text) { + view = null + } else if (view && view.changes) { + updateLineForChanges(cm, view, lineN, getDimensions(cm)) + cm.curOp.forceUpdate = true + } + if (!view) + { view = updateExternalMeasurement(cm, line) } + + var info = mapFromLineView(view, line, lineN) + return { + line: line, view: view, rect: null, + map: info.map, cache: info.cache, before: info.before, + hasHeights: false + } + } + + // Given a prepared measurement object, measures the position of an + // actual character (or fetches it from the cache). + function measureCharPrepared(cm, prepared, ch, bias, varHeight) { + if (prepared.before) { ch = -1 } + var key = ch + (bias || ""), found + if (prepared.cache.hasOwnProperty(key)) { + found = prepared.cache[key] + } else { + if (!prepared.rect) + { prepared.rect = prepared.view.text.getBoundingClientRect() } + if (!prepared.hasHeights) { + ensureLineHeights(cm, prepared.view, prepared.rect) + prepared.hasHeights = true + } + found = measureCharInner(cm, prepared, ch, bias) + if (!found.bogus) { prepared.cache[key] = found } + } + return {left: found.left, right: found.right, + top: varHeight ? found.rtop : found.top, + bottom: varHeight ? found.rbottom : found.bottom} + } + + var nullRect = {left: 0, right: 0, top: 0, bottom: 0} + + function nodeAndOffsetInLineMap(map, ch, bias) { + var node, start, end, collapse, mStart, mEnd + // First, search the line map for the text node corresponding to, + // or closest to, the target character. + for (var i = 0; i < map.length; i += 3) { + mStart = map[i] + mEnd = map[i + 1] + if (ch < mStart) { + start = 0; end = 1 + collapse = "left" + } else if (ch < mEnd) { + start = ch - mStart + end = start + 1 + } else if (i == map.length - 3 || ch == mEnd && map[i + 3] > ch) { + end = mEnd - mStart + start = end - 1 + if (ch >= mEnd) { collapse = "right" } + } + if (start != null) { + node = map[i + 2] + if (mStart == mEnd && bias == (node.insertLeft ? "left" : "right")) + { collapse = bias } + if (bias == "left" && start == 0) + { while (i && map[i - 2] == map[i - 3] && map[i - 1].insertLeft) { + node = map[(i -= 3) + 2] + collapse = "left" + } } + if (bias == "right" && start == mEnd - mStart) + { while (i < map.length - 3 && map[i + 3] == map[i + 4] && !map[i + 5].insertLeft) { + node = map[(i += 3) + 2] + collapse = "right" + } } + break + } + } + return {node: node, start: start, end: end, collapse: collapse, coverStart: mStart, coverEnd: mEnd} + } + + function getUsefulRect(rects, bias) { + var rect = nullRect + if (bias == "left") { for (var i = 0; i < rects.length; i++) { + if ((rect = rects[i]).left != rect.right) { break } + } } else { for (var i$1 = rects.length - 1; i$1 >= 0; i$1--) { + if ((rect = rects[i$1]).left != rect.right) { break } + } } + return rect + } + + function measureCharInner(cm, prepared, ch, bias) { + var place = nodeAndOffsetInLineMap(prepared.map, ch, bias) + var node = place.node, start = place.start, end = place.end, collapse = place.collapse + + var rect + if (node.nodeType == 3) { // If it is a text node, use a range to retrieve the coordinates. + for (var i$1 = 0; i$1 < 4; i$1++) { // Retry a maximum of 4 times when nonsense rectangles are returned + while (start && isExtendingChar(prepared.line.text.charAt(place.coverStart + start))) { --start } + while (place.coverStart + end < place.coverEnd && isExtendingChar(prepared.line.text.charAt(place.coverStart + end))) { ++end } + if (ie && ie_version < 9 && start == 0 && end == place.coverEnd - place.coverStart) + { rect = node.parentNode.getBoundingClientRect() } + else + { rect = getUsefulRect(range(node, start, end).getClientRects(), bias) } + if (rect.left || rect.right || start == 0) { break } + end = start + start = start - 1 + collapse = "right" + } + if (ie && ie_version < 11) { rect = maybeUpdateRectForZooming(cm.display.measure, rect) } + } else { // If it is a widget, simply get the box for the whole widget. + if (start > 0) { collapse = bias = "right" } + var rects + if (cm.options.lineWrapping && (rects = node.getClientRects()).length > 1) + { rect = rects[bias == "right" ? rects.length - 1 : 0] } + else + { rect = node.getBoundingClientRect() } + } + if (ie && ie_version < 9 && !start && (!rect || !rect.left && !rect.right)) { + var rSpan = node.parentNode.getClientRects()[0] + if (rSpan) + { rect = {left: rSpan.left, right: rSpan.left + charWidth(cm.display), top: rSpan.top, bottom: rSpan.bottom} } + else + { rect = nullRect } + } + + var rtop = rect.top - prepared.rect.top, rbot = rect.bottom - prepared.rect.top + var mid = (rtop + rbot) / 2 + var heights = prepared.view.measure.heights + var i = 0 + for (; i < heights.length - 1; i++) + { if (mid < heights[i]) { break } } + var top = i ? heights[i - 1] : 0, bot = heights[i] + var result = {left: (collapse == "right" ? rect.right : rect.left) - prepared.rect.left, + right: (collapse == "left" ? rect.left : rect.right) - prepared.rect.left, + top: top, bottom: bot} + if (!rect.left && !rect.right) { result.bogus = true } + if (!cm.options.singleCursorHeightPerLine) { result.rtop = rtop; result.rbottom = rbot } + + return result + } + + // Work around problem with bounding client rects on ranges being + // returned incorrectly when zoomed on IE10 and below. + function maybeUpdateRectForZooming(measure, rect) { + if (!window.screen || screen.logicalXDPI == null || + screen.logicalXDPI == screen.deviceXDPI || !hasBadZoomedRects(measure)) + { return rect } + var scaleX = screen.logicalXDPI / screen.deviceXDPI + var scaleY = screen.logicalYDPI / screen.deviceYDPI + return {left: rect.left * scaleX, right: rect.right * scaleX, + top: rect.top * scaleY, bottom: rect.bottom * scaleY} + } + + function clearLineMeasurementCacheFor(lineView) { + if (lineView.measure) { + lineView.measure.cache = {} + lineView.measure.heights = null + if (lineView.rest) { for (var i = 0; i < lineView.rest.length; i++) + { lineView.measure.caches[i] = {} } } + } + } + + function clearLineMeasurementCache(cm) { + cm.display.externalMeasure = null + removeChildren(cm.display.lineMeasure) + for (var i = 0; i < cm.display.view.length; i++) + { clearLineMeasurementCacheFor(cm.display.view[i]) } + } + + function clearCaches(cm) { + clearLineMeasurementCache(cm) + cm.display.cachedCharWidth = cm.display.cachedTextHeight = cm.display.cachedPaddingH = null + if (!cm.options.lineWrapping) { cm.display.maxLineChanged = true } + cm.display.lineNumChars = null + } + + function pageScrollX() { + // Work around https://bugs.chromium.org/p/chromium/issues/detail?id=489206 + // which causes page_Offset and bounding client rects to use + // different reference viewports and invalidate our calculations. + if (chrome && android) { return -(document.body.getBoundingClientRect().left - parseInt(getComputedStyle(document.body).marginLeft)) } + return window.pageXOffset || (document.documentElement || document.body).scrollLeft + } + function pageScrollY() { + if (chrome && android) { return -(document.body.getBoundingClientRect().top - parseInt(getComputedStyle(document.body).marginTop)) } + return window.pageYOffset || (document.documentElement || document.body).scrollTop + } + + function widgetTopHeight(lineObj) { + var height = 0 + if (lineObj.widgets) { for (var i = 0; i < lineObj.widgets.length; ++i) { if (lineObj.widgets[i].above) + { height += widgetHeight(lineObj.widgets[i]) } } } + return height + } + + // Converts a {top, bottom, left, right} box from line-local + // coordinates into another coordinate system. Context may be one of + // "line", "div" (display.lineDiv), "local"./null (editor), "window", + // or "page". + function intoCoordSystem(cm, lineObj, rect, context, includeWidgets) { + if (!includeWidgets) { + var height = widgetTopHeight(lineObj) + rect.top += height; rect.bottom += height + } + if (context == "line") { return rect } + if (!context) { context = "local" } + var yOff = heightAtLine(lineObj) + if (context == "local") { yOff += paddingTop(cm.display) } + else { yOff -= cm.display.viewOffset } + if (context == "page" || context == "window") { + var lOff = cm.display.lineSpace.getBoundingClientRect() + yOff += lOff.top + (context == "window" ? 0 : pageScrollY()) + var xOff = lOff.left + (context == "window" ? 0 : pageScrollX()) + rect.left += xOff; rect.right += xOff + } + rect.top += yOff; rect.bottom += yOff + return rect + } + + // Coverts a box from "div" coords to another coordinate system. + // Context may be "window", "page", "div", or "local"./null. + function fromCoordSystem(cm, coords, context) { + if (context == "div") { return coords } + var left = coords.left, top = coords.top + // First move into "page" coordinate system + if (context == "page") { + left -= pageScrollX() + top -= pageScrollY() + } else if (context == "local" || !context) { + var localBox = cm.display.sizer.getBoundingClientRect() + left += localBox.left + top += localBox.top + } + + var lineSpaceBox = cm.display.lineSpace.getBoundingClientRect() + return {left: left - lineSpaceBox.left, top: top - lineSpaceBox.top} + } + + function charCoords(cm, pos, context, lineObj, bias) { + if (!lineObj) { lineObj = getLine(cm.doc, pos.line) } + return intoCoordSystem(cm, lineObj, measureChar(cm, lineObj, pos.ch, bias), context) + } + + // Returns a box for a given cursor position, which may have an + // 'other' property containing the position of the secondary cursor + // on a bidi boundary. + // A cursor Pos(line, char, "before") is on the same visual line as `char - 1` + // and after `char - 1` in writing order of `char - 1` + // A cursor Pos(line, char, "after") is on the same visual line as `char` + // and before `char` in writing order of `char` + // Examples (upper-case letters are RTL, lower-case are LTR): + // Pos(0, 1, ...) + // before after + // ab a|b a|b + // aB a|B aB| + // Ab |Ab A|b + // AB B|A B|A + // Every position after the last character on a line is considered to stick + // to the last character on the line. + function cursorCoords(cm, pos, context, lineObj, preparedMeasure, varHeight) { + lineObj = lineObj || getLine(cm.doc, pos.line) + if (!preparedMeasure) { preparedMeasure = prepareMeasureForLine(cm, lineObj) } + function get(ch, right) { + var m = measureCharPrepared(cm, preparedMeasure, ch, right ? "right" : "left", varHeight) + if (right) { m.left = m.right; } else { m.right = m.left } + return intoCoordSystem(cm, lineObj, m, context) + } + var order = getOrder(lineObj, cm.doc.direction), ch = pos.ch, sticky = pos.sticky + if (ch >= lineObj.text.length) { + ch = lineObj.text.length + sticky = "before" + } else if (ch <= 0) { + ch = 0 + sticky = "after" + } + if (!order) { return get(sticky == "before" ? ch - 1 : ch, sticky == "before") } + + function getBidi(ch, partPos, invert) { + var part = order[partPos], right = part.level == 1 + return get(invert ? ch - 1 : ch, right != invert) + } + var partPos = getBidiPartAt(order, ch, sticky) + var other = bidiOther + var val = getBidi(ch, partPos, sticky == "before") + if (other != null) { val.other = getBidi(ch, other, sticky != "before") } + return val + } + + // Used to cheaply estimate the coordinates for a position. Used for + // intermediate scroll updates. + function estimateCoords(cm, pos) { + var left = 0 + pos = clipPos(cm.doc, pos) + if (!cm.options.lineWrapping) { left = charWidth(cm.display) * pos.ch } + var lineObj = getLine(cm.doc, pos.line) + var top = heightAtLine(lineObj) + paddingTop(cm.display) + return {left: left, right: left, top: top, bottom: top + lineObj.height} + } + + // Positions returned by coordsChar contain some extra information. + // xRel is the relative x position of the input coordinates compared + // to the found position (so xRel > 0 means the coordinates are to + // the right of the character position, for example). When outside + // is true, that means the coordinates lie outside the line's + // vertical range. + function PosWithInfo(line, ch, sticky, outside, xRel) { + var pos = Pos(line, ch, sticky) + pos.xRel = xRel + if (outside) { pos.outside = true } + return pos + } + + // Compute the character position closest to the given coordinates. + // Input must be lineSpace-local ("div" coordinate system). + function coordsChar(cm, x, y) { + var doc = cm.doc + y += cm.display.viewOffset + if (y < 0) { return PosWithInfo(doc.first, 0, null, true, -1) } + var lineN = lineAtHeight(doc, y), last = doc.first + doc.size - 1 + if (lineN > last) + { return PosWithInfo(doc.first + doc.size - 1, getLine(doc, last).text.length, null, true, 1) } + if (x < 0) { x = 0 } + + var lineObj = getLine(doc, lineN) + for (;;) { + var found = coordsCharInner(cm, lineObj, lineN, x, y) + var merged = collapsedSpanAtEnd(lineObj) + var mergedPos = merged && merged.find(0, true) + if (merged && (found.ch > mergedPos.from.ch || found.ch == mergedPos.from.ch && found.xRel > 0)) + { lineN = lineNo(lineObj = mergedPos.to.line) } + else + { return found } + } + } + + function wrappedLineExtent(cm, lineObj, preparedMeasure, y) { + y -= widgetTopHeight(lineObj) + var end = lineObj.text.length + var begin = findFirst(function (ch) { return measureCharPrepared(cm, preparedMeasure, ch - 1).bottom <= y; }, end, 0) + end = findFirst(function (ch) { return measureCharPrepared(cm, preparedMeasure, ch).top > y; }, begin, end) + return {begin: begin, end: end} + } + + function wrappedLineExtentChar(cm, lineObj, preparedMeasure, target) { + if (!preparedMeasure) { preparedMeasure = prepareMeasureForLine(cm, lineObj) } + var targetTop = intoCoordSystem(cm, lineObj, measureCharPrepared(cm, preparedMeasure, target), "line").top + return wrappedLineExtent(cm, lineObj, preparedMeasure, targetTop) + } + + // Returns true if the given side of a box is after the given + // coordinates, in top-to-bottom, left-to-right order. + function boxIsAfter(box, x, y, left) { + return box.bottom <= y ? false : box.top > y ? true : (left ? box.left : box.right) > x + } + + function coordsCharInner(cm, lineObj, lineNo, x, y) { + // Move y into line-local coordinate space + y -= heightAtLine(lineObj) + var preparedMeasure = prepareMeasureForLine(cm, lineObj) + // When directly calling `measureCharPrepared`, we have to adjust + // for the widgets at this line. + var widgetHeight = widgetTopHeight(lineObj) + var begin = 0, end = lineObj.text.length, ltr = true + + var order = getOrder(lineObj, cm.doc.direction) + // If the line isn't plain left-to-right text, first figure out + // which bidi section the coordinates fall into. + if (order) { + var part = (cm.options.lineWrapping ? coordsBidiPartWrapped : coordsBidiPart) + (cm, lineObj, lineNo, preparedMeasure, order, x, y) + ltr = part.level != 1 + // The awkward -1 offsets are needed because findFirst (called + // on these below) will treat its first bound as inclusive, + // second as exclusive, but we want to actually address the + // characters in the part's range + begin = ltr ? part.from : part.to - 1 + end = ltr ? part.to : part.from - 1 + } + + // A binary search to find the first character whose bounding box + // starts after the coordinates. If we run across any whose box wrap + // the coordinates, store that. + var chAround = null, boxAround = null + var ch = findFirst(function (ch) { + var box = measureCharPrepared(cm, preparedMeasure, ch) + box.top += widgetHeight; box.bottom += widgetHeight + if (!boxIsAfter(box, x, y, false)) { return false } + if (box.top <= y && box.left <= x) { + chAround = ch + boxAround = box + } + return true + }, begin, end) + + var baseX, sticky, outside = false + // If a box around the coordinates was found, use that + if (boxAround) { + // Distinguish coordinates nearer to the left or right side of the box + var atLeft = x - boxAround.left < boxAround.right - x, atStart = atLeft == ltr + ch = chAround + (atStart ? 0 : 1) + sticky = atStart ? "after" : "before" + baseX = atLeft ? boxAround.left : boxAround.right + } else { + // (Adjust for extended bound, if necessary.) + if (!ltr && (ch == end || ch == begin)) { ch++ } + // To determine which side to associate with, get the box to the + // left of the character and compare it's vertical position to the + // coordinates + sticky = ch == 0 ? "after" : ch == lineObj.text.length ? "before" : + (measureCharPrepared(cm, preparedMeasure, ch - (ltr ? 1 : 0)).bottom + widgetHeight <= y) == ltr ? + "after" : "before" + // Now get accurate coordinates for this place, in order to get a + // base X position + var coords = cursorCoords(cm, Pos(lineNo, ch, sticky), "line", lineObj, preparedMeasure) + baseX = coords.left + outside = y < coords.top || y >= coords.bottom + } + + ch = skipExtendingChars(lineObj.text, ch, 1) + return PosWithInfo(lineNo, ch, sticky, outside, x - baseX) + } + + function coordsBidiPart(cm, lineObj, lineNo, preparedMeasure, order, x, y) { + // Bidi parts are sorted left-to-right, and in a non-line-wrapping + // situation, we can take this ordering to correspond to the visual + // ordering. This finds the first part whose end is after the given + // coordinates. + var index = findFirst(function (i) { + var part = order[i], ltr = part.level != 1 + return boxIsAfter(cursorCoords(cm, Pos(lineNo, ltr ? part.to : part.from, ltr ? "before" : "after"), + "line", lineObj, preparedMeasure), x, y, true) + }, 0, order.length - 1) + var part = order[index] + // If this isn't the first part, the part's start is also after + // the coordinates, and the coordinates aren't on the same line as + // that start, move one part back. + if (index > 0) { + var ltr = part.level != 1 + var start = cursorCoords(cm, Pos(lineNo, ltr ? part.from : part.to, ltr ? "after" : "before"), + "line", lineObj, preparedMeasure) + if (boxIsAfter(start, x, y, true) && start.top > y) + { part = order[index - 1] } + } + return part + } + + function coordsBidiPartWrapped(cm, lineObj, _lineNo, preparedMeasure, order, x, y) { + // In a wrapped line, rtl text on wrapping boundaries can do things + // that don't correspond to the ordering in our `order` array at + // all, so a binary search doesn't work, and we want to return a + // part that only spans one line so that the binary search in + // coordsCharInner is safe. As such, we first find the extent of the + // wrapped line, and then do a flat search in which we discard any + // spans that aren't on the line. + var ref = wrappedLineExtent(cm, lineObj, preparedMeasure, y); + var begin = ref.begin; + var end = ref.end; + if (/\s/.test(lineObj.text.charAt(end - 1))) { end-- } + var part = null, closestDist = null + for (var i = 0; i < order.length; i++) { + var p = order[i] + if (p.from >= end || p.to <= begin) { continue } + var ltr = p.level != 1 + var endX = measureCharPrepared(cm, preparedMeasure, ltr ? Math.min(end, p.to) - 1 : Math.max(begin, p.from)).right + // Weigh against spans ending before this, so that they are only + // picked if nothing ends after + var dist = endX < x ? x - endX + 1e9 : endX - x + if (!part || closestDist > dist) { + part = p + closestDist = dist + } + } + if (!part) { part = order[order.length - 1] } + // Clip the part to the wrapped line. + if (part.from < begin) { part = {from: begin, to: part.to, level: part.level} } + if (part.to > end) { part = {from: part.from, to: end, level: part.level} } + return part + } + + var measureText + // Compute the default text height. + function textHeight(display) { + if (display.cachedTextHeight != null) { return display.cachedTextHeight } + if (measureText == null) { + measureText = elt("pre") + // Measure a bunch of lines, for browsers that compute + // fractional heights. + for (var i = 0; i < 49; ++i) { + measureText.appendChild(document.createTextNode("x")) + measureText.appendChild(elt("br")) + } + measureText.appendChild(document.createTextNode("x")) + } + removeChildrenAndAdd(display.measure, measureText) + var height = measureText.offsetHeight / 50 + if (height > 3) { display.cachedTextHeight = height } + removeChildren(display.measure) + return height || 1 + } + + // Compute the default character width. + function charWidth(display) { + if (display.cachedCharWidth != null) { return display.cachedCharWidth } + var anchor = elt("span", "xxxxxxxxxx") + var pre = elt("pre", [anchor]) + removeChildrenAndAdd(display.measure, pre) + var rect = anchor.getBoundingClientRect(), width = (rect.right - rect.left) / 10 + if (width > 2) { display.cachedCharWidth = width } + return width || 10 + } + + // Do a bulk-read of the DOM positions and sizes needed to draw the + // view, so that we don't interleave reading and writing to the DOM. + function getDimensions(cm) { + var d = cm.display, left = {}, width = {} + var gutterLeft = d.gutters.clientLeft + for (var n = d.gutters.firstChild, i = 0; n; n = n.nextSibling, ++i) { + left[cm.options.gutters[i]] = n.offsetLeft + n.clientLeft + gutterLeft + width[cm.options.gutters[i]] = n.clientWidth + } + return {fixedPos: compensateForHScroll(d), + gutterTotalWidth: d.gutters.offsetWidth, + gutterLeft: left, + gutterWidth: width, + wrapperWidth: d.wrapper.clientWidth} + } + + // Computes display.scroller.scrollLeft + display.gutters.offsetWidth, + // but using getBoundingClientRect to get a sub-pixel-accurate + // result. + function compensateForHScroll(display) { + return display.scroller.getBoundingClientRect().left - display.sizer.getBoundingClientRect().left + } + + // Returns a function that estimates the height of a line, to use as + // first approximation until the line becomes visible (and is thus + // properly measurable). + function estimateHeight(cm) { + var th = textHeight(cm.display), wrapping = cm.options.lineWrapping + var perLine = wrapping && Math.max(5, cm.display.scroller.clientWidth / charWidth(cm.display) - 3) + return function (line) { + if (lineIsHidden(cm.doc, line)) { return 0 } + + var widgetsHeight = 0 + if (line.widgets) { for (var i = 0; i < line.widgets.length; i++) { + if (line.widgets[i].height) { widgetsHeight += line.widgets[i].height } + } } + + if (wrapping) + { return widgetsHeight + (Math.ceil(line.text.length / perLine) || 1) * th } + else + { return widgetsHeight + th } + } + } + + function estimateLineHeights(cm) { + var doc = cm.doc, est = estimateHeight(cm) + doc.iter(function (line) { + var estHeight = est(line) + if (estHeight != line.height) { updateLineHeight(line, estHeight) } + }) + } + + // Given a mouse event, find the corresponding position. If liberal + // is false, it checks whether a gutter or scrollbar was clicked, + // and returns null if it was. forRect is used by rectangular + // selections, and tries to estimate a character position even for + // coordinates beyond the right of the text. + function posFromMouse(cm, e, liberal, forRect) { + var display = cm.display + if (!liberal && e_target(e).getAttribute("cm-not-content") == "true") { return null } + + var x, y, space = display.lineSpace.getBoundingClientRect() + // Fails unpredictably on IE[67] when mouse is dragged around quickly. + try { x = e.clientX - space.left; y = e.clientY - space.top } + catch (e) { return null } + var coords = coordsChar(cm, x, y), line + if (forRect && coords.xRel == 1 && (line = getLine(cm.doc, coords.line).text).length == coords.ch) { + var colDiff = countColumn(line, line.length, cm.options.tabSize) - line.length + coords = Pos(coords.line, Math.max(0, Math.round((x - paddingH(cm.display).left) / charWidth(cm.display)) - colDiff)) + } + return coords + } + + // Find the view element corresponding to a given line. Return null + // when the line isn't visible. + function findViewIndex(cm, n) { + if (n >= cm.display.viewTo) { return null } + n -= cm.display.viewFrom + if (n < 0) { return null } + var view = cm.display.view + for (var i = 0; i < view.length; i++) { + n -= view[i].size + if (n < 0) { return i } + } + } + + function updateSelection(cm) { + cm.display.input.showSelection(cm.display.input.prepareSelection()) + } + + function prepareSelection(cm, primary) { + if ( primary === void 0 ) primary = true; + + var doc = cm.doc, result = {} + var curFragment = result.cursors = document.createDocumentFragment() + var selFragment = result.selection = document.createDocumentFragment() + + for (var i = 0; i < doc.sel.ranges.length; i++) { + if (!primary && i == doc.sel.primIndex) { continue } + var range = doc.sel.ranges[i] + if (range.from().line >= cm.display.viewTo || range.to().line < cm.display.viewFrom) { continue } + var collapsed = range.empty() + if (collapsed || cm.options.showCursorWhenSelecting) + { drawSelectionCursor(cm, range.head, curFragment) } + if (!collapsed) + { drawSelectionRange(cm, range, selFragment) } + } + return result + } + + // Draws a cursor for the given range + function drawSelectionCursor(cm, head, output) { + var pos = cursorCoords(cm, head, "div", null, null, !cm.options.singleCursorHeightPerLine) + + var cursor = output.appendChild(elt("div", "\u00a0", "CodeMirror-cursor")) + cursor.style.left = pos.left + "px" + cursor.style.top = pos.top + "px" + cursor.style.height = Math.max(0, pos.bottom - pos.top) * cm.options.cursorHeight + "px" + + if (pos.other) { + // Secondary cursor, shown when on a 'jump' in bi-directional text + var otherCursor = output.appendChild(elt("div", "\u00a0", "CodeMirror-cursor CodeMirror-secondarycursor")) + otherCursor.style.display = "" + otherCursor.style.left = pos.other.left + "px" + otherCursor.style.top = pos.other.top + "px" + otherCursor.style.height = (pos.other.bottom - pos.other.top) * .85 + "px" + } + } + + function cmpCoords(a, b) { return a.top - b.top || a.left - b.left } + + // Draws the given range as a highlighted selection + function drawSelectionRange(cm, range, output) { + var display = cm.display, doc = cm.doc + var fragment = document.createDocumentFragment() + var padding = paddingH(cm.display), leftSide = padding.left + var rightSide = Math.max(display.sizerWidth, displayWidth(cm) - display.sizer.offsetLeft) - padding.right + var docLTR = doc.direction == "ltr" + + function add(left, top, width, bottom) { + if (top < 0) { top = 0 } + top = Math.round(top) + bottom = Math.round(bottom) + fragment.appendChild(elt("div", null, "CodeMirror-selected", ("position: absolute; left: " + left + "px;\n top: " + top + "px; width: " + (width == null ? rightSide - left : width) + "px;\n height: " + (bottom - top) + "px"))) + } + + function drawForLine(line, fromArg, toArg) { + var lineObj = getLine(doc, line) + var lineLen = lineObj.text.length + var start, end + function coords(ch, bias) { + return charCoords(cm, Pos(line, ch), "div", lineObj, bias) + } + + function wrapX(pos, dir, side) { + var extent = wrappedLineExtentChar(cm, lineObj, null, pos) + var prop = (dir == "ltr") == (side == "after") ? "left" : "right" + var ch = side == "after" ? extent.begin : extent.end - (/\s/.test(lineObj.text.charAt(extent.end - 1)) ? 2 : 1) + return coords(ch, prop)[prop] + } + + var order = getOrder(lineObj, doc.direction) + iterateBidiSections(order, fromArg || 0, toArg == null ? lineLen : toArg, function (from, to, dir, i) { + var ltr = dir == "ltr" + var fromPos = coords(from, ltr ? "left" : "right") + var toPos = coords(to - 1, ltr ? "right" : "left") + + var openStart = fromArg == null && from == 0, openEnd = toArg == null && to == lineLen + var first = i == 0, last = !order || i == order.length - 1 + if (toPos.top - fromPos.top <= 3) { // Single line + var openLeft = (docLTR ? openStart : openEnd) && first + var openRight = (docLTR ? openEnd : openStart) && last + var left = openLeft ? leftSide : (ltr ? fromPos : toPos).left + var right = openRight ? rightSide : (ltr ? toPos : fromPos).right + add(left, fromPos.top, right - left, fromPos.bottom) + } else { // Multiple lines + var topLeft, topRight, botLeft, botRight + if (ltr) { + topLeft = docLTR && openStart && first ? leftSide : fromPos.left + topRight = docLTR ? rightSide : wrapX(from, dir, "before") + botLeft = docLTR ? leftSide : wrapX(to, dir, "after") + botRight = docLTR && openEnd && last ? rightSide : toPos.right + } else { + topLeft = !docLTR ? leftSide : wrapX(from, dir, "before") + topRight = !docLTR && openStart && first ? rightSide : fromPos.right + botLeft = !docLTR && openEnd && last ? leftSide : toPos.left + botRight = !docLTR ? rightSide : wrapX(to, dir, "after") + } + add(topLeft, fromPos.top, topRight - topLeft, fromPos.bottom) + if (fromPos.bottom < toPos.top) { add(leftSide, fromPos.bottom, null, toPos.top) } + add(botLeft, toPos.top, botRight - botLeft, toPos.bottom) + } + + if (!start || cmpCoords(fromPos, start) < 0) { start = fromPos } + if (cmpCoords(toPos, start) < 0) { start = toPos } + if (!end || cmpCoords(fromPos, end) < 0) { end = fromPos } + if (cmpCoords(toPos, end) < 0) { end = toPos } + }) + return {start: start, end: end} + } + + var sFrom = range.from(), sTo = range.to() + if (sFrom.line == sTo.line) { + drawForLine(sFrom.line, sFrom.ch, sTo.ch) + } else { + var fromLine = getLine(doc, sFrom.line), toLine = getLine(doc, sTo.line) + var singleVLine = visualLine(fromLine) == visualLine(toLine) + var leftEnd = drawForLine(sFrom.line, sFrom.ch, singleVLine ? fromLine.text.length + 1 : null).end + var rightStart = drawForLine(sTo.line, singleVLine ? 0 : null, sTo.ch).start + if (singleVLine) { + if (leftEnd.top < rightStart.top - 2) { + add(leftEnd.right, leftEnd.top, null, leftEnd.bottom) + add(leftSide, rightStart.top, rightStart.left, rightStart.bottom) + } else { + add(leftEnd.right, leftEnd.top, rightStart.left - leftEnd.right, leftEnd.bottom) + } + } + if (leftEnd.bottom < rightStart.top) + { add(leftSide, leftEnd.bottom, null, rightStart.top) } + } + + output.appendChild(fragment) + } + + // Cursor-blinking + function restartBlink(cm) { + if (!cm.state.focused) { return } + var display = cm.display + clearInterval(display.blinker) + var on = true + display.cursorDiv.style.visibility = "" + if (cm.options.cursorBlinkRate > 0) + { display.blinker = setInterval(function () { return display.cursorDiv.style.visibility = (on = !on) ? "" : "hidden"; }, + cm.options.cursorBlinkRate) } + else if (cm.options.cursorBlinkRate < 0) + { display.cursorDiv.style.visibility = "hidden" } + } + + function ensureFocus(cm) { + if (!cm.state.focused) { cm.display.input.focus(); onFocus(cm) } + } + + function delayBlurEvent(cm) { + cm.state.delayingBlurEvent = true + setTimeout(function () { if (cm.state.delayingBlurEvent) { + cm.state.delayingBlurEvent = false + onBlur(cm) + } }, 100) + } + + function onFocus(cm, e) { + if (cm.state.delayingBlurEvent) { cm.state.delayingBlurEvent = false } + + if (cm.options.readOnly == "nocursor") { return } + if (!cm.state.focused) { + signal(cm, "focus", cm, e) + cm.state.focused = true + addClass(cm.display.wrapper, "CodeMirror-focused") + // This test prevents this from firing when a context + // menu is closed (since the input reset would kill the + // select-all detection hack) + if (!cm.curOp && cm.display.selForContextMenu != cm.doc.sel) { + cm.display.input.reset() + if (webkit) { setTimeout(function () { return cm.display.input.reset(true); }, 20) } // Issue #1730 + } + cm.display.input.receivedFocus() + } + restartBlink(cm) + } + function onBlur(cm, e) { + if (cm.state.delayingBlurEvent) { return } + + if (cm.state.focused) { + signal(cm, "blur", cm, e) + cm.state.focused = false + rmClass(cm.display.wrapper, "CodeMirror-focused") + } + clearInterval(cm.display.blinker) + setTimeout(function () { if (!cm.state.focused) { cm.display.shift = false } }, 150) + } + + // Read the actual heights of the rendered lines, and update their + // stored heights to match. + function updateHeightsInViewport(cm) { + var display = cm.display + var prevBottom = display.lineDiv.offsetTop + for (var i = 0; i < display.view.length; i++) { + var cur = display.view[i], height = (void 0) + if (cur.hidden) { continue } + if (ie && ie_version < 8) { + var bot = cur.node.offsetTop + cur.node.offsetHeight + height = bot - prevBottom + prevBottom = bot + } else { + var box = cur.node.getBoundingClientRect() + height = box.bottom - box.top + } + var diff = cur.line.height - height + if (height < 2) { height = textHeight(display) } + if (diff > .005 || diff < -.005) { + updateLineHeight(cur.line, height) + updateWidgetHeight(cur.line) + if (cur.rest) { for (var j = 0; j < cur.rest.length; j++) + { updateWidgetHeight(cur.rest[j]) } } + } + } + } + + // Read and store the height of line widgets associated with the + // given line. + function updateWidgetHeight(line) { + if (line.widgets) { for (var i = 0; i < line.widgets.length; ++i) { + var w = line.widgets[i], parent = w.node.parentNode + if (parent) { w.height = parent.offsetHeight } + } } + } + + // Compute the lines that are visible in a given viewport (defaults + // the the current scroll position). viewport may contain top, + // height, and ensure (see op.scrollToPos) properties. + function visibleLines(display, doc, viewport) { + var top = viewport && viewport.top != null ? Math.max(0, viewport.top) : display.scroller.scrollTop + top = Math.floor(top - paddingTop(display)) + var bottom = viewport && viewport.bottom != null ? viewport.bottom : top + display.wrapper.clientHeight + + var from = lineAtHeight(doc, top), to = lineAtHeight(doc, bottom) + // Ensure is a {from: {line, ch}, to: {line, ch}} object, and + // forces those lines into the viewport (if possible). + if (viewport && viewport.ensure) { + var ensureFrom = viewport.ensure.from.line, ensureTo = viewport.ensure.to.line + if (ensureFrom < from) { + from = ensureFrom + to = lineAtHeight(doc, heightAtLine(getLine(doc, ensureFrom)) + display.wrapper.clientHeight) + } else if (Math.min(ensureTo, doc.lastLine()) >= to) { + from = lineAtHeight(doc, heightAtLine(getLine(doc, ensureTo)) - display.wrapper.clientHeight) + to = ensureTo + } + } + return {from: from, to: Math.max(to, from + 1)} + } + + // Re-align line numbers and gutter marks to compensate for + // horizontal scrolling. + function alignHorizontally(cm) { + var display = cm.display, view = display.view + if (!display.alignWidgets && (!display.gutters.firstChild || !cm.options.fixedGutter)) { return } + var comp = compensateForHScroll(display) - display.scroller.scrollLeft + cm.doc.scrollLeft + var gutterW = display.gutters.offsetWidth, left = comp + "px" + for (var i = 0; i < view.length; i++) { if (!view[i].hidden) { + if (cm.options.fixedGutter) { + if (view[i].gutter) + { view[i].gutter.style.left = left } + if (view[i].gutterBackground) + { view[i].gutterBackground.style.left = left } + } + var align = view[i].alignable + if (align) { for (var j = 0; j < align.length; j++) + { align[j].style.left = left } } + } } + if (cm.options.fixedGutter) + { display.gutters.style.left = (comp + gutterW) + "px" } + } + + // Used to ensure that the line number gutter is still the right + // size for the current document size. Returns true when an update + // is needed. + function maybeUpdateLineNumberWidth(cm) { + if (!cm.options.lineNumbers) { return false } + var doc = cm.doc, last = lineNumberFor(cm.options, doc.first + doc.size - 1), display = cm.display + if (last.length != display.lineNumChars) { + var test = display.measure.appendChild(elt("div", [elt("div", last)], + "CodeMirror-linenumber CodeMirror-gutter-elt")) + var innerW = test.firstChild.offsetWidth, padding = test.offsetWidth - innerW + display.lineGutter.style.width = "" + display.lineNumInnerWidth = Math.max(innerW, display.lineGutter.offsetWidth - padding) + 1 + display.lineNumWidth = display.lineNumInnerWidth + padding + display.lineNumChars = display.lineNumInnerWidth ? last.length : -1 + display.lineGutter.style.width = display.lineNumWidth + "px" + updateGutterSpace(cm) + return true + } + return false + } + + // SCROLLING THINGS INTO VIEW + + // If an editor sits on the top or bottom of the window, partially + // scrolled out of view, this ensures that the cursor is visible. + function maybeScrollWindow(cm, rect) { + if (signalDOMEvent(cm, "scrollCursorIntoView")) { return } + + var display = cm.display, box = display.sizer.getBoundingClientRect(), doScroll = null + if (rect.top + box.top < 0) { doScroll = true } + else if (rect.bottom + box.top > (window.innerHeight || document.documentElement.clientHeight)) { doScroll = false } + if (doScroll != null && !phantom) { + var scrollNode = elt("div", "\u200b", null, ("position: absolute;\n top: " + (rect.top - display.viewOffset - paddingTop(cm.display)) + "px;\n height: " + (rect.bottom - rect.top + scrollGap(cm) + display.barHeight) + "px;\n left: " + (rect.left) + "px; width: " + (Math.max(2, rect.right - rect.left)) + "px;")) + cm.display.lineSpace.appendChild(scrollNode) + scrollNode.scrollIntoView(doScroll) + cm.display.lineSpace.removeChild(scrollNode) + } + } + + // Scroll a given position into view (immediately), verifying that + // it actually became visible (as line heights are accurately + // measured, the position of something may 'drift' during drawing). + function scrollPosIntoView(cm, pos, end, margin) { + if (margin == null) { margin = 0 } + var rect + if (!cm.options.lineWrapping && pos == end) { + // Set pos and end to the cursor positions around the character pos sticks to + // If pos.sticky == "before", that is around pos.ch - 1, otherwise around pos.ch + // If pos == Pos(_, 0, "before"), pos and end are unchanged + pos = pos.ch ? Pos(pos.line, pos.sticky == "before" ? pos.ch - 1 : pos.ch, "after") : pos + end = pos.sticky == "before" ? Pos(pos.line, pos.ch + 1, "before") : pos + } + for (var limit = 0; limit < 5; limit++) { + var changed = false + var coords = cursorCoords(cm, pos) + var endCoords = !end || end == pos ? coords : cursorCoords(cm, end) + rect = {left: Math.min(coords.left, endCoords.left), + top: Math.min(coords.top, endCoords.top) - margin, + right: Math.max(coords.left, endCoords.left), + bottom: Math.max(coords.bottom, endCoords.bottom) + margin} + var scrollPos = calculateScrollPos(cm, rect) + var startTop = cm.doc.scrollTop, startLeft = cm.doc.scrollLeft + if (scrollPos.scrollTop != null) { + updateScrollTop(cm, scrollPos.scrollTop) + if (Math.abs(cm.doc.scrollTop - startTop) > 1) { changed = true } + } + if (scrollPos.scrollLeft != null) { + setScrollLeft(cm, scrollPos.scrollLeft) + if (Math.abs(cm.doc.scrollLeft - startLeft) > 1) { changed = true } + } + if (!changed) { break } + } + return rect + } + + // Scroll a given set of coordinates into view (immediately). + function scrollIntoView(cm, rect) { + var scrollPos = calculateScrollPos(cm, rect) + if (scrollPos.scrollTop != null) { updateScrollTop(cm, scrollPos.scrollTop) } + if (scrollPos.scrollLeft != null) { setScrollLeft(cm, scrollPos.scrollLeft) } + } + + // Calculate a new scroll position needed to scroll the given + // rectangle into view. Returns an object with scrollTop and + // scrollLeft properties. When these are undefined, the + // vertical/horizontal position does not need to be adjusted. + function calculateScrollPos(cm, rect) { + var display = cm.display, snapMargin = textHeight(cm.display) + if (rect.top < 0) { rect.top = 0 } + var screentop = cm.curOp && cm.curOp.scrollTop != null ? cm.curOp.scrollTop : display.scroller.scrollTop + var screen = displayHeight(cm), result = {} + if (rect.bottom - rect.top > screen) { rect.bottom = rect.top + screen } + var docBottom = cm.doc.height + paddingVert(display) + var atTop = rect.top < snapMargin, atBottom = rect.bottom > docBottom - snapMargin + if (rect.top < screentop) { + result.scrollTop = atTop ? 0 : rect.top + } else if (rect.bottom > screentop + screen) { + var newTop = Math.min(rect.top, (atBottom ? docBottom : rect.bottom) - screen) + if (newTop != screentop) { result.scrollTop = newTop } + } + + var screenleft = cm.curOp && cm.curOp.scrollLeft != null ? cm.curOp.scrollLeft : display.scroller.scrollLeft + var screenw = displayWidth(cm) - (cm.options.fixedGutter ? display.gutters.offsetWidth : 0) + var tooWide = rect.right - rect.left > screenw + if (tooWide) { rect.right = rect.left + screenw } + if (rect.left < 10) + { result.scrollLeft = 0 } + else if (rect.left < screenleft) + { result.scrollLeft = Math.max(0, rect.left - (tooWide ? 0 : 10)) } + else if (rect.right > screenw + screenleft - 3) + { result.scrollLeft = rect.right + (tooWide ? 0 : 10) - screenw } + return result + } + + // Store a relative adjustment to the scroll position in the current + // operation (to be applied when the operation finishes). + function addToScrollTop(cm, top) { + if (top == null) { return } + resolveScrollToPos(cm) + cm.curOp.scrollTop = (cm.curOp.scrollTop == null ? cm.doc.scrollTop : cm.curOp.scrollTop) + top + } + + // Make sure that at the end of the operation the current cursor is + // shown. + function ensureCursorVisible(cm) { + resolveScrollToPos(cm) + var cur = cm.getCursor() + cm.curOp.scrollToPos = {from: cur, to: cur, margin: cm.options.cursorScrollMargin} + } + + function scrollToCoords(cm, x, y) { + if (x != null || y != null) { resolveScrollToPos(cm) } + if (x != null) { cm.curOp.scrollLeft = x } + if (y != null) { cm.curOp.scrollTop = y } + } + + function scrollToRange(cm, range) { + resolveScrollToPos(cm) + cm.curOp.scrollToPos = range + } + + // When an operation has its scrollToPos property set, and another + // scroll action is applied before the end of the operation, this + // 'simulates' scrolling that position into view in a cheap way, so + // that the effect of intermediate scroll commands is not ignored. + function resolveScrollToPos(cm) { + var range = cm.curOp.scrollToPos + if (range) { + cm.curOp.scrollToPos = null + var from = estimateCoords(cm, range.from), to = estimateCoords(cm, range.to) + scrollToCoordsRange(cm, from, to, range.margin) + } + } + + function scrollToCoordsRange(cm, from, to, margin) { + var sPos = calculateScrollPos(cm, { + left: Math.min(from.left, to.left), + top: Math.min(from.top, to.top) - margin, + right: Math.max(from.right, to.right), + bottom: Math.max(from.bottom, to.bottom) + margin + }) + scrollToCoords(cm, sPos.scrollLeft, sPos.scrollTop) + } + + // Sync the scrollable area and scrollbars, ensure the viewport + // covers the visible area. + function updateScrollTop(cm, val) { + if (Math.abs(cm.doc.scrollTop - val) < 2) { return } + if (!gecko) { updateDisplaySimple(cm, {top: val}) } + setScrollTop(cm, val, true) + if (gecko) { updateDisplaySimple(cm) } + startWorker(cm, 100) + } + + function setScrollTop(cm, val, forceScroll) { + val = Math.min(cm.display.scroller.scrollHeight - cm.display.scroller.clientHeight, val) + if (cm.display.scroller.scrollTop == val && !forceScroll) { return } + cm.doc.scrollTop = val + cm.display.scrollbars.setScrollTop(val) + if (cm.display.scroller.scrollTop != val) { cm.display.scroller.scrollTop = val } + } + + // Sync scroller and scrollbar, ensure the gutter elements are + // aligned. + function setScrollLeft(cm, val, isScroller, forceScroll) { + val = Math.min(val, cm.display.scroller.scrollWidth - cm.display.scroller.clientWidth) + if ((isScroller ? val == cm.doc.scrollLeft : Math.abs(cm.doc.scrollLeft - val) < 2) && !forceScroll) { return } + cm.doc.scrollLeft = val + alignHorizontally(cm) + if (cm.display.scroller.scrollLeft != val) { cm.display.scroller.scrollLeft = val } + cm.display.scrollbars.setScrollLeft(val) + } + + // SCROLLBARS + + // Prepare DOM reads needed to update the scrollbars. Done in one + // shot to minimize update/measure roundtrips. + function measureForScrollbars(cm) { + var d = cm.display, gutterW = d.gutters.offsetWidth + var docH = Math.round(cm.doc.height + paddingVert(cm.display)) + return { + clientHeight: d.scroller.clientHeight, + viewHeight: d.wrapper.clientHeight, + scrollWidth: d.scroller.scrollWidth, clientWidth: d.scroller.clientWidth, + viewWidth: d.wrapper.clientWidth, + barLeft: cm.options.fixedGutter ? gutterW : 0, + docHeight: docH, + scrollHeight: docH + scrollGap(cm) + d.barHeight, + nativeBarWidth: d.nativeBarWidth, + gutterWidth: gutterW + } + } + + var NativeScrollbars = function(place, scroll, cm) { + this.cm = cm + var vert = this.vert = elt("div", [elt("div", null, null, "min-width: 1px")], "CodeMirror-vscrollbar") + var horiz = this.horiz = elt("div", [elt("div", null, null, "height: 100%; min-height: 1px")], "CodeMirror-hscrollbar") + place(vert); place(horiz) + + on(vert, "scroll", function () { + if (vert.clientHeight) { scroll(vert.scrollTop, "vertical") } + }) + on(horiz, "scroll", function () { + if (horiz.clientWidth) { scroll(horiz.scrollLeft, "horizontal") } + }) + + this.checkedZeroWidth = false + // Need to set a minimum width to see the scrollbar on IE7 (but must not set it on IE8). + if (ie && ie_version < 8) { this.horiz.style.minHeight = this.vert.style.minWidth = "18px" } + }; + + NativeScrollbars.prototype.update = function (measure) { + var needsH = measure.scrollWidth > measure.clientWidth + 1 + var needsV = measure.scrollHeight > measure.clientHeight + 1 + var sWidth = measure.nativeBarWidth + + if (needsV) { + this.vert.style.display = "block" + this.vert.style.bottom = needsH ? sWidth + "px" : "0" + var totalHeight = measure.viewHeight - (needsH ? sWidth : 0) + // A bug in IE8 can cause this value to be negative, so guard it. + this.vert.firstChild.style.height = + Math.max(0, measure.scrollHeight - measure.clientHeight + totalHeight) + "px" + } else { + this.vert.style.display = "" + this.vert.firstChild.style.height = "0" + } + + if (needsH) { + this.horiz.style.display = "block" + this.horiz.style.right = needsV ? sWidth + "px" : "0" + this.horiz.style.left = measure.barLeft + "px" + var totalWidth = measure.viewWidth - measure.barLeft - (needsV ? sWidth : 0) + this.horiz.firstChild.style.width = + Math.max(0, measure.scrollWidth - measure.clientWidth + totalWidth) + "px" + } else { + this.horiz.style.display = "" + this.horiz.firstChild.style.width = "0" + } + + if (!this.checkedZeroWidth && measure.clientHeight > 0) { + if (sWidth == 0) { this.zeroWidthHack() } + this.checkedZeroWidth = true + } + + return {right: needsV ? sWidth : 0, bottom: needsH ? sWidth : 0} + }; + + NativeScrollbars.prototype.setScrollLeft = function (pos) { + if (this.horiz.scrollLeft != pos) { this.horiz.scrollLeft = pos } + if (this.disableHoriz) { this.enableZeroWidthBar(this.horiz, this.disableHoriz, "horiz") } + }; + + NativeScrollbars.prototype.setScrollTop = function (pos) { + if (this.vert.scrollTop != pos) { this.vert.scrollTop = pos } + if (this.disableVert) { this.enableZeroWidthBar(this.vert, this.disableVert, "vert") } + }; + + NativeScrollbars.prototype.zeroWidthHack = function () { + var w = mac && !mac_geMountainLion ? "12px" : "18px" + this.horiz.style.height = this.vert.style.width = w + this.horiz.style.pointerEvents = this.vert.style.pointerEvents = "none" + this.disableHoriz = new Delayed + this.disableVert = new Delayed + }; + + NativeScrollbars.prototype.enableZeroWidthBar = function (bar, delay, type) { + bar.style.pointerEvents = "auto" + function maybeDisable() { + // To find out whether the scrollbar is still visible, we + // check whether the element under the pixel in the bottom + // right corner of the scrollbar box is the scrollbar box + // itself (when the bar is still visible) or its filler child + // (when the bar is hidden). If it is still visible, we keep + // it enabled, if it's hidden, we disable pointer events. + var box = bar.getBoundingClientRect() + var elt = type == "vert" ? document.elementFromPoint(box.right - 1, (box.top + box.bottom) / 2) + : document.elementFromPoint((box.right + box.left) / 2, box.bottom - 1) + if (elt != bar) { bar.style.pointerEvents = "none" } + else { delay.set(1000, maybeDisable) } + } + delay.set(1000, maybeDisable) + }; + + NativeScrollbars.prototype.clear = function () { + var parent = this.horiz.parentNode + parent.removeChild(this.horiz) + parent.removeChild(this.vert) + }; + + var NullScrollbars = function () {}; + + NullScrollbars.prototype.update = function () { return {bottom: 0, right: 0} }; + NullScrollbars.prototype.setScrollLeft = function () {}; + NullScrollbars.prototype.setScrollTop = function () {}; + NullScrollbars.prototype.clear = function () {}; + + function updateScrollbars(cm, measure) { + if (!measure) { measure = measureForScrollbars(cm) } + var startWidth = cm.display.barWidth, startHeight = cm.display.barHeight + updateScrollbarsInner(cm, measure) + for (var i = 0; i < 4 && startWidth != cm.display.barWidth || startHeight != cm.display.barHeight; i++) { + if (startWidth != cm.display.barWidth && cm.options.lineWrapping) + { updateHeightsInViewport(cm) } + updateScrollbarsInner(cm, measureForScrollbars(cm)) + startWidth = cm.display.barWidth; startHeight = cm.display.barHeight + } + } + + // Re-synchronize the fake scrollbars with the actual size of the + // content. + function updateScrollbarsInner(cm, measure) { + var d = cm.display + var sizes = d.scrollbars.update(measure) + + d.sizer.style.paddingRight = (d.barWidth = sizes.right) + "px" + d.sizer.style.paddingBottom = (d.barHeight = sizes.bottom) + "px" + d.heightForcer.style.borderBottom = sizes.bottom + "px solid transparent" + + if (sizes.right && sizes.bottom) { + d.scrollbarFiller.style.display = "block" + d.scrollbarFiller.style.height = sizes.bottom + "px" + d.scrollbarFiller.style.width = sizes.right + "px" + } else { d.scrollbarFiller.style.display = "" } + if (sizes.bottom && cm.options.coverGutterNextToScrollbar && cm.options.fixedGutter) { + d.gutterFiller.style.display = "block" + d.gutterFiller.style.height = sizes.bottom + "px" + d.gutterFiller.style.width = measure.gutterWidth + "px" + } else { d.gutterFiller.style.display = "" } + } + + var scrollbarModel = {"native": NativeScrollbars, "null": NullScrollbars} + + function initScrollbars(cm) { + if (cm.display.scrollbars) { + cm.display.scrollbars.clear() + if (cm.display.scrollbars.addClass) + { rmClass(cm.display.wrapper, cm.display.scrollbars.addClass) } + } + + cm.display.scrollbars = new scrollbarModel[cm.options.scrollbarStyle](function (node) { + cm.display.wrapper.insertBefore(node, cm.display.scrollbarFiller) + // Prevent clicks in the scrollbars from killing focus + on(node, "mousedown", function () { + if (cm.state.focused) { setTimeout(function () { return cm.display.input.focus(); }, 0) } + }) + node.setAttribute("cm-not-content", "true") + }, function (pos, axis) { + if (axis == "horizontal") { setScrollLeft(cm, pos) } + else { updateScrollTop(cm, pos) } + }, cm) + if (cm.display.scrollbars.addClass) + { addClass(cm.display.wrapper, cm.display.scrollbars.addClass) } + } + + // Operations are used to wrap a series of changes to the editor + // state in such a way that each change won't have to update the + // cursor and display (which would be awkward, slow, and + // error-prone). Instead, display updates are batched and then all + // combined and executed at once. + + var nextOpId = 0 + // Start a new operation. + function startOperation(cm) { + cm.curOp = { + cm: cm, + viewChanged: false, // Flag that indicates that lines might need to be redrawn + startHeight: cm.doc.height, // Used to detect need to update scrollbar + forceUpdate: false, // Used to force a redraw + updateInput: null, // Whether to reset the input textarea + typing: false, // Whether this reset should be careful to leave existing text (for compositing) + changeObjs: null, // Accumulated changes, for firing change events + cursorActivityHandlers: null, // Set of handlers to fire cursorActivity on + cursorActivityCalled: 0, // Tracks which cursorActivity handlers have been called already + selectionChanged: false, // Whether the selection needs to be redrawn + updateMaxLine: false, // Set when the widest line needs to be determined anew + scrollLeft: null, scrollTop: null, // Intermediate scroll position, not pushed to DOM yet + scrollToPos: null, // Used to scroll to a specific position + focus: false, + id: ++nextOpId // Unique ID + } + pushOperation(cm.curOp) + } + + // Finish an operation, updating the display and signalling delayed events + function endOperation(cm) { + var op = cm.curOp + finishOperation(op, function (group) { + for (var i = 0; i < group.ops.length; i++) + { group.ops[i].cm.curOp = null } + endOperations(group) + }) + } + + // The DOM updates done when an operation finishes are batched so + // that the minimum number of relayouts are required. + function endOperations(group) { + var ops = group.ops + for (var i = 0; i < ops.length; i++) // Read DOM + { endOperation_R1(ops[i]) } + for (var i$1 = 0; i$1 < ops.length; i$1++) // Write DOM (maybe) + { endOperation_W1(ops[i$1]) } + for (var i$2 = 0; i$2 < ops.length; i$2++) // Read DOM + { endOperation_R2(ops[i$2]) } + for (var i$3 = 0; i$3 < ops.length; i$3++) // Write DOM (maybe) + { endOperation_W2(ops[i$3]) } + for (var i$4 = 0; i$4 < ops.length; i$4++) // Read DOM + { endOperation_finish(ops[i$4]) } + } + + function endOperation_R1(op) { + var cm = op.cm, display = cm.display + maybeClipScrollbars(cm) + if (op.updateMaxLine) { findMaxLine(cm) } + + op.mustUpdate = op.viewChanged || op.forceUpdate || op.scrollTop != null || + op.scrollToPos && (op.scrollToPos.from.line < display.viewFrom || + op.scrollToPos.to.line >= display.viewTo) || + display.maxLineChanged && cm.options.lineWrapping + op.update = op.mustUpdate && + new DisplayUpdate(cm, op.mustUpdate && {top: op.scrollTop, ensure: op.scrollToPos}, op.forceUpdate) + } + + function endOperation_W1(op) { + op.updatedDisplay = op.mustUpdate && updateDisplayIfNeeded(op.cm, op.update) + } + + function endOperation_R2(op) { + var cm = op.cm, display = cm.display + if (op.updatedDisplay) { updateHeightsInViewport(cm) } + + op.barMeasure = measureForScrollbars(cm) + + // If the max line changed since it was last measured, measure it, + // and ensure the document's width matches it. + // updateDisplay_W2 will use these properties to do the actual resizing + if (display.maxLineChanged && !cm.options.lineWrapping) { + op.adjustWidthTo = measureChar(cm, display.maxLine, display.maxLine.text.length).left + 3 + cm.display.sizerWidth = op.adjustWidthTo + op.barMeasure.scrollWidth = + Math.max(display.scroller.clientWidth, display.sizer.offsetLeft + op.adjustWidthTo + scrollGap(cm) + cm.display.barWidth) + op.maxScrollLeft = Math.max(0, display.sizer.offsetLeft + op.adjustWidthTo - displayWidth(cm)) + } + + if (op.updatedDisplay || op.selectionChanged) + { op.preparedSelection = display.input.prepareSelection() } + } + + function endOperation_W2(op) { + var cm = op.cm + + if (op.adjustWidthTo != null) { + cm.display.sizer.style.minWidth = op.adjustWidthTo + "px" + if (op.maxScrollLeft < cm.doc.scrollLeft) + { setScrollLeft(cm, Math.min(cm.display.scroller.scrollLeft, op.maxScrollLeft), true) } + cm.display.maxLineChanged = false + } + + var takeFocus = op.focus && op.focus == activeElt() + if (op.preparedSelection) + { cm.display.input.showSelection(op.preparedSelection, takeFocus) } + if (op.updatedDisplay || op.startHeight != cm.doc.height) + { updateScrollbars(cm, op.barMeasure) } + if (op.updatedDisplay) + { setDocumentHeight(cm, op.barMeasure) } + + if (op.selectionChanged) { restartBlink(cm) } + + if (cm.state.focused && op.updateInput) + { cm.display.input.reset(op.typing) } + if (takeFocus) { ensureFocus(op.cm) } + } + + function endOperation_finish(op) { + var cm = op.cm, display = cm.display, doc = cm.doc + + if (op.updatedDisplay) { postUpdateDisplay(cm, op.update) } + + // Abort mouse wheel delta measurement, when scrolling explicitly + if (display.wheelStartX != null && (op.scrollTop != null || op.scrollLeft != null || op.scrollToPos)) + { display.wheelStartX = display.wheelStartY = null } + + // Propagate the scroll position to the actual DOM scroller + if (op.scrollTop != null) { setScrollTop(cm, op.scrollTop, op.forceScroll) } + + if (op.scrollLeft != null) { setScrollLeft(cm, op.scrollLeft, true, true) } + // If we need to scroll a specific position into view, do so. + if (op.scrollToPos) { + var rect = scrollPosIntoView(cm, clipPos(doc, op.scrollToPos.from), + clipPos(doc, op.scrollToPos.to), op.scrollToPos.margin) + maybeScrollWindow(cm, rect) + } + + // Fire events for markers that are hidden/unidden by editing or + // undoing + var hidden = op.maybeHiddenMarkers, unhidden = op.maybeUnhiddenMarkers + if (hidden) { for (var i = 0; i < hidden.length; ++i) + { if (!hidden[i].lines.length) { signal(hidden[i], "hide") } } } + if (unhidden) { for (var i$1 = 0; i$1 < unhidden.length; ++i$1) + { if (unhidden[i$1].lines.length) { signal(unhidden[i$1], "unhide") } } } + + if (display.wrapper.offsetHeight) + { doc.scrollTop = cm.display.scroller.scrollTop } + + // Fire change events, and delayed event handlers + if (op.changeObjs) + { signal(cm, "changes", cm, op.changeObjs) } + if (op.update) + { op.update.finish() } + } + + // Run the given function in an operation + function runInOp(cm, f) { + if (cm.curOp) { return f() } + startOperation(cm) + try { return f() } + finally { endOperation(cm) } + } + // Wraps a function in an operation. Returns the wrapped function. + function operation(cm, f) { + return function() { + if (cm.curOp) { return f.apply(cm, arguments) } + startOperation(cm) + try { return f.apply(cm, arguments) } + finally { endOperation(cm) } + } + } + // Used to add methods to editor and doc instances, wrapping them in + // operations. + function methodOp(f) { + return function() { + if (this.curOp) { return f.apply(this, arguments) } + startOperation(this) + try { return f.apply(this, arguments) } + finally { endOperation(this) } + } + } + function docMethodOp(f) { + return function() { + var cm = this.cm + if (!cm || cm.curOp) { return f.apply(this, arguments) } + startOperation(cm) + try { return f.apply(this, arguments) } + finally { endOperation(cm) } + } + } + + // Updates the display.view data structure for a given change to the + // document. From and to are in pre-change coordinates. Lendiff is + // the amount of lines added or subtracted by the change. This is + // used for changes that span multiple lines, or change the way + // lines are divided into visual lines. regLineChange (below) + // registers single-line changes. + function regChange(cm, from, to, lendiff) { + if (from == null) { from = cm.doc.first } + if (to == null) { to = cm.doc.first + cm.doc.size } + if (!lendiff) { lendiff = 0 } + + var display = cm.display + if (lendiff && to < display.viewTo && + (display.updateLineNumbers == null || display.updateLineNumbers > from)) + { display.updateLineNumbers = from } + + cm.curOp.viewChanged = true + + if (from >= display.viewTo) { // Change after + if (sawCollapsedSpans && visualLineNo(cm.doc, from) < display.viewTo) + { resetView(cm) } + } else if (to <= display.viewFrom) { // Change before + if (sawCollapsedSpans && visualLineEndNo(cm.doc, to + lendiff) > display.viewFrom) { + resetView(cm) + } else { + display.viewFrom += lendiff + display.viewTo += lendiff + } + } else if (from <= display.viewFrom && to >= display.viewTo) { // Full overlap + resetView(cm) + } else if (from <= display.viewFrom) { // Top overlap + var cut = viewCuttingPoint(cm, to, to + lendiff, 1) + if (cut) { + display.view = display.view.slice(cut.index) + display.viewFrom = cut.lineN + display.viewTo += lendiff + } else { + resetView(cm) + } + } else if (to >= display.viewTo) { // Bottom overlap + var cut$1 = viewCuttingPoint(cm, from, from, -1) + if (cut$1) { + display.view = display.view.slice(0, cut$1.index) + display.viewTo = cut$1.lineN + } else { + resetView(cm) + } + } else { // Gap in the middle + var cutTop = viewCuttingPoint(cm, from, from, -1) + var cutBot = viewCuttingPoint(cm, to, to + lendiff, 1) + if (cutTop && cutBot) { + display.view = display.view.slice(0, cutTop.index) + .concat(buildViewArray(cm, cutTop.lineN, cutBot.lineN)) + .concat(display.view.slice(cutBot.index)) + display.viewTo += lendiff + } else { + resetView(cm) + } + } + + var ext = display.externalMeasured + if (ext) { + if (to < ext.lineN) + { ext.lineN += lendiff } + else if (from < ext.lineN + ext.size) + { display.externalMeasured = null } + } + } + + // Register a change to a single line. Type must be one of "text", + // "gutter", "class", "widget" + function regLineChange(cm, line, type) { + cm.curOp.viewChanged = true + var display = cm.display, ext = cm.display.externalMeasured + if (ext && line >= ext.lineN && line < ext.lineN + ext.size) + { display.externalMeasured = null } + + if (line < display.viewFrom || line >= display.viewTo) { return } + var lineView = display.view[findViewIndex(cm, line)] + if (lineView.node == null) { return } + var arr = lineView.changes || (lineView.changes = []) + if (indexOf(arr, type) == -1) { arr.push(type) } + } + + // Clear the view. + function resetView(cm) { + cm.display.viewFrom = cm.display.viewTo = cm.doc.first + cm.display.view = [] + cm.display.viewOffset = 0 + } + + function viewCuttingPoint(cm, oldN, newN, dir) { + var index = findViewIndex(cm, oldN), diff, view = cm.display.view + if (!sawCollapsedSpans || newN == cm.doc.first + cm.doc.size) + { return {index: index, lineN: newN} } + var n = cm.display.viewFrom + for (var i = 0; i < index; i++) + { n += view[i].size } + if (n != oldN) { + if (dir > 0) { + if (index == view.length - 1) { return null } + diff = (n + view[index].size) - oldN + index++ + } else { + diff = n - oldN + } + oldN += diff; newN += diff + } + while (visualLineNo(cm.doc, newN) != newN) { + if (index == (dir < 0 ? 0 : view.length - 1)) { return null } + newN += dir * view[index - (dir < 0 ? 1 : 0)].size + index += dir + } + return {index: index, lineN: newN} + } + + // Force the view to cover a given range, adding empty view element + // or clipping off existing ones as needed. + function adjustView(cm, from, to) { + var display = cm.display, view = display.view + if (view.length == 0 || from >= display.viewTo || to <= display.viewFrom) { + display.view = buildViewArray(cm, from, to) + display.viewFrom = from + } else { + if (display.viewFrom > from) + { display.view = buildViewArray(cm, from, display.viewFrom).concat(display.view) } + else if (display.viewFrom < from) + { display.view = display.view.slice(findViewIndex(cm, from)) } + display.viewFrom = from + if (display.viewTo < to) + { display.view = display.view.concat(buildViewArray(cm, display.viewTo, to)) } + else if (display.viewTo > to) + { display.view = display.view.slice(0, findViewIndex(cm, to)) } + } + display.viewTo = to + } + + // Count the number of lines in the view whose DOM representation is + // out of date (or nonexistent). + function countDirtyView(cm) { + var view = cm.display.view, dirty = 0 + for (var i = 0; i < view.length; i++) { + var lineView = view[i] + if (!lineView.hidden && (!lineView.node || lineView.changes)) { ++dirty } + } + return dirty + } + + // HIGHLIGHT WORKER + + function startWorker(cm, time) { + if (cm.doc.highlightFrontier < cm.display.viewTo) + { cm.state.highlight.set(time, bind(highlightWorker, cm)) } + } + + function highlightWorker(cm) { + var doc = cm.doc + if (doc.highlightFrontier >= cm.display.viewTo) { return } + var end = +new Date + cm.options.workTime + var context = getContextBefore(cm, doc.highlightFrontier) + var changedLines = [] + + doc.iter(context.line, Math.min(doc.first + doc.size, cm.display.viewTo + 500), function (line) { + if (context.line >= cm.display.viewFrom) { // Visible + var oldStyles = line.styles + var resetState = line.text.length > cm.options.maxHighlightLength ? copyState(doc.mode, context.state) : null + var highlighted = highlightLine(cm, line, context, true) + if (resetState) { context.state = resetState } + line.styles = highlighted.styles + var oldCls = line.styleClasses, newCls = highlighted.classes + if (newCls) { line.styleClasses = newCls } + else if (oldCls) { line.styleClasses = null } + var ischange = !oldStyles || oldStyles.length != line.styles.length || + oldCls != newCls && (!oldCls || !newCls || oldCls.bgClass != newCls.bgClass || oldCls.textClass != newCls.textClass) + for (var i = 0; !ischange && i < oldStyles.length; ++i) { ischange = oldStyles[i] != line.styles[i] } + if (ischange) { changedLines.push(context.line) } + line.stateAfter = context.save() + context.nextLine() + } else { + if (line.text.length <= cm.options.maxHighlightLength) + { processLine(cm, line.text, context) } + line.stateAfter = context.line % 5 == 0 ? context.save() : null + context.nextLine() + } + if (+new Date > end) { + startWorker(cm, cm.options.workDelay) + return true + } + }) + doc.highlightFrontier = context.line + doc.modeFrontier = Math.max(doc.modeFrontier, context.line) + if (changedLines.length) { runInOp(cm, function () { + for (var i = 0; i < changedLines.length; i++) + { regLineChange(cm, changedLines[i], "text") } + }) } + } + + // DISPLAY DRAWING + + var DisplayUpdate = function(cm, viewport, force) { + var display = cm.display + + this.viewport = viewport + // Store some values that we'll need later (but don't want to force a relayout for) + this.visible = visibleLines(display, cm.doc, viewport) + this.editorIsHidden = !display.wrapper.offsetWidth + this.wrapperHeight = display.wrapper.clientHeight + this.wrapperWidth = display.wrapper.clientWidth + this.oldDisplayWidth = displayWidth(cm) + this.force = force + this.dims = getDimensions(cm) + this.events = [] + }; + + DisplayUpdate.prototype.signal = function (emitter, type) { + if (hasHandler(emitter, type)) + { this.events.push(arguments) } + }; + DisplayUpdate.prototype.finish = function () { + var this$1 = this; + + for (var i = 0; i < this.events.length; i++) + { signal.apply(null, this$1.events[i]) } + }; + + function maybeClipScrollbars(cm) { + var display = cm.display + if (!display.scrollbarsClipped && display.scroller.offsetWidth) { + display.nativeBarWidth = display.scroller.offsetWidth - display.scroller.clientWidth + display.heightForcer.style.height = scrollGap(cm) + "px" + display.sizer.style.marginBottom = -display.nativeBarWidth + "px" + display.sizer.style.borderRightWidth = scrollGap(cm) + "px" + display.scrollbarsClipped = true + } + } + + function selectionSnapshot(cm) { + if (cm.hasFocus()) { return null } + var active = activeElt() + if (!active || !contains(cm.display.lineDiv, active)) { return null } + var result = {activeElt: active} + if (window.getSelection) { + var sel = window.getSelection() + if (sel.anchorNode && sel.extend && contains(cm.display.lineDiv, sel.anchorNode)) { + result.anchorNode = sel.anchorNode + result.anchorOffset = sel.anchorOffset + result.focusNode = sel.focusNode + result.focusOffset = sel.focusOffset + } + } + return result + } + + function restoreSelection(snapshot) { + if (!snapshot || !snapshot.activeElt || snapshot.activeElt == activeElt()) { return } + snapshot.activeElt.focus() + if (snapshot.anchorNode && contains(document.body, snapshot.anchorNode) && contains(document.body, snapshot.focusNode)) { + var sel = window.getSelection(), range = document.createRange() + range.setEnd(snapshot.anchorNode, snapshot.anchorOffset) + range.collapse(false) + sel.removeAllRanges() + sel.addRange(range) + sel.extend(snapshot.focusNode, snapshot.focusOffset) + } + } + + // Does the actual updating of the line display. Bails out + // (returning false) when there is nothing to be done and forced is + // false. + function updateDisplayIfNeeded(cm, update) { + var display = cm.display, doc = cm.doc + + if (update.editorIsHidden) { + resetView(cm) + return false + } + + // Bail out if the visible area is already rendered and nothing changed. + if (!update.force && + update.visible.from >= display.viewFrom && update.visible.to <= display.viewTo && + (display.updateLineNumbers == null || display.updateLineNumbers >= display.viewTo) && + display.renderedView == display.view && countDirtyView(cm) == 0) + { return false } + + if (maybeUpdateLineNumberWidth(cm)) { + resetView(cm) + update.dims = getDimensions(cm) + } + + // Compute a suitable new viewport (from & to) + var end = doc.first + doc.size + var from = Math.max(update.visible.from - cm.options.viewportMargin, doc.first) + var to = Math.min(end, update.visible.to + cm.options.viewportMargin) + if (display.viewFrom < from && from - display.viewFrom < 20) { from = Math.max(doc.first, display.viewFrom) } + if (display.viewTo > to && display.viewTo - to < 20) { to = Math.min(end, display.viewTo) } + if (sawCollapsedSpans) { + from = visualLineNo(cm.doc, from) + to = visualLineEndNo(cm.doc, to) + } + + var different = from != display.viewFrom || to != display.viewTo || + display.lastWrapHeight != update.wrapperHeight || display.lastWrapWidth != update.wrapperWidth + adjustView(cm, from, to) + + display.viewOffset = heightAtLine(getLine(cm.doc, display.viewFrom)) + // Position the mover div to align with the current scroll position + cm.display.mover.style.top = display.viewOffset + "px" + + var toUpdate = countDirtyView(cm) + if (!different && toUpdate == 0 && !update.force && display.renderedView == display.view && + (display.updateLineNumbers == null || display.updateLineNumbers >= display.viewTo)) + { return false } + + // For big changes, we hide the enclosing element during the + // update, since that speeds up the operations on most browsers. + var selSnapshot = selectionSnapshot(cm) + if (toUpdate > 4) { display.lineDiv.style.display = "none" } + patchDisplay(cm, display.updateLineNumbers, update.dims) + if (toUpdate > 4) { display.lineDiv.style.display = "" } + display.renderedView = display.view + // There might have been a widget with a focused element that got + // hidden or updated, if so re-focus it. + restoreSelection(selSnapshot) + + // Prevent selection and cursors from interfering with the scroll + // width and height. + removeChildren(display.cursorDiv) + removeChildren(display.selectionDiv) + display.gutters.style.height = display.sizer.style.minHeight = 0 + + if (different) { + display.lastWrapHeight = update.wrapperHeight + display.lastWrapWidth = update.wrapperWidth + startWorker(cm, 400) + } + + display.updateLineNumbers = null + + return true + } + + function postUpdateDisplay(cm, update) { + var viewport = update.viewport + + for (var first = true;; first = false) { + if (!first || !cm.options.lineWrapping || update.oldDisplayWidth == displayWidth(cm)) { + // Clip forced viewport to actual scrollable area. + if (viewport && viewport.top != null) + { viewport = {top: Math.min(cm.doc.height + paddingVert(cm.display) - displayHeight(cm), viewport.top)} } + // Updated line heights might result in the drawn area not + // actually covering the viewport. Keep looping until it does. + update.visible = visibleLines(cm.display, cm.doc, viewport) + if (update.visible.from >= cm.display.viewFrom && update.visible.to <= cm.display.viewTo) + { break } + } + if (!updateDisplayIfNeeded(cm, update)) { break } + updateHeightsInViewport(cm) + var barMeasure = measureForScrollbars(cm) + updateSelection(cm) + updateScrollbars(cm, barMeasure) + setDocumentHeight(cm, barMeasure) + update.force = false + } + + update.signal(cm, "update", cm) + if (cm.display.viewFrom != cm.display.reportedViewFrom || cm.display.viewTo != cm.display.reportedViewTo) { + update.signal(cm, "viewportChange", cm, cm.display.viewFrom, cm.display.viewTo) + cm.display.reportedViewFrom = cm.display.viewFrom; cm.display.reportedViewTo = cm.display.viewTo + } + } + + function updateDisplaySimple(cm, viewport) { + var update = new DisplayUpdate(cm, viewport) + if (updateDisplayIfNeeded(cm, update)) { + updateHeightsInViewport(cm) + postUpdateDisplay(cm, update) + var barMeasure = measureForScrollbars(cm) + updateSelection(cm) + updateScrollbars(cm, barMeasure) + setDocumentHeight(cm, barMeasure) + update.finish() + } + } + + // Sync the actual display DOM structure with display.view, removing + // nodes for lines that are no longer in view, and creating the ones + // that are not there yet, and updating the ones that are out of + // date. + function patchDisplay(cm, updateNumbersFrom, dims) { + var display = cm.display, lineNumbers = cm.options.lineNumbers + var container = display.lineDiv, cur = container.firstChild + + function rm(node) { + var next = node.nextSibling + // Works around a throw-scroll bug in OS X Webkit + if (webkit && mac && cm.display.currentWheelTarget == node) + { node.style.display = "none" } + else + { node.parentNode.removeChild(node) } + return next + } + + var view = display.view, lineN = display.viewFrom + // Loop over the elements in the view, syncing cur (the DOM nodes + // in display.lineDiv) with the view as we go. + for (var i = 0; i < view.length; i++) { + var lineView = view[i] + if (lineView.hidden) { + } else if (!lineView.node || lineView.node.parentNode != container) { // Not drawn yet + var node = buildLineElement(cm, lineView, lineN, dims) + container.insertBefore(node, cur) + } else { // Already drawn + while (cur != lineView.node) { cur = rm(cur) } + var updateNumber = lineNumbers && updateNumbersFrom != null && + updateNumbersFrom <= lineN && lineView.lineNumber + if (lineView.changes) { + if (indexOf(lineView.changes, "gutter") > -1) { updateNumber = false } + updateLineForChanges(cm, lineView, lineN, dims) + } + if (updateNumber) { + removeChildren(lineView.lineNumber) + lineView.lineNumber.appendChild(document.createTextNode(lineNumberFor(cm.options, lineN))) + } + cur = lineView.node.nextSibling + } + lineN += lineView.size + } + while (cur) { cur = rm(cur) } + } + + function updateGutterSpace(cm) { + var width = cm.display.gutters.offsetWidth + cm.display.sizer.style.marginLeft = width + "px" + } + + function setDocumentHeight(cm, measure) { + cm.display.sizer.style.minHeight = measure.docHeight + "px" + cm.display.heightForcer.style.top = measure.docHeight + "px" + cm.display.gutters.style.height = (measure.docHeight + cm.display.barHeight + scrollGap(cm)) + "px" + } + + // Rebuild the gutter elements, ensure the margin to the left of the + // code matches their width. + function updateGutters(cm) { + var gutters = cm.display.gutters, specs = cm.options.gutters + removeChildren(gutters) + var i = 0 + for (; i < specs.length; ++i) { + var gutterClass = specs[i] + var gElt = gutters.appendChild(elt("div", null, "CodeMirror-gutter " + gutterClass)) + if (gutterClass == "CodeMirror-linenumbers") { + cm.display.lineGutter = gElt + gElt.style.width = (cm.display.lineNumWidth || 1) + "px" + } + } + gutters.style.display = i ? "" : "none" + updateGutterSpace(cm) + } + + // Make sure the gutters options contains the element + // "CodeMirror-linenumbers" when the lineNumbers option is true. + function setGuttersForLineNumbers(options) { + var found = indexOf(options.gutters, "CodeMirror-linenumbers") + if (found == -1 && options.lineNumbers) { + options.gutters = options.gutters.concat(["CodeMirror-linenumbers"]) + } else if (found > -1 && !options.lineNumbers) { + options.gutters = options.gutters.slice(0) + options.gutters.splice(found, 1) + } + } + + var wheelSamples = 0; + var wheelPixelsPerUnit = null; + // Fill in a browser-detected starting value on browsers where we + // know one. These don't have to be accurate -- the result of them + // being wrong would just be a slight flicker on the first wheel + // scroll (if it is large enough). + if (ie) { wheelPixelsPerUnit = -.53 } + else if (gecko) { wheelPixelsPerUnit = 15 } + else if (chrome) { wheelPixelsPerUnit = -.7 } + else if (safari) { wheelPixelsPerUnit = -1/3 } + + function wheelEventDelta(e) { + var dx = e.wheelDeltaX, dy = e.wheelDeltaY + if (dx == null && e.detail && e.axis == e.HORIZONTAL_AXIS) { dx = e.detail } + if (dy == null && e.detail && e.axis == e.VERTICAL_AXIS) { dy = e.detail } + else if (dy == null) { dy = e.wheelDelta } + return {x: dx, y: dy} + } + function wheelEventPixels(e) { + var delta = wheelEventDelta(e) + delta.x *= wheelPixelsPerUnit + delta.y *= wheelPixelsPerUnit + return delta + } + + function onScrollWheel(cm, e) { + var delta = wheelEventDelta(e), dx = delta.x, dy = delta.y + + var display = cm.display, scroll = display.scroller + // Quit if there's nothing to scroll here + var canScrollX = scroll.scrollWidth > scroll.clientWidth + var canScrollY = scroll.scrollHeight > scroll.clientHeight + if (!(dx && canScrollX || dy && canScrollY)) { return } + + // Webkit browsers on OS X abort momentum scrolls when the target + // of the scroll event is removed from the scrollable element. + // This hack (see related code in patchDisplay) makes sure the + // element is kept around. + if (dy && mac && webkit) { + outer: for (var cur = e.target, view = display.view; cur != scroll; cur = cur.parentNode) { + for (var i = 0; i < view.length; i++) { + if (view[i].node == cur) { + cm.display.currentWheelTarget = cur + break outer + } + } + } + } + + // On some browsers, horizontal scrolling will cause redraws to + // happen before the gutter has been realigned, causing it to + // wriggle around in a most unseemly way. When we have an + // estimated pixels/delta value, we just handle horizontal + // scrolling entirely here. It'll be slightly off from native, but + // better than glitching out. + if (dx && !gecko && !presto && wheelPixelsPerUnit != null) { + if (dy && canScrollY) + { updateScrollTop(cm, Math.max(0, scroll.scrollTop + dy * wheelPixelsPerUnit)) } + setScrollLeft(cm, Math.max(0, scroll.scrollLeft + dx * wheelPixelsPerUnit)) + // Only prevent default scrolling if vertical scrolling is + // actually possible. Otherwise, it causes vertical scroll + // jitter on OSX trackpads when deltaX is small and deltaY + // is large (issue #3579) + if (!dy || (dy && canScrollY)) + { e_preventDefault(e) } + display.wheelStartX = null // Abort measurement, if in progress + return + } + + // 'Project' the visible viewport to cover the area that is being + // scrolled into view (if we know enough to estimate it). + if (dy && wheelPixelsPerUnit != null) { + var pixels = dy * wheelPixelsPerUnit + var top = cm.doc.scrollTop, bot = top + display.wrapper.clientHeight + if (pixels < 0) { top = Math.max(0, top + pixels - 50) } + else { bot = Math.min(cm.doc.height, bot + pixels + 50) } + updateDisplaySimple(cm, {top: top, bottom: bot}) + } + + if (wheelSamples < 20) { + if (display.wheelStartX == null) { + display.wheelStartX = scroll.scrollLeft; display.wheelStartY = scroll.scrollTop + display.wheelDX = dx; display.wheelDY = dy + setTimeout(function () { + if (display.wheelStartX == null) { return } + var movedX = scroll.scrollLeft - display.wheelStartX + var movedY = scroll.scrollTop - display.wheelStartY + var sample = (movedY && display.wheelDY && movedY / display.wheelDY) || + (movedX && display.wheelDX && movedX / display.wheelDX) + display.wheelStartX = display.wheelStartY = null + if (!sample) { return } + wheelPixelsPerUnit = (wheelPixelsPerUnit * wheelSamples + sample) / (wheelSamples + 1) + ++wheelSamples + }, 200) + } else { + display.wheelDX += dx; display.wheelDY += dy + } + } + } + + // Selection objects are immutable. A new one is created every time + // the selection changes. A selection is one or more non-overlapping + // (and non-touching) ranges, sorted, and an integer that indicates + // which one is the primary selection (the one that's scrolled into + // view, that getCursor returns, etc). + var Selection = function(ranges, primIndex) { + this.ranges = ranges + this.primIndex = primIndex + }; + + Selection.prototype.primary = function () { return this.ranges[this.primIndex] }; + + Selection.prototype.equals = function (other) { + var this$1 = this; + + if (other == this) { return true } + if (other.primIndex != this.primIndex || other.ranges.length != this.ranges.length) { return false } + for (var i = 0; i < this.ranges.length; i++) { + var here = this$1.ranges[i], there = other.ranges[i] + if (!equalCursorPos(here.anchor, there.anchor) || !equalCursorPos(here.head, there.head)) { return false } + } + return true + }; + + Selection.prototype.deepCopy = function () { + var this$1 = this; + + var out = [] + for (var i = 0; i < this.ranges.length; i++) + { out[i] = new Range(copyPos(this$1.ranges[i].anchor), copyPos(this$1.ranges[i].head)) } + return new Selection(out, this.primIndex) + }; + + Selection.prototype.somethingSelected = function () { + var this$1 = this; + + for (var i = 0; i < this.ranges.length; i++) + { if (!this$1.ranges[i].empty()) { return true } } + return false + }; + + Selection.prototype.contains = function (pos, end) { + var this$1 = this; + + if (!end) { end = pos } + for (var i = 0; i < this.ranges.length; i++) { + var range = this$1.ranges[i] + if (cmp(end, range.from()) >= 0 && cmp(pos, range.to()) <= 0) + { return i } + } + return -1 + }; + + var Range = function(anchor, head) { + this.anchor = anchor; this.head = head + }; + + Range.prototype.from = function () { return minPos(this.anchor, this.head) }; + Range.prototype.to = function () { return maxPos(this.anchor, this.head) }; + Range.prototype.empty = function () { return this.head.line == this.anchor.line && this.head.ch == this.anchor.ch }; + + // Take an unsorted, potentially overlapping set of ranges, and + // build a selection out of it. 'Consumes' ranges array (modifying + // it). + function normalizeSelection(ranges, primIndex) { + var prim = ranges[primIndex] + ranges.sort(function (a, b) { return cmp(a.from(), b.from()); }) + primIndex = indexOf(ranges, prim) + for (var i = 1; i < ranges.length; i++) { + var cur = ranges[i], prev = ranges[i - 1] + if (cmp(prev.to(), cur.from()) >= 0) { + var from = minPos(prev.from(), cur.from()), to = maxPos(prev.to(), cur.to()) + var inv = prev.empty() ? cur.from() == cur.head : prev.from() == prev.head + if (i <= primIndex) { --primIndex } + ranges.splice(--i, 2, new Range(inv ? to : from, inv ? from : to)) + } + } + return new Selection(ranges, primIndex) + } + + function simpleSelection(anchor, head) { + return new Selection([new Range(anchor, head || anchor)], 0) + } + + // Compute the position of the end of a change (its 'to' property + // refers to the pre-change end). + function changeEnd(change) { + if (!change.text) { return change.to } + return Pos(change.from.line + change.text.length - 1, + lst(change.text).length + (change.text.length == 1 ? change.from.ch : 0)) + } + + // Adjust a position to refer to the post-change position of the + // same text, or the end of the change if the change covers it. + function adjustForChange(pos, change) { + if (cmp(pos, change.from) < 0) { return pos } + if (cmp(pos, change.to) <= 0) { return changeEnd(change) } + + var line = pos.line + change.text.length - (change.to.line - change.from.line) - 1, ch = pos.ch + if (pos.line == change.to.line) { ch += changeEnd(change).ch - change.to.ch } + return Pos(line, ch) + } + + function computeSelAfterChange(doc, change) { + var out = [] + for (var i = 0; i < doc.sel.ranges.length; i++) { + var range = doc.sel.ranges[i] + out.push(new Range(adjustForChange(range.anchor, change), + adjustForChange(range.head, change))) + } + return normalizeSelection(out, doc.sel.primIndex) + } + + function offsetPos(pos, old, nw) { + if (pos.line == old.line) + { return Pos(nw.line, pos.ch - old.ch + nw.ch) } + else + { return Pos(nw.line + (pos.line - old.line), pos.ch) } + } + + // Used by replaceSelections to allow moving the selection to the + // start or around the replaced test. Hint may be "start" or "around". + function computeReplacedSel(doc, changes, hint) { + var out = [] + var oldPrev = Pos(doc.first, 0), newPrev = oldPrev + for (var i = 0; i < changes.length; i++) { + var change = changes[i] + var from = offsetPos(change.from, oldPrev, newPrev) + var to = offsetPos(changeEnd(change), oldPrev, newPrev) + oldPrev = change.to + newPrev = to + if (hint == "around") { + var range = doc.sel.ranges[i], inv = cmp(range.head, range.anchor) < 0 + out[i] = new Range(inv ? to : from, inv ? from : to) + } else { + out[i] = new Range(from, from) + } + } + return new Selection(out, doc.sel.primIndex) + } + + // Used to get the editor into a consistent state again when options change. + + function loadMode(cm) { + cm.doc.mode = getMode(cm.options, cm.doc.modeOption) + resetModeState(cm) + } + + function resetModeState(cm) { + cm.doc.iter(function (line) { + if (line.stateAfter) { line.stateAfter = null } + if (line.styles) { line.styles = null } + }) + cm.doc.modeFrontier = cm.doc.highlightFrontier = cm.doc.first + startWorker(cm, 100) + cm.state.modeGen++ + if (cm.curOp) { regChange(cm) } + } + + // DOCUMENT DATA STRUCTURE + + // By default, updates that start and end at the beginning of a line + // are treated specially, in order to make the association of line + // widgets and marker elements with the text behave more intuitive. + function isWholeLineUpdate(doc, change) { + return change.from.ch == 0 && change.to.ch == 0 && lst(change.text) == "" && + (!doc.cm || doc.cm.options.wholeLineUpdateBefore) + } + + // Perform a change on the document data structure. + function updateDoc(doc, change, markedSpans, estimateHeight) { + function spansFor(n) {return markedSpans ? markedSpans[n] : null} + function update(line, text, spans) { + updateLine(line, text, spans, estimateHeight) + signalLater(line, "change", line, change) + } + function linesFor(start, end) { + var result = [] + for (var i = start; i < end; ++i) + { result.push(new Line(text[i], spansFor(i), estimateHeight)) } + return result + } + + var from = change.from, to = change.to, text = change.text + var firstLine = getLine(doc, from.line), lastLine = getLine(doc, to.line) + var lastText = lst(text), lastSpans = spansFor(text.length - 1), nlines = to.line - from.line + + // Adjust the line structure + if (change.full) { + doc.insert(0, linesFor(0, text.length)) + doc.remove(text.length, doc.size - text.length) + } else if (isWholeLineUpdate(doc, change)) { + // This is a whole-line replace. Treated specially to make + // sure line objects move the way they are supposed to. + var added = linesFor(0, text.length - 1) + update(lastLine, lastLine.text, lastSpans) + if (nlines) { doc.remove(from.line, nlines) } + if (added.length) { doc.insert(from.line, added) } + } else if (firstLine == lastLine) { + if (text.length == 1) { + update(firstLine, firstLine.text.slice(0, from.ch) + lastText + firstLine.text.slice(to.ch), lastSpans) + } else { + var added$1 = linesFor(1, text.length - 1) + added$1.push(new Line(lastText + firstLine.text.slice(to.ch), lastSpans, estimateHeight)) + update(firstLine, firstLine.text.slice(0, from.ch) + text[0], spansFor(0)) + doc.insert(from.line + 1, added$1) + } + } else if (text.length == 1) { + update(firstLine, firstLine.text.slice(0, from.ch) + text[0] + lastLine.text.slice(to.ch), spansFor(0)) + doc.remove(from.line + 1, nlines) + } else { + update(firstLine, firstLine.text.slice(0, from.ch) + text[0], spansFor(0)) + update(lastLine, lastText + lastLine.text.slice(to.ch), lastSpans) + var added$2 = linesFor(1, text.length - 1) + if (nlines > 1) { doc.remove(from.line + 1, nlines - 1) } + doc.insert(from.line + 1, added$2) + } + + signalLater(doc, "change", doc, change) + } + + // Call f for all linked documents. + function linkedDocs(doc, f, sharedHistOnly) { + function propagate(doc, skip, sharedHist) { + if (doc.linked) { for (var i = 0; i < doc.linked.length; ++i) { + var rel = doc.linked[i] + if (rel.doc == skip) { continue } + var shared = sharedHist && rel.sharedHist + if (sharedHistOnly && !shared) { continue } + f(rel.doc, shared) + propagate(rel.doc, doc, shared) + } } + } + propagate(doc, null, true) + } + + // Attach a document to an editor. + function attachDoc(cm, doc) { + if (doc.cm) { throw new Error("This document is already in use.") } + cm.doc = doc + doc.cm = cm + estimateLineHeights(cm) + loadMode(cm) + setDirectionClass(cm) + if (!cm.options.lineWrapping) { findMaxLine(cm) } + cm.options.mode = doc.modeOption + regChange(cm) + } + + function setDirectionClass(cm) { + ;(cm.doc.direction == "rtl" ? addClass : rmClass)(cm.display.lineDiv, "CodeMirror-rtl") + } + + function directionChanged(cm) { + runInOp(cm, function () { + setDirectionClass(cm) + regChange(cm) + }) + } + + function History(startGen) { + // Arrays of change events and selections. Doing something adds an + // event to done and clears undo. Undoing moves events from done + // to undone, redoing moves them in the other direction. + this.done = []; this.undone = [] + this.undoDepth = Infinity + // Used to track when changes can be merged into a single undo + // event + this.lastModTime = this.lastSelTime = 0 + this.lastOp = this.lastSelOp = null + this.lastOrigin = this.lastSelOrigin = null + // Used by the isClean() method + this.generation = this.maxGeneration = startGen || 1 + } + + // Create a history change event from an updateDoc-style change + // object. + function historyChangeFromChange(doc, change) { + var histChange = {from: copyPos(change.from), to: changeEnd(change), text: getBetween(doc, change.from, change.to)} + attachLocalSpans(doc, histChange, change.from.line, change.to.line + 1) + linkedDocs(doc, function (doc) { return attachLocalSpans(doc, histChange, change.from.line, change.to.line + 1); }, true) + return histChange + } + + // Pop all selection events off the end of a history array. Stop at + // a change event. + function clearSelectionEvents(array) { + while (array.length) { + var last = lst(array) + if (last.ranges) { array.pop() } + else { break } + } + } + + // Find the top change event in the history. Pop off selection + // events that are in the way. + function lastChangeEvent(hist, force) { + if (force) { + clearSelectionEvents(hist.done) + return lst(hist.done) + } else if (hist.done.length && !lst(hist.done).ranges) { + return lst(hist.done) + } else if (hist.done.length > 1 && !hist.done[hist.done.length - 2].ranges) { + hist.done.pop() + return lst(hist.done) + } + } + + // Register a change in the history. Merges changes that are within + // a single operation, or are close together with an origin that + // allows merging (starting with "+") into a single event. + function addChangeToHistory(doc, change, selAfter, opId) { + var hist = doc.history + hist.undone.length = 0 + var time = +new Date, cur + var last + + if ((hist.lastOp == opId || + hist.lastOrigin == change.origin && change.origin && + ((change.origin.charAt(0) == "+" && hist.lastModTime > time - (doc.cm ? doc.cm.options.historyEventDelay : 500)) || + change.origin.charAt(0) == "*")) && + (cur = lastChangeEvent(hist, hist.lastOp == opId))) { + // Merge this change into the last event + last = lst(cur.changes) + if (cmp(change.from, change.to) == 0 && cmp(change.from, last.to) == 0) { + // Optimized case for simple insertion -- don't want to add + // new changesets for every character typed + last.to = changeEnd(change) + } else { + // Add new sub-event + cur.changes.push(historyChangeFromChange(doc, change)) + } + } else { + // Can not be merged, start a new event. + var before = lst(hist.done) + if (!before || !before.ranges) + { pushSelectionToHistory(doc.sel, hist.done) } + cur = {changes: [historyChangeFromChange(doc, change)], + generation: hist.generation} + hist.done.push(cur) + while (hist.done.length > hist.undoDepth) { + hist.done.shift() + if (!hist.done[0].ranges) { hist.done.shift() } + } + } + hist.done.push(selAfter) + hist.generation = ++hist.maxGeneration + hist.lastModTime = hist.lastSelTime = time + hist.lastOp = hist.lastSelOp = opId + hist.lastOrigin = hist.lastSelOrigin = change.origin + + if (!last) { signal(doc, "historyAdded") } + } + + function selectionEventCanBeMerged(doc, origin, prev, sel) { + var ch = origin.charAt(0) + return ch == "*" || + ch == "+" && + prev.ranges.length == sel.ranges.length && + prev.somethingSelected() == sel.somethingSelected() && + new Date - doc.history.lastSelTime <= (doc.cm ? doc.cm.options.historyEventDelay : 500) + } + + // Called whenever the selection changes, sets the new selection as + // the pending selection in the history, and pushes the old pending + // selection into the 'done' array when it was significantly + // different (in number of selected ranges, emptiness, or time). + function addSelectionToHistory(doc, sel, opId, options) { + var hist = doc.history, origin = options && options.origin + + // A new event is started when the previous origin does not match + // the current, or the origins don't allow matching. Origins + // starting with * are always merged, those starting with + are + // merged when similar and close together in time. + if (opId == hist.lastSelOp || + (origin && hist.lastSelOrigin == origin && + (hist.lastModTime == hist.lastSelTime && hist.lastOrigin == origin || + selectionEventCanBeMerged(doc, origin, lst(hist.done), sel)))) + { hist.done[hist.done.length - 1] = sel } + else + { pushSelectionToHistory(sel, hist.done) } + + hist.lastSelTime = +new Date + hist.lastSelOrigin = origin + hist.lastSelOp = opId + if (options && options.clearRedo !== false) + { clearSelectionEvents(hist.undone) } + } + + function pushSelectionToHistory(sel, dest) { + var top = lst(dest) + if (!(top && top.ranges && top.equals(sel))) + { dest.push(sel) } + } + + // Used to store marked span information in the history. + function attachLocalSpans(doc, change, from, to) { + var existing = change["spans_" + doc.id], n = 0 + doc.iter(Math.max(doc.first, from), Math.min(doc.first + doc.size, to), function (line) { + if (line.markedSpans) + { (existing || (existing = change["spans_" + doc.id] = {}))[n] = line.markedSpans } + ++n + }) + } + + // When un/re-doing restores text containing marked spans, those + // that have been explicitly cleared should not be restored. + function removeClearedSpans(spans) { + if (!spans) { return null } + var out + for (var i = 0; i < spans.length; ++i) { + if (spans[i].marker.explicitlyCleared) { if (!out) { out = spans.slice(0, i) } } + else if (out) { out.push(spans[i]) } + } + return !out ? spans : out.length ? out : null + } + + // Retrieve and filter the old marked spans stored in a change event. + function getOldSpans(doc, change) { + var found = change["spans_" + doc.id] + if (!found) { return null } + var nw = [] + for (var i = 0; i < change.text.length; ++i) + { nw.push(removeClearedSpans(found[i])) } + return nw + } + + // Used for un/re-doing changes from the history. Combines the + // result of computing the existing spans with the set of spans that + // existed in the history (so that deleting around a span and then + // undoing brings back the span). + function mergeOldSpans(doc, change) { + var old = getOldSpans(doc, change) + var stretched = stretchSpansOverChange(doc, change) + if (!old) { return stretched } + if (!stretched) { return old } + + for (var i = 0; i < old.length; ++i) { + var oldCur = old[i], stretchCur = stretched[i] + if (oldCur && stretchCur) { + spans: for (var j = 0; j < stretchCur.length; ++j) { + var span = stretchCur[j] + for (var k = 0; k < oldCur.length; ++k) + { if (oldCur[k].marker == span.marker) { continue spans } } + oldCur.push(span) + } + } else if (stretchCur) { + old[i] = stretchCur + } + } + return old + } + + // Used both to provide a JSON-safe object in .getHistory, and, when + // detaching a document, to split the history in two + function copyHistoryArray(events, newGroup, instantiateSel) { + var copy = [] + for (var i = 0; i < events.length; ++i) { + var event = events[i] + if (event.ranges) { + copy.push(instantiateSel ? Selection.prototype.deepCopy.call(event) : event) + continue + } + var changes = event.changes, newChanges = [] + copy.push({changes: newChanges}) + for (var j = 0; j < changes.length; ++j) { + var change = changes[j], m = (void 0) + newChanges.push({from: change.from, to: change.to, text: change.text}) + if (newGroup) { for (var prop in change) { if (m = prop.match(/^spans_(\d+)$/)) { + if (indexOf(newGroup, Number(m[1])) > -1) { + lst(newChanges)[prop] = change[prop] + delete change[prop] + } + } } } + } + } + return copy + } + + // The 'scroll' parameter given to many of these indicated whether + // the new cursor position should be scrolled into view after + // modifying the selection. + + // If shift is held or the extend flag is set, extends a range to + // include a given position (and optionally a second position). + // Otherwise, simply returns the range between the given positions. + // Used for cursor motion and such. + function extendRange(range, head, other, extend) { + if (extend) { + var anchor = range.anchor + if (other) { + var posBefore = cmp(head, anchor) < 0 + if (posBefore != (cmp(other, anchor) < 0)) { + anchor = head + head = other + } else if (posBefore != (cmp(head, other) < 0)) { + head = other + } + } + return new Range(anchor, head) + } else { + return new Range(other || head, head) + } + } + + // Extend the primary selection range, discard the rest. + function extendSelection(doc, head, other, options, extend) { + if (extend == null) { extend = doc.cm && (doc.cm.display.shift || doc.extend) } + setSelection(doc, new Selection([extendRange(doc.sel.primary(), head, other, extend)], 0), options) + } + + // Extend all selections (pos is an array of selections with length + // equal the number of selections) + function extendSelections(doc, heads, options) { + var out = [] + var extend = doc.cm && (doc.cm.display.shift || doc.extend) + for (var i = 0; i < doc.sel.ranges.length; i++) + { out[i] = extendRange(doc.sel.ranges[i], heads[i], null, extend) } + var newSel = normalizeSelection(out, doc.sel.primIndex) + setSelection(doc, newSel, options) + } + + // Updates a single range in the selection. + function replaceOneSelection(doc, i, range, options) { + var ranges = doc.sel.ranges.slice(0) + ranges[i] = range + setSelection(doc, normalizeSelection(ranges, doc.sel.primIndex), options) + } + + // Reset the selection to a single range. + function setSimpleSelection(doc, anchor, head, options) { + setSelection(doc, simpleSelection(anchor, head), options) + } + + // Give beforeSelectionChange handlers a change to influence a + // selection update. + function filterSelectionChange(doc, sel, options) { + var obj = { + ranges: sel.ranges, + update: function(ranges) { + var this$1 = this; + + this.ranges = [] + for (var i = 0; i < ranges.length; i++) + { this$1.ranges[i] = new Range(clipPos(doc, ranges[i].anchor), + clipPos(doc, ranges[i].head)) } + }, + origin: options && options.origin + } + signal(doc, "beforeSelectionChange", doc, obj) + if (doc.cm) { signal(doc.cm, "beforeSelectionChange", doc.cm, obj) } + if (obj.ranges != sel.ranges) { return normalizeSelection(obj.ranges, obj.ranges.length - 1) } + else { return sel } + } + + function setSelectionReplaceHistory(doc, sel, options) { + var done = doc.history.done, last = lst(done) + if (last && last.ranges) { + done[done.length - 1] = sel + setSelectionNoUndo(doc, sel, options) + } else { + setSelection(doc, sel, options) + } + } + + // Set a new selection. + function setSelection(doc, sel, options) { + setSelectionNoUndo(doc, sel, options) + addSelectionToHistory(doc, doc.sel, doc.cm ? doc.cm.curOp.id : NaN, options) + } + + function setSelectionNoUndo(doc, sel, options) { + if (hasHandler(doc, "beforeSelectionChange") || doc.cm && hasHandler(doc.cm, "beforeSelectionChange")) + { sel = filterSelectionChange(doc, sel, options) } + + var bias = options && options.bias || + (cmp(sel.primary().head, doc.sel.primary().head) < 0 ? -1 : 1) + setSelectionInner(doc, skipAtomicInSelection(doc, sel, bias, true)) + + if (!(options && options.scroll === false) && doc.cm) + { ensureCursorVisible(doc.cm) } + } + + function setSelectionInner(doc, sel) { + if (sel.equals(doc.sel)) { return } + + doc.sel = sel + + if (doc.cm) { + doc.cm.curOp.updateInput = doc.cm.curOp.selectionChanged = true + signalCursorActivity(doc.cm) + } + signalLater(doc, "cursorActivity", doc) + } + + // Verify that the selection does not partially select any atomic + // marked ranges. + function reCheckSelection(doc) { + setSelectionInner(doc, skipAtomicInSelection(doc, doc.sel, null, false)) + } + + // Return a selection that does not partially select any atomic + // ranges. + function skipAtomicInSelection(doc, sel, bias, mayClear) { + var out + for (var i = 0; i < sel.ranges.length; i++) { + var range = sel.ranges[i] + var old = sel.ranges.length == doc.sel.ranges.length && doc.sel.ranges[i] + var newAnchor = skipAtomic(doc, range.anchor, old && old.anchor, bias, mayClear) + var newHead = skipAtomic(doc, range.head, old && old.head, bias, mayClear) + if (out || newAnchor != range.anchor || newHead != range.head) { + if (!out) { out = sel.ranges.slice(0, i) } + out[i] = new Range(newAnchor, newHead) + } + } + return out ? normalizeSelection(out, sel.primIndex) : sel + } + + function skipAtomicInner(doc, pos, oldPos, dir, mayClear) { + var line = getLine(doc, pos.line) + if (line.markedSpans) { for (var i = 0; i < line.markedSpans.length; ++i) { + var sp = line.markedSpans[i], m = sp.marker + if ((sp.from == null || (m.inclusiveLeft ? sp.from <= pos.ch : sp.from < pos.ch)) && + (sp.to == null || (m.inclusiveRight ? sp.to >= pos.ch : sp.to > pos.ch))) { + if (mayClear) { + signal(m, "beforeCursorEnter") + if (m.explicitlyCleared) { + if (!line.markedSpans) { break } + else {--i; continue} + } + } + if (!m.atomic) { continue } + + if (oldPos) { + var near = m.find(dir < 0 ? 1 : -1), diff = (void 0) + if (dir < 0 ? m.inclusiveRight : m.inclusiveLeft) + { near = movePos(doc, near, -dir, near && near.line == pos.line ? line : null) } + if (near && near.line == pos.line && (diff = cmp(near, oldPos)) && (dir < 0 ? diff < 0 : diff > 0)) + { return skipAtomicInner(doc, near, pos, dir, mayClear) } + } + + var far = m.find(dir < 0 ? -1 : 1) + if (dir < 0 ? m.inclusiveLeft : m.inclusiveRight) + { far = movePos(doc, far, dir, far.line == pos.line ? line : null) } + return far ? skipAtomicInner(doc, far, pos, dir, mayClear) : null + } + } } + return pos + } + + // Ensure a given position is not inside an atomic range. + function skipAtomic(doc, pos, oldPos, bias, mayClear) { + var dir = bias || 1 + var found = skipAtomicInner(doc, pos, oldPos, dir, mayClear) || + (!mayClear && skipAtomicInner(doc, pos, oldPos, dir, true)) || + skipAtomicInner(doc, pos, oldPos, -dir, mayClear) || + (!mayClear && skipAtomicInner(doc, pos, oldPos, -dir, true)) + if (!found) { + doc.cantEdit = true + return Pos(doc.first, 0) + } + return found + } + + function movePos(doc, pos, dir, line) { + if (dir < 0 && pos.ch == 0) { + if (pos.line > doc.first) { return clipPos(doc, Pos(pos.line - 1)) } + else { return null } + } else if (dir > 0 && pos.ch == (line || getLine(doc, pos.line)).text.length) { + if (pos.line < doc.first + doc.size - 1) { return Pos(pos.line + 1, 0) } + else { return null } + } else { + return new Pos(pos.line, pos.ch + dir) + } + } + + function selectAll(cm) { + cm.setSelection(Pos(cm.firstLine(), 0), Pos(cm.lastLine()), sel_dontScroll) + } + + // UPDATING + + // Allow "beforeChange" event handlers to influence a change + function filterChange(doc, change, update) { + var obj = { + canceled: false, + from: change.from, + to: change.to, + text: change.text, + origin: change.origin, + cancel: function () { return obj.canceled = true; } + } + if (update) { obj.update = function (from, to, text, origin) { + if (from) { obj.from = clipPos(doc, from) } + if (to) { obj.to = clipPos(doc, to) } + if (text) { obj.text = text } + if (origin !== undefined) { obj.origin = origin } + } } + signal(doc, "beforeChange", doc, obj) + if (doc.cm) { signal(doc.cm, "beforeChange", doc.cm, obj) } + + if (obj.canceled) { return null } + return {from: obj.from, to: obj.to, text: obj.text, origin: obj.origin} + } + + // Apply a change to a document, and add it to the document's + // history, and propagating it to all linked documents. + function makeChange(doc, change, ignoreReadOnly) { + if (doc.cm) { + if (!doc.cm.curOp) { return operation(doc.cm, makeChange)(doc, change, ignoreReadOnly) } + if (doc.cm.state.suppressEdits) { return } + } + + if (hasHandler(doc, "beforeChange") || doc.cm && hasHandler(doc.cm, "beforeChange")) { + change = filterChange(doc, change, true) + if (!change) { return } + } + + // Possibly split or suppress the update based on the presence + // of read-only spans in its range. + var split = sawReadOnlySpans && !ignoreReadOnly && removeReadOnlyRanges(doc, change.from, change.to) + if (split) { + for (var i = split.length - 1; i >= 0; --i) + { makeChangeInner(doc, {from: split[i].from, to: split[i].to, text: i ? [""] : change.text, origin: change.origin}) } + } else { + makeChangeInner(doc, change) + } + } + + function makeChangeInner(doc, change) { + if (change.text.length == 1 && change.text[0] == "" && cmp(change.from, change.to) == 0) { return } + var selAfter = computeSelAfterChange(doc, change) + addChangeToHistory(doc, change, selAfter, doc.cm ? doc.cm.curOp.id : NaN) + + makeChangeSingleDoc(doc, change, selAfter, stretchSpansOverChange(doc, change)) + var rebased = [] + + linkedDocs(doc, function (doc, sharedHist) { + if (!sharedHist && indexOf(rebased, doc.history) == -1) { + rebaseHist(doc.history, change) + rebased.push(doc.history) + } + makeChangeSingleDoc(doc, change, null, stretchSpansOverChange(doc, change)) + }) + } + + // Revert a change stored in a document's history. + function makeChangeFromHistory(doc, type, allowSelectionOnly) { + var suppress = doc.cm && doc.cm.state.suppressEdits + if (suppress && !allowSelectionOnly) { return } + + var hist = doc.history, event, selAfter = doc.sel + var source = type == "undo" ? hist.done : hist.undone, dest = type == "undo" ? hist.undone : hist.done + + // Verify that there is a useable event (so that ctrl-z won't + // needlessly clear selection events) + var i = 0 + for (; i < source.length; i++) { + event = source[i] + if (allowSelectionOnly ? event.ranges && !event.equals(doc.sel) : !event.ranges) + { break } + } + if (i == source.length) { return } + hist.lastOrigin = hist.lastSelOrigin = null + + for (;;) { + event = source.pop() + if (event.ranges) { + pushSelectionToHistory(event, dest) + if (allowSelectionOnly && !event.equals(doc.sel)) { + setSelection(doc, event, {clearRedo: false}) + return + } + selAfter = event + } else if (suppress) { + source.push(event) + return + } else { break } + } + + // Build up a reverse change object to add to the opposite history + // stack (redo when undoing, and vice versa). + var antiChanges = [] + pushSelectionToHistory(selAfter, dest) + dest.push({changes: antiChanges, generation: hist.generation}) + hist.generation = event.generation || ++hist.maxGeneration + + var filter = hasHandler(doc, "beforeChange") || doc.cm && hasHandler(doc.cm, "beforeChange") + + var loop = function ( i ) { + var change = event.changes[i] + change.origin = type + if (filter && !filterChange(doc, change, false)) { + source.length = 0 + return {} + } + + antiChanges.push(historyChangeFromChange(doc, change)) + + var after = i ? computeSelAfterChange(doc, change) : lst(source) + makeChangeSingleDoc(doc, change, after, mergeOldSpans(doc, change)) + if (!i && doc.cm) { doc.cm.scrollIntoView({from: change.from, to: changeEnd(change)}) } + var rebased = [] + + // Propagate to the linked documents + linkedDocs(doc, function (doc, sharedHist) { + if (!sharedHist && indexOf(rebased, doc.history) == -1) { + rebaseHist(doc.history, change) + rebased.push(doc.history) + } + makeChangeSingleDoc(doc, change, null, mergeOldSpans(doc, change)) + }) + }; + + for (var i$1 = event.changes.length - 1; i$1 >= 0; --i$1) { + var returned = loop( i$1 ); + + if ( returned ) return returned.v; + } + } + + // Sub-views need their line numbers shifted when text is added + // above or below them in the parent document. + function shiftDoc(doc, distance) { + if (distance == 0) { return } + doc.first += distance + doc.sel = new Selection(map(doc.sel.ranges, function (range) { return new Range( + Pos(range.anchor.line + distance, range.anchor.ch), + Pos(range.head.line + distance, range.head.ch) + ); }), doc.sel.primIndex) + if (doc.cm) { + regChange(doc.cm, doc.first, doc.first - distance, distance) + for (var d = doc.cm.display, l = d.viewFrom; l < d.viewTo; l++) + { regLineChange(doc.cm, l, "gutter") } + } + } + + // More lower-level change function, handling only a single document + // (not linked ones). + function makeChangeSingleDoc(doc, change, selAfter, spans) { + if (doc.cm && !doc.cm.curOp) + { return operation(doc.cm, makeChangeSingleDoc)(doc, change, selAfter, spans) } + + if (change.to.line < doc.first) { + shiftDoc(doc, change.text.length - 1 - (change.to.line - change.from.line)) + return + } + if (change.from.line > doc.lastLine()) { return } + + // Clip the change to the size of this doc + if (change.from.line < doc.first) { + var shift = change.text.length - 1 - (doc.first - change.from.line) + shiftDoc(doc, shift) + change = {from: Pos(doc.first, 0), to: Pos(change.to.line + shift, change.to.ch), + text: [lst(change.text)], origin: change.origin} + } + var last = doc.lastLine() + if (change.to.line > last) { + change = {from: change.from, to: Pos(last, getLine(doc, last).text.length), + text: [change.text[0]], origin: change.origin} + } + + change.removed = getBetween(doc, change.from, change.to) + + if (!selAfter) { selAfter = computeSelAfterChange(doc, change) } + if (doc.cm) { makeChangeSingleDocInEditor(doc.cm, change, spans) } + else { updateDoc(doc, change, spans) } + setSelectionNoUndo(doc, selAfter, sel_dontScroll) + } + + // Handle the interaction of a change to a document with the editor + // that this document is part of. + function makeChangeSingleDocInEditor(cm, change, spans) { + var doc = cm.doc, display = cm.display, from = change.from, to = change.to + + var recomputeMaxLength = false, checkWidthStart = from.line + if (!cm.options.lineWrapping) { + checkWidthStart = lineNo(visualLine(getLine(doc, from.line))) + doc.iter(checkWidthStart, to.line + 1, function (line) { + if (line == display.maxLine) { + recomputeMaxLength = true + return true + } + }) + } + + if (doc.sel.contains(change.from, change.to) > -1) + { signalCursorActivity(cm) } + + updateDoc(doc, change, spans, estimateHeight(cm)) + + if (!cm.options.lineWrapping) { + doc.iter(checkWidthStart, from.line + change.text.length, function (line) { + var len = lineLength(line) + if (len > display.maxLineLength) { + display.maxLine = line + display.maxLineLength = len + display.maxLineChanged = true + recomputeMaxLength = false + } + }) + if (recomputeMaxLength) { cm.curOp.updateMaxLine = true } + } + + retreatFrontier(doc, from.line) + startWorker(cm, 400) + + var lendiff = change.text.length - (to.line - from.line) - 1 + // Remember that these lines changed, for updating the display + if (change.full) + { regChange(cm) } + else if (from.line == to.line && change.text.length == 1 && !isWholeLineUpdate(cm.doc, change)) + { regLineChange(cm, from.line, "text") } + else + { regChange(cm, from.line, to.line + 1, lendiff) } + + var changesHandler = hasHandler(cm, "changes"), changeHandler = hasHandler(cm, "change") + if (changeHandler || changesHandler) { + var obj = { + from: from, to: to, + text: change.text, + removed: change.removed, + origin: change.origin + } + if (changeHandler) { signalLater(cm, "change", cm, obj) } + if (changesHandler) { (cm.curOp.changeObjs || (cm.curOp.changeObjs = [])).push(obj) } + } + cm.display.selForContextMenu = null + } + + function replaceRange(doc, code, from, to, origin) { + if (!to) { to = from } + if (cmp(to, from) < 0) { var assign; + (assign = [to, from], from = assign[0], to = assign[1], assign) } + if (typeof code == "string") { code = doc.splitLines(code) } + makeChange(doc, {from: from, to: to, text: code, origin: origin}) + } + + // Rebasing/resetting history to deal with externally-sourced changes + + function rebaseHistSelSingle(pos, from, to, diff) { + if (to < pos.line) { + pos.line += diff + } else if (from < pos.line) { + pos.line = from + pos.ch = 0 + } + } + + // Tries to rebase an array of history events given a change in the + // document. If the change touches the same lines as the event, the + // event, and everything 'behind' it, is discarded. If the change is + // before the event, the event's positions are updated. Uses a + // copy-on-write scheme for the positions, to avoid having to + // reallocate them all on every rebase, but also avoid problems with + // shared position objects being unsafely updated. + function rebaseHistArray(array, from, to, diff) { + for (var i = 0; i < array.length; ++i) { + var sub = array[i], ok = true + if (sub.ranges) { + if (!sub.copied) { sub = array[i] = sub.deepCopy(); sub.copied = true } + for (var j = 0; j < sub.ranges.length; j++) { + rebaseHistSelSingle(sub.ranges[j].anchor, from, to, diff) + rebaseHistSelSingle(sub.ranges[j].head, from, to, diff) + } + continue + } + for (var j$1 = 0; j$1 < sub.changes.length; ++j$1) { + var cur = sub.changes[j$1] + if (to < cur.from.line) { + cur.from = Pos(cur.from.line + diff, cur.from.ch) + cur.to = Pos(cur.to.line + diff, cur.to.ch) + } else if (from <= cur.to.line) { + ok = false + break + } + } + if (!ok) { + array.splice(0, i + 1) + i = 0 + } + } + } + + function rebaseHist(hist, change) { + var from = change.from.line, to = change.to.line, diff = change.text.length - (to - from) - 1 + rebaseHistArray(hist.done, from, to, diff) + rebaseHistArray(hist.undone, from, to, diff) + } + + // Utility for applying a change to a line by handle or number, + // returning the number and optionally registering the line as + // changed. + function changeLine(doc, handle, changeType, op) { + var no = handle, line = handle + if (typeof handle == "number") { line = getLine(doc, clipLine(doc, handle)) } + else { no = lineNo(handle) } + if (no == null) { return null } + if (op(line, no) && doc.cm) { regLineChange(doc.cm, no, changeType) } + return line + } + + // The document is represented as a BTree consisting of leaves, with + // chunk of lines in them, and branches, with up to ten leaves or + // other branch nodes below them. The top node is always a branch + // node, and is the document object itself (meaning it has + // additional methods and properties). + // + // All nodes have parent links. The tree is used both to go from + // line numbers to line objects, and to go from objects to numbers. + // It also indexes by height, and is used to convert between height + // and line object, and to find the total height of the document. + // + // See also http://marijnhaverbeke.nl/blog/codemirror-line-tree.html + + function LeafChunk(lines) { + var this$1 = this; + + this.lines = lines + this.parent = null + var height = 0 + for (var i = 0; i < lines.length; ++i) { + lines[i].parent = this$1 + height += lines[i].height + } + this.height = height + } + + LeafChunk.prototype = { + chunkSize: function chunkSize() { return this.lines.length }, + + // Remove the n lines at offset 'at'. + removeInner: function removeInner(at, n) { + var this$1 = this; + + for (var i = at, e = at + n; i < e; ++i) { + var line = this$1.lines[i] + this$1.height -= line.height + cleanUpLine(line) + signalLater(line, "delete") + } + this.lines.splice(at, n) + }, + + // Helper used to collapse a small branch into a single leaf. + collapse: function collapse(lines) { + lines.push.apply(lines, this.lines) + }, + + // Insert the given array of lines at offset 'at', count them as + // having the given height. + insertInner: function insertInner(at, lines, height) { + var this$1 = this; + + this.height += height + this.lines = this.lines.slice(0, at).concat(lines).concat(this.lines.slice(at)) + for (var i = 0; i < lines.length; ++i) { lines[i].parent = this$1 } + }, + + // Used to iterate over a part of the tree. + iterN: function iterN(at, n, op) { + var this$1 = this; + + for (var e = at + n; at < e; ++at) + { if (op(this$1.lines[at])) { return true } } + } + } + + function BranchChunk(children) { + var this$1 = this; + + this.children = children + var size = 0, height = 0 + for (var i = 0; i < children.length; ++i) { + var ch = children[i] + size += ch.chunkSize(); height += ch.height + ch.parent = this$1 + } + this.size = size + this.height = height + this.parent = null + } + + BranchChunk.prototype = { + chunkSize: function chunkSize() { return this.size }, + + removeInner: function removeInner(at, n) { + var this$1 = this; + + this.size -= n + for (var i = 0; i < this.children.length; ++i) { + var child = this$1.children[i], sz = child.chunkSize() + if (at < sz) { + var rm = Math.min(n, sz - at), oldHeight = child.height + child.removeInner(at, rm) + this$1.height -= oldHeight - child.height + if (sz == rm) { this$1.children.splice(i--, 1); child.parent = null } + if ((n -= rm) == 0) { break } + at = 0 + } else { at -= sz } + } + // If the result is smaller than 25 lines, ensure that it is a + // single leaf node. + if (this.size - n < 25 && + (this.children.length > 1 || !(this.children[0] instanceof LeafChunk))) { + var lines = [] + this.collapse(lines) + this.children = [new LeafChunk(lines)] + this.children[0].parent = this + } + }, + + collapse: function collapse(lines) { + var this$1 = this; + + for (var i = 0; i < this.children.length; ++i) { this$1.children[i].collapse(lines) } + }, + + insertInner: function insertInner(at, lines, height) { + var this$1 = this; + + this.size += lines.length + this.height += height + for (var i = 0; i < this.children.length; ++i) { + var child = this$1.children[i], sz = child.chunkSize() + if (at <= sz) { + child.insertInner(at, lines, height) + if (child.lines && child.lines.length > 50) { + // To avoid memory thrashing when child.lines is huge (e.g. first view of a large file), it's never spliced. + // Instead, small slices are taken. They're taken in order because sequential memory accesses are fastest. + var remaining = child.lines.length % 25 + 25 + for (var pos = remaining; pos < child.lines.length;) { + var leaf = new LeafChunk(child.lines.slice(pos, pos += 25)) + child.height -= leaf.height + this$1.children.splice(++i, 0, leaf) + leaf.parent = this$1 + } + child.lines = child.lines.slice(0, remaining) + this$1.maybeSpill() + } + break + } + at -= sz + } + }, + + // When a node has grown, check whether it should be split. + maybeSpill: function maybeSpill() { + if (this.children.length <= 10) { return } + var me = this + do { + var spilled = me.children.splice(me.children.length - 5, 5) + var sibling = new BranchChunk(spilled) + if (!me.parent) { // Become the parent node + var copy = new BranchChunk(me.children) + copy.parent = me + me.children = [copy, sibling] + me = copy + } else { + me.size -= sibling.size + me.height -= sibling.height + var myIndex = indexOf(me.parent.children, me) + me.parent.children.splice(myIndex + 1, 0, sibling) + } + sibling.parent = me.parent + } while (me.children.length > 10) + me.parent.maybeSpill() + }, + + iterN: function iterN(at, n, op) { + var this$1 = this; + + for (var i = 0; i < this.children.length; ++i) { + var child = this$1.children[i], sz = child.chunkSize() + if (at < sz) { + var used = Math.min(n, sz - at) + if (child.iterN(at, used, op)) { return true } + if ((n -= used) == 0) { break } + at = 0 + } else { at -= sz } + } + } + } + + // Line widgets are block elements displayed above or below a line. + + var LineWidget = function(doc, node, options) { + var this$1 = this; + + if (options) { for (var opt in options) { if (options.hasOwnProperty(opt)) + { this$1[opt] = options[opt] } } } + this.doc = doc + this.node = node + }; + + LineWidget.prototype.clear = function () { + var this$1 = this; + + var cm = this.doc.cm, ws = this.line.widgets, line = this.line, no = lineNo(line) + if (no == null || !ws) { return } + for (var i = 0; i < ws.length; ++i) { if (ws[i] == this$1) { ws.splice(i--, 1) } } + if (!ws.length) { line.widgets = null } + var height = widgetHeight(this) + updateLineHeight(line, Math.max(0, line.height - height)) + if (cm) { + runInOp(cm, function () { + adjustScrollWhenAboveVisible(cm, line, -height) + regLineChange(cm, no, "widget") + }) + signalLater(cm, "lineWidgetCleared", cm, this, no) + } + }; + + LineWidget.prototype.changed = function () { + var this$1 = this; + + var oldH = this.height, cm = this.doc.cm, line = this.line + this.height = null + var diff = widgetHeight(this) - oldH + if (!diff) { return } + updateLineHeight(line, line.height + diff) + if (cm) { + runInOp(cm, function () { + cm.curOp.forceUpdate = true + adjustScrollWhenAboveVisible(cm, line, diff) + signalLater(cm, "lineWidgetChanged", cm, this$1, lineNo(line)) + }) + } + }; + eventMixin(LineWidget) + + function adjustScrollWhenAboveVisible(cm, line, diff) { + if (heightAtLine(line) < ((cm.curOp && cm.curOp.scrollTop) || cm.doc.scrollTop)) + { addToScrollTop(cm, diff) } + } + + function addLineWidget(doc, handle, node, options) { + var widget = new LineWidget(doc, node, options) + var cm = doc.cm + if (cm && widget.noHScroll) { cm.display.alignWidgets = true } + changeLine(doc, handle, "widget", function (line) { + var widgets = line.widgets || (line.widgets = []) + if (widget.insertAt == null) { widgets.push(widget) } + else { widgets.splice(Math.min(widgets.length - 1, Math.max(0, widget.insertAt)), 0, widget) } + widget.line = line + if (cm && !lineIsHidden(doc, line)) { + var aboveVisible = heightAtLine(line) < doc.scrollTop + updateLineHeight(line, line.height + widgetHeight(widget)) + if (aboveVisible) { addToScrollTop(cm, widget.height) } + cm.curOp.forceUpdate = true + } + return true + }) + if (cm) { signalLater(cm, "lineWidgetAdded", cm, widget, typeof handle == "number" ? handle : lineNo(handle)) } + return widget + } + + // TEXTMARKERS + + // Created with markText and setBookmark methods. A TextMarker is a + // handle that can be used to clear or find a marked position in the + // document. Line objects hold arrays (markedSpans) containing + // {from, to, marker} object pointing to such marker objects, and + // indicating that such a marker is present on that line. Multiple + // lines may point to the same marker when it spans across lines. + // The spans will have null for their from/to properties when the + // marker continues beyond the start/end of the line. Markers have + // links back to the lines they currently touch. + + // Collapsed markers have unique ids, in order to be able to order + // them, which is needed for uniquely determining an outer marker + // when they overlap (they may nest, but not partially overlap). + var nextMarkerId = 0 + + var TextMarker = function(doc, type) { + this.lines = [] + this.type = type + this.doc = doc + this.id = ++nextMarkerId + }; + + // Clear the marker. + TextMarker.prototype.clear = function () { + var this$1 = this; + + if (this.explicitlyCleared) { return } + var cm = this.doc.cm, withOp = cm && !cm.curOp + if (withOp) { startOperation(cm) } + if (hasHandler(this, "clear")) { + var found = this.find() + if (found) { signalLater(this, "clear", found.from, found.to) } + } + var min = null, max = null + for (var i = 0; i < this.lines.length; ++i) { + var line = this$1.lines[i] + var span = getMarkedSpanFor(line.markedSpans, this$1) + if (cm && !this$1.collapsed) { regLineChange(cm, lineNo(line), "text") } + else if (cm) { + if (span.to != null) { max = lineNo(line) } + if (span.from != null) { min = lineNo(line) } + } + line.markedSpans = removeMarkedSpan(line.markedSpans, span) + if (span.from == null && this$1.collapsed && !lineIsHidden(this$1.doc, line) && cm) + { updateLineHeight(line, textHeight(cm.display)) } + } + if (cm && this.collapsed && !cm.options.lineWrapping) { for (var i$1 = 0; i$1 < this.lines.length; ++i$1) { + var visual = visualLine(this$1.lines[i$1]), len = lineLength(visual) + if (len > cm.display.maxLineLength) { + cm.display.maxLine = visual + cm.display.maxLineLength = len + cm.display.maxLineChanged = true + } + } } + + if (min != null && cm && this.collapsed) { regChange(cm, min, max + 1) } + this.lines.length = 0 + this.explicitlyCleared = true + if (this.atomic && this.doc.cantEdit) { + this.doc.cantEdit = false + if (cm) { reCheckSelection(cm.doc) } + } + if (cm) { signalLater(cm, "markerCleared", cm, this, min, max) } + if (withOp) { endOperation(cm) } + if (this.parent) { this.parent.clear() } + }; + + // Find the position of the marker in the document. Returns a {from, + // to} object by default. Side can be passed to get a specific side + // -- 0 (both), -1 (left), or 1 (right). When lineObj is true, the + // Pos objects returned contain a line object, rather than a line + // number (used to prevent looking up the same line twice). + TextMarker.prototype.find = function (side, lineObj) { + var this$1 = this; + + if (side == null && this.type == "bookmark") { side = 1 } + var from, to + for (var i = 0; i < this.lines.length; ++i) { + var line = this$1.lines[i] + var span = getMarkedSpanFor(line.markedSpans, this$1) + if (span.from != null) { + from = Pos(lineObj ? line : lineNo(line), span.from) + if (side == -1) { return from } + } + if (span.to != null) { + to = Pos(lineObj ? line : lineNo(line), span.to) + if (side == 1) { return to } + } + } + return from && {from: from, to: to} + }; + + // Signals that the marker's widget changed, and surrounding layout + // should be recomputed. + TextMarker.prototype.changed = function () { + var this$1 = this; + + var pos = this.find(-1, true), widget = this, cm = this.doc.cm + if (!pos || !cm) { return } + runInOp(cm, function () { + var line = pos.line, lineN = lineNo(pos.line) + var view = findViewForLine(cm, lineN) + if (view) { + clearLineMeasurementCacheFor(view) + cm.curOp.selectionChanged = cm.curOp.forceUpdate = true + } + cm.curOp.updateMaxLine = true + if (!lineIsHidden(widget.doc, line) && widget.height != null) { + var oldHeight = widget.height + widget.height = null + var dHeight = widgetHeight(widget) - oldHeight + if (dHeight) + { updateLineHeight(line, line.height + dHeight) } + } + signalLater(cm, "markerChanged", cm, this$1) + }) + }; + + TextMarker.prototype.attachLine = function (line) { + if (!this.lines.length && this.doc.cm) { + var op = this.doc.cm.curOp + if (!op.maybeHiddenMarkers || indexOf(op.maybeHiddenMarkers, this) == -1) + { (op.maybeUnhiddenMarkers || (op.maybeUnhiddenMarkers = [])).push(this) } + } + this.lines.push(line) + }; + + TextMarker.prototype.detachLine = function (line) { + this.lines.splice(indexOf(this.lines, line), 1) + if (!this.lines.length && this.doc.cm) { + var op = this.doc.cm.curOp + ;(op.maybeHiddenMarkers || (op.maybeHiddenMarkers = [])).push(this) + } + }; + eventMixin(TextMarker) + + // Create a marker, wire it up to the right lines, and + function markText(doc, from, to, options, type) { + // Shared markers (across linked documents) are handled separately + // (markTextShared will call out to this again, once per + // document). + if (options && options.shared) { return markTextShared(doc, from, to, options, type) } + // Ensure we are in an operation. + if (doc.cm && !doc.cm.curOp) { return operation(doc.cm, markText)(doc, from, to, options, type) } + + var marker = new TextMarker(doc, type), diff = cmp(from, to) + if (options) { copyObj(options, marker, false) } + // Don't connect empty markers unless clearWhenEmpty is false + if (diff > 0 || diff == 0 && marker.clearWhenEmpty !== false) + { return marker } + if (marker.replacedWith) { + // Showing up as a widget implies collapsed (widget replaces text) + marker.collapsed = true + marker.widgetNode = eltP("span", [marker.replacedWith], "CodeMirror-widget") + if (!options.handleMouseEvents) { marker.widgetNode.setAttribute("cm-ignore-events", "true") } + if (options.insertLeft) { marker.widgetNode.insertLeft = true } + } + if (marker.collapsed) { + if (conflictingCollapsedRange(doc, from.line, from, to, marker) || + from.line != to.line && conflictingCollapsedRange(doc, to.line, from, to, marker)) + { throw new Error("Inserting collapsed marker partially overlapping an existing one") } + seeCollapsedSpans() + } + + if (marker.addToHistory) + { addChangeToHistory(doc, {from: from, to: to, origin: "markText"}, doc.sel, NaN) } + + var curLine = from.line, cm = doc.cm, updateMaxLine + doc.iter(curLine, to.line + 1, function (line) { + if (cm && marker.collapsed && !cm.options.lineWrapping && visualLine(line) == cm.display.maxLine) + { updateMaxLine = true } + if (marker.collapsed && curLine != from.line) { updateLineHeight(line, 0) } + addMarkedSpan(line, new MarkedSpan(marker, + curLine == from.line ? from.ch : null, + curLine == to.line ? to.ch : null)) + ++curLine + }) + // lineIsHidden depends on the presence of the spans, so needs a second pass + if (marker.collapsed) { doc.iter(from.line, to.line + 1, function (line) { + if (lineIsHidden(doc, line)) { updateLineHeight(line, 0) } + }) } + + if (marker.clearOnEnter) { on(marker, "beforeCursorEnter", function () { return marker.clear(); }) } + + if (marker.readOnly) { + seeReadOnlySpans() + if (doc.history.done.length || doc.history.undone.length) + { doc.clearHistory() } + } + if (marker.collapsed) { + marker.id = ++nextMarkerId + marker.atomic = true + } + if (cm) { + // Sync editor state + if (updateMaxLine) { cm.curOp.updateMaxLine = true } + if (marker.collapsed) + { regChange(cm, from.line, to.line + 1) } + else if (marker.className || marker.title || marker.startStyle || marker.endStyle || marker.css) + { for (var i = from.line; i <= to.line; i++) { regLineChange(cm, i, "text") } } + if (marker.atomic) { reCheckSelection(cm.doc) } + signalLater(cm, "markerAdded", cm, marker) + } + return marker + } + + // SHARED TEXTMARKERS + + // A shared marker spans multiple linked documents. It is + // implemented as a meta-marker-object controlling multiple normal + // markers. + var SharedTextMarker = function(markers, primary) { + var this$1 = this; + + this.markers = markers + this.primary = primary + for (var i = 0; i < markers.length; ++i) + { markers[i].parent = this$1 } + }; + + SharedTextMarker.prototype.clear = function () { + var this$1 = this; + + if (this.explicitlyCleared) { return } + this.explicitlyCleared = true + for (var i = 0; i < this.markers.length; ++i) + { this$1.markers[i].clear() } + signalLater(this, "clear") + }; + + SharedTextMarker.prototype.find = function (side, lineObj) { + return this.primary.find(side, lineObj) + }; + eventMixin(SharedTextMarker) + + function markTextShared(doc, from, to, options, type) { + options = copyObj(options) + options.shared = false + var markers = [markText(doc, from, to, options, type)], primary = markers[0] + var widget = options.widgetNode + linkedDocs(doc, function (doc) { + if (widget) { options.widgetNode = widget.cloneNode(true) } + markers.push(markText(doc, clipPos(doc, from), clipPos(doc, to), options, type)) + for (var i = 0; i < doc.linked.length; ++i) + { if (doc.linked[i].isParent) { return } } + primary = lst(markers) + }) + return new SharedTextMarker(markers, primary) + } + + function findSharedMarkers(doc) { + return doc.findMarks(Pos(doc.first, 0), doc.clipPos(Pos(doc.lastLine())), function (m) { return m.parent; }) + } + + function copySharedMarkers(doc, markers) { + for (var i = 0; i < markers.length; i++) { + var marker = markers[i], pos = marker.find() + var mFrom = doc.clipPos(pos.from), mTo = doc.clipPos(pos.to) + if (cmp(mFrom, mTo)) { + var subMark = markText(doc, mFrom, mTo, marker.primary, marker.primary.type) + marker.markers.push(subMark) + subMark.parent = marker + } + } + } + + function detachSharedMarkers(markers) { + var loop = function ( i ) { + var marker = markers[i], linked = [marker.primary.doc] + linkedDocs(marker.primary.doc, function (d) { return linked.push(d); }) + for (var j = 0; j < marker.markers.length; j++) { + var subMarker = marker.markers[j] + if (indexOf(linked, subMarker.doc) == -1) { + subMarker.parent = null + marker.markers.splice(j--, 1) + } + } + }; + + for (var i = 0; i < markers.length; i++) loop( i ); + } + + var nextDocId = 0 + var Doc = function(text, mode, firstLine, lineSep, direction) { + if (!(this instanceof Doc)) { return new Doc(text, mode, firstLine, lineSep, direction) } + if (firstLine == null) { firstLine = 0 } + + BranchChunk.call(this, [new LeafChunk([new Line("", null)])]) + this.first = firstLine + this.scrollTop = this.scrollLeft = 0 + this.cantEdit = false + this.cleanGeneration = 1 + this.modeFrontier = this.highlightFrontier = firstLine + var start = Pos(firstLine, 0) + this.sel = simpleSelection(start) + this.history = new History(null) + this.id = ++nextDocId + this.modeOption = mode + this.lineSep = lineSep + this.direction = (direction == "rtl") ? "rtl" : "ltr" + this.extend = false + + if (typeof text == "string") { text = this.splitLines(text) } + updateDoc(this, {from: start, to: start, text: text}) + setSelection(this, simpleSelection(start), sel_dontScroll) + } + + Doc.prototype = createObj(BranchChunk.prototype, { + constructor: Doc, + // Iterate over the document. Supports two forms -- with only one + // argument, it calls that for each line in the document. With + // three, it iterates over the range given by the first two (with + // the second being non-inclusive). + iter: function(from, to, op) { + if (op) { this.iterN(from - this.first, to - from, op) } + else { this.iterN(this.first, this.first + this.size, from) } + }, + + // Non-public interface for adding and removing lines. + insert: function(at, lines) { + var height = 0 + for (var i = 0; i < lines.length; ++i) { height += lines[i].height } + this.insertInner(at - this.first, lines, height) + }, + remove: function(at, n) { this.removeInner(at - this.first, n) }, + + // From here, the methods are part of the public interface. Most + // are also available from CodeMirror (editor) instances. + + getValue: function(lineSep) { + var lines = getLines(this, this.first, this.first + this.size) + if (lineSep === false) { return lines } + return lines.join(lineSep || this.lineSeparator()) + }, + setValue: docMethodOp(function(code) { + var top = Pos(this.first, 0), last = this.first + this.size - 1 + makeChange(this, {from: top, to: Pos(last, getLine(this, last).text.length), + text: this.splitLines(code), origin: "setValue", full: true}, true) + if (this.cm) { scrollToCoords(this.cm, 0, 0) } + setSelection(this, simpleSelection(top), sel_dontScroll) + }), + replaceRange: function(code, from, to, origin) { + from = clipPos(this, from) + to = to ? clipPos(this, to) : from + replaceRange(this, code, from, to, origin) + }, + getRange: function(from, to, lineSep) { + var lines = getBetween(this, clipPos(this, from), clipPos(this, to)) + if (lineSep === false) { return lines } + return lines.join(lineSep || this.lineSeparator()) + }, + + getLine: function(line) {var l = this.getLineHandle(line); return l && l.text}, + + getLineHandle: function(line) {if (isLine(this, line)) { return getLine(this, line) }}, + getLineNumber: function(line) {return lineNo(line)}, + + getLineHandleVisualStart: function(line) { + if (typeof line == "number") { line = getLine(this, line) } + return visualLine(line) + }, + + lineCount: function() {return this.size}, + firstLine: function() {return this.first}, + lastLine: function() {return this.first + this.size - 1}, + + clipPos: function(pos) {return clipPos(this, pos)}, + + getCursor: function(start) { + var range = this.sel.primary(), pos + if (start == null || start == "head") { pos = range.head } + else if (start == "anchor") { pos = range.anchor } + else if (start == "end" || start == "to" || start === false) { pos = range.to() } + else { pos = range.from() } + return pos + }, + listSelections: function() { return this.sel.ranges }, + somethingSelected: function() {return this.sel.somethingSelected()}, + + setCursor: docMethodOp(function(line, ch, options) { + setSimpleSelection(this, clipPos(this, typeof line == "number" ? Pos(line, ch || 0) : line), null, options) + }), + setSelection: docMethodOp(function(anchor, head, options) { + setSimpleSelection(this, clipPos(this, anchor), clipPos(this, head || anchor), options) + }), + extendSelection: docMethodOp(function(head, other, options) { + extendSelection(this, clipPos(this, head), other && clipPos(this, other), options) + }), + extendSelections: docMethodOp(function(heads, options) { + extendSelections(this, clipPosArray(this, heads), options) + }), + extendSelectionsBy: docMethodOp(function(f, options) { + var heads = map(this.sel.ranges, f) + extendSelections(this, clipPosArray(this, heads), options) + }), + setSelections: docMethodOp(function(ranges, primary, options) { + var this$1 = this; + + if (!ranges.length) { return } + var out = [] + for (var i = 0; i < ranges.length; i++) + { out[i] = new Range(clipPos(this$1, ranges[i].anchor), + clipPos(this$1, ranges[i].head)) } + if (primary == null) { primary = Math.min(ranges.length - 1, this.sel.primIndex) } + setSelection(this, normalizeSelection(out, primary), options) + }), + addSelection: docMethodOp(function(anchor, head, options) { + var ranges = this.sel.ranges.slice(0) + ranges.push(new Range(clipPos(this, anchor), clipPos(this, head || anchor))) + setSelection(this, normalizeSelection(ranges, ranges.length - 1), options) + }), + + getSelection: function(lineSep) { + var this$1 = this; + + var ranges = this.sel.ranges, lines + for (var i = 0; i < ranges.length; i++) { + var sel = getBetween(this$1, ranges[i].from(), ranges[i].to()) + lines = lines ? lines.concat(sel) : sel + } + if (lineSep === false) { return lines } + else { return lines.join(lineSep || this.lineSeparator()) } + }, + getSelections: function(lineSep) { + var this$1 = this; + + var parts = [], ranges = this.sel.ranges + for (var i = 0; i < ranges.length; i++) { + var sel = getBetween(this$1, ranges[i].from(), ranges[i].to()) + if (lineSep !== false) { sel = sel.join(lineSep || this$1.lineSeparator()) } + parts[i] = sel + } + return parts + }, + replaceSelection: function(code, collapse, origin) { + var dup = [] + for (var i = 0; i < this.sel.ranges.length; i++) + { dup[i] = code } + this.replaceSelections(dup, collapse, origin || "+input") + }, + replaceSelections: docMethodOp(function(code, collapse, origin) { + var this$1 = this; + + var changes = [], sel = this.sel + for (var i = 0; i < sel.ranges.length; i++) { + var range = sel.ranges[i] + changes[i] = {from: range.from(), to: range.to(), text: this$1.splitLines(code[i]), origin: origin} + } + var newSel = collapse && collapse != "end" && computeReplacedSel(this, changes, collapse) + for (var i$1 = changes.length - 1; i$1 >= 0; i$1--) + { makeChange(this$1, changes[i$1]) } + if (newSel) { setSelectionReplaceHistory(this, newSel) } + else if (this.cm) { ensureCursorVisible(this.cm) } + }), + undo: docMethodOp(function() {makeChangeFromHistory(this, "undo")}), + redo: docMethodOp(function() {makeChangeFromHistory(this, "redo")}), + undoSelection: docMethodOp(function() {makeChangeFromHistory(this, "undo", true)}), + redoSelection: docMethodOp(function() {makeChangeFromHistory(this, "redo", true)}), + + setExtending: function(val) {this.extend = val}, + getExtending: function() {return this.extend}, + + historySize: function() { + var hist = this.history, done = 0, undone = 0 + for (var i = 0; i < hist.done.length; i++) { if (!hist.done[i].ranges) { ++done } } + for (var i$1 = 0; i$1 < hist.undone.length; i$1++) { if (!hist.undone[i$1].ranges) { ++undone } } + return {undo: done, redo: undone} + }, + clearHistory: function() {this.history = new History(this.history.maxGeneration)}, + + markClean: function() { + this.cleanGeneration = this.changeGeneration(true) + }, + changeGeneration: function(forceSplit) { + if (forceSplit) + { this.history.lastOp = this.history.lastSelOp = this.history.lastOrigin = null } + return this.history.generation + }, + isClean: function (gen) { + return this.history.generation == (gen || this.cleanGeneration) + }, + + getHistory: function() { + return {done: copyHistoryArray(this.history.done), + undone: copyHistoryArray(this.history.undone)} + }, + setHistory: function(histData) { + var hist = this.history = new History(this.history.maxGeneration) + hist.done = copyHistoryArray(histData.done.slice(0), null, true) + hist.undone = copyHistoryArray(histData.undone.slice(0), null, true) + }, + + setGutterMarker: docMethodOp(function(line, gutterID, value) { + return changeLine(this, line, "gutter", function (line) { + var markers = line.gutterMarkers || (line.gutterMarkers = {}) + markers[gutterID] = value + if (!value && isEmpty(markers)) { line.gutterMarkers = null } + return true + }) + }), + + clearGutter: docMethodOp(function(gutterID) { + var this$1 = this; + + this.iter(function (line) { + if (line.gutterMarkers && line.gutterMarkers[gutterID]) { + changeLine(this$1, line, "gutter", function () { + line.gutterMarkers[gutterID] = null + if (isEmpty(line.gutterMarkers)) { line.gutterMarkers = null } + return true + }) + } + }) + }), + + lineInfo: function(line) { + var n + if (typeof line == "number") { + if (!isLine(this, line)) { return null } + n = line + line = getLine(this, line) + if (!line) { return null } + } else { + n = lineNo(line) + if (n == null) { return null } + } + return {line: n, handle: line, text: line.text, gutterMarkers: line.gutterMarkers, + textClass: line.textClass, bgClass: line.bgClass, wrapClass: line.wrapClass, + widgets: line.widgets} + }, + + addLineClass: docMethodOp(function(handle, where, cls) { + return changeLine(this, handle, where == "gutter" ? "gutter" : "class", function (line) { + var prop = where == "text" ? "textClass" + : where == "background" ? "bgClass" + : where == "gutter" ? "gutterClass" : "wrapClass" + if (!line[prop]) { line[prop] = cls } + else if (classTest(cls).test(line[prop])) { return false } + else { line[prop] += " " + cls } + return true + }) + }), + removeLineClass: docMethodOp(function(handle, where, cls) { + return changeLine(this, handle, where == "gutter" ? "gutter" : "class", function (line) { + var prop = where == "text" ? "textClass" + : where == "background" ? "bgClass" + : where == "gutter" ? "gutterClass" : "wrapClass" + var cur = line[prop] + if (!cur) { return false } + else if (cls == null) { line[prop] = null } + else { + var found = cur.match(classTest(cls)) + if (!found) { return false } + var end = found.index + found[0].length + line[prop] = cur.slice(0, found.index) + (!found.index || end == cur.length ? "" : " ") + cur.slice(end) || null + } + return true + }) + }), + + addLineWidget: docMethodOp(function(handle, node, options) { + return addLineWidget(this, handle, node, options) + }), + removeLineWidget: function(widget) { widget.clear() }, + + markText: function(from, to, options) { + return markText(this, clipPos(this, from), clipPos(this, to), options, options && options.type || "range") + }, + setBookmark: function(pos, options) { + var realOpts = {replacedWith: options && (options.nodeType == null ? options.widget : options), + insertLeft: options && options.insertLeft, + clearWhenEmpty: false, shared: options && options.shared, + handleMouseEvents: options && options.handleMouseEvents} + pos = clipPos(this, pos) + return markText(this, pos, pos, realOpts, "bookmark") + }, + findMarksAt: function(pos) { + pos = clipPos(this, pos) + var markers = [], spans = getLine(this, pos.line).markedSpans + if (spans) { for (var i = 0; i < spans.length; ++i) { + var span = spans[i] + if ((span.from == null || span.from <= pos.ch) && + (span.to == null || span.to >= pos.ch)) + { markers.push(span.marker.parent || span.marker) } + } } + return markers + }, + findMarks: function(from, to, filter) { + from = clipPos(this, from); to = clipPos(this, to) + var found = [], lineNo = from.line + this.iter(from.line, to.line + 1, function (line) { + var spans = line.markedSpans + if (spans) { for (var i = 0; i < spans.length; i++) { + var span = spans[i] + if (!(span.to != null && lineNo == from.line && from.ch >= span.to || + span.from == null && lineNo != from.line || + span.from != null && lineNo == to.line && span.from >= to.ch) && + (!filter || filter(span.marker))) + { found.push(span.marker.parent || span.marker) } + } } + ++lineNo + }) + return found + }, + getAllMarks: function() { + var markers = [] + this.iter(function (line) { + var sps = line.markedSpans + if (sps) { for (var i = 0; i < sps.length; ++i) + { if (sps[i].from != null) { markers.push(sps[i].marker) } } } + }) + return markers + }, + + posFromIndex: function(off) { + var ch, lineNo = this.first, sepSize = this.lineSeparator().length + this.iter(function (line) { + var sz = line.text.length + sepSize + if (sz > off) { ch = off; return true } + off -= sz + ++lineNo + }) + return clipPos(this, Pos(lineNo, ch)) + }, + indexFromPos: function (coords) { + coords = clipPos(this, coords) + var index = coords.ch + if (coords.line < this.first || coords.ch < 0) { return 0 } + var sepSize = this.lineSeparator().length + this.iter(this.first, coords.line, function (line) { // iter aborts when callback returns a truthy value + index += line.text.length + sepSize + }) + return index + }, + + copy: function(copyHistory) { + var doc = new Doc(getLines(this, this.first, this.first + this.size), + this.modeOption, this.first, this.lineSep, this.direction) + doc.scrollTop = this.scrollTop; doc.scrollLeft = this.scrollLeft + doc.sel = this.sel + doc.extend = false + if (copyHistory) { + doc.history.undoDepth = this.history.undoDepth + doc.setHistory(this.getHistory()) + } + return doc + }, + + linkedDoc: function(options) { + if (!options) { options = {} } + var from = this.first, to = this.first + this.size + if (options.from != null && options.from > from) { from = options.from } + if (options.to != null && options.to < to) { to = options.to } + var copy = new Doc(getLines(this, from, to), options.mode || this.modeOption, from, this.lineSep, this.direction) + if (options.sharedHist) { copy.history = this.history + ; }(this.linked || (this.linked = [])).push({doc: copy, sharedHist: options.sharedHist}) + copy.linked = [{doc: this, isParent: true, sharedHist: options.sharedHist}] + copySharedMarkers(copy, findSharedMarkers(this)) + return copy + }, + unlinkDoc: function(other) { + var this$1 = this; + + if (other instanceof CodeMirror) { other = other.doc } + if (this.linked) { for (var i = 0; i < this.linked.length; ++i) { + var link = this$1.linked[i] + if (link.doc != other) { continue } + this$1.linked.splice(i, 1) + other.unlinkDoc(this$1) + detachSharedMarkers(findSharedMarkers(this$1)) + break + } } + // If the histories were shared, split them again + if (other.history == this.history) { + var splitIds = [other.id] + linkedDocs(other, function (doc) { return splitIds.push(doc.id); }, true) + other.history = new History(null) + other.history.done = copyHistoryArray(this.history.done, splitIds) + other.history.undone = copyHistoryArray(this.history.undone, splitIds) + } + }, + iterLinkedDocs: function(f) {linkedDocs(this, f)}, + + getMode: function() {return this.mode}, + getEditor: function() {return this.cm}, + + splitLines: function(str) { + if (this.lineSep) { return str.split(this.lineSep) } + return splitLinesAuto(str) + }, + lineSeparator: function() { return this.lineSep || "\n" }, + + setDirection: docMethodOp(function (dir) { + if (dir != "rtl") { dir = "ltr" } + if (dir == this.direction) { return } + this.direction = dir + this.iter(function (line) { return line.order = null; }) + if (this.cm) { directionChanged(this.cm) } + }) + }) + + // Public alias. + Doc.prototype.eachLine = Doc.prototype.iter + + // Kludge to work around strange IE behavior where it'll sometimes + // re-fire a series of drag-related events right after the drop (#1551) + var lastDrop = 0 + + function onDrop(e) { + var cm = this + clearDragCursor(cm) + if (signalDOMEvent(cm, e) || eventInWidget(cm.display, e)) + { return } + e_preventDefault(e) + if (ie) { lastDrop = +new Date } + var pos = posFromMouse(cm, e, true), files = e.dataTransfer.files + if (!pos || cm.isReadOnly()) { return } + // Might be a file drop, in which case we simply extract the text + // and insert it. + if (files && files.length && window.FileReader && window.File) { + var n = files.length, text = Array(n), read = 0 + var loadFile = function (file, i) { + if (cm.options.allowDropFileTypes && + indexOf(cm.options.allowDropFileTypes, file.type) == -1) + { return } + + var reader = new FileReader + reader.onload = operation(cm, function () { + var content = reader.result + if (/[\x00-\x08\x0e-\x1f]{2}/.test(content)) { content = "" } + text[i] = content + if (++read == n) { + pos = clipPos(cm.doc, pos) + var change = {from: pos, to: pos, + text: cm.doc.splitLines(text.join(cm.doc.lineSeparator())), + origin: "paste"} + makeChange(cm.doc, change) + setSelectionReplaceHistory(cm.doc, simpleSelection(pos, changeEnd(change))) + } + }) + reader.readAsText(file) + } + for (var i = 0; i < n; ++i) { loadFile(files[i], i) } + } else { // Normal drop + // Don't do a replace if the drop happened inside of the selected text. + if (cm.state.draggingText && cm.doc.sel.contains(pos) > -1) { + cm.state.draggingText(e) + // Ensure the editor is re-focused + setTimeout(function () { return cm.display.input.focus(); }, 20) + return + } + try { + var text$1 = e.dataTransfer.getData("Text") + if (text$1) { + var selected + if (cm.state.draggingText && !cm.state.draggingText.copy) + { selected = cm.listSelections() } + setSelectionNoUndo(cm.doc, simpleSelection(pos, pos)) + if (selected) { for (var i$1 = 0; i$1 < selected.length; ++i$1) + { replaceRange(cm.doc, "", selected[i$1].anchor, selected[i$1].head, "drag") } } + cm.replaceSelection(text$1, "around", "paste") + cm.display.input.focus() + } + } + catch(e){} + } + } + + function onDragStart(cm, e) { + if (ie && (!cm.state.draggingText || +new Date - lastDrop < 100)) { e_stop(e); return } + if (signalDOMEvent(cm, e) || eventInWidget(cm.display, e)) { return } + + e.dataTransfer.setData("Text", cm.getSelection()) + e.dataTransfer.effectAllowed = "copyMove" + + // Use dummy image instead of default browsers image. + // Recent Safari (~6.0.2) have a tendency to segfault when this happens, so we don't do it there. + if (e.dataTransfer.setDragImage && !safari) { + var img = elt("img", null, null, "position: fixed; left: 0; top: 0;") + img.src = "data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==" + if (presto) { + img.width = img.height = 1 + cm.display.wrapper.appendChild(img) + // Force a relayout, or Opera won't use our image for some obscure reason + img._top = img.offsetTop + } + e.dataTransfer.setDragImage(img, 0, 0) + if (presto) { img.parentNode.removeChild(img) } + } + } + + function onDragOver(cm, e) { + var pos = posFromMouse(cm, e) + if (!pos) { return } + var frag = document.createDocumentFragment() + drawSelectionCursor(cm, pos, frag) + if (!cm.display.dragCursor) { + cm.display.dragCursor = elt("div", null, "CodeMirror-cursors CodeMirror-dragcursors") + cm.display.lineSpace.insertBefore(cm.display.dragCursor, cm.display.cursorDiv) + } + removeChildrenAndAdd(cm.display.dragCursor, frag) + } + + function clearDragCursor(cm) { + if (cm.display.dragCursor) { + cm.display.lineSpace.removeChild(cm.display.dragCursor) + cm.display.dragCursor = null + } + } + + // These must be handled carefully, because naively registering a + // handler for each editor will cause the editors to never be + // garbage collected. + + function forEachCodeMirror(f) { + if (!document.getElementsByClassName) { return } + var byClass = document.getElementsByClassName("CodeMirror") + for (var i = 0; i < byClass.length; i++) { + var cm = byClass[i].CodeMirror + if (cm) { f(cm) } + } + } + + var globalsRegistered = false + function ensureGlobalHandlers() { + if (globalsRegistered) { return } + registerGlobalHandlers() + globalsRegistered = true + } + function registerGlobalHandlers() { + // When the window resizes, we need to refresh active editors. + var resizeTimer + on(window, "resize", function () { + if (resizeTimer == null) { resizeTimer = setTimeout(function () { + resizeTimer = null + forEachCodeMirror(onResize) + }, 100) } + }) + // When the window loses focus, we want to show the editor as blurred + on(window, "blur", function () { return forEachCodeMirror(onBlur); }) + } + // Called when the window resizes + function onResize(cm) { + var d = cm.display + if (d.lastWrapHeight == d.wrapper.clientHeight && d.lastWrapWidth == d.wrapper.clientWidth) + { return } + // Might be a text scaling operation, clear size caches. + d.cachedCharWidth = d.cachedTextHeight = d.cachedPaddingH = null + d.scrollbarsClipped = false + cm.setSize() + } + + var keyNames = { + 3: "Pause", 8: "Backspace", 9: "Tab", 13: "Enter", 16: "Shift", 17: "Ctrl", 18: "Alt", + 19: "Pause", 20: "CapsLock", 27: "Esc", 32: "Space", 33: "PageUp", 34: "PageDown", 35: "End", + 36: "Home", 37: "Left", 38: "Up", 39: "Right", 40: "Down", 44: "PrintScrn", 45: "Insert", + 46: "Delete", 59: ";", 61: "=", 91: "Mod", 92: "Mod", 93: "Mod", + 106: "*", 107: "=", 109: "-", 110: ".", 111: "/", 127: "Delete", 145: "ScrollLock", + 173: "-", 186: ";", 187: "=", 188: ",", 189: "-", 190: ".", 191: "/", 192: "`", 219: "[", 220: "\\", + 221: "]", 222: "'", 63232: "Up", 63233: "Down", 63234: "Left", 63235: "Right", 63272: "Delete", + 63273: "Home", 63275: "End", 63276: "PageUp", 63277: "PageDown", 63302: "Insert" + } + + // Number keys + for (var i = 0; i < 10; i++) { keyNames[i + 48] = keyNames[i + 96] = String(i) } + // Alphabetic keys + for (var i$1 = 65; i$1 <= 90; i$1++) { keyNames[i$1] = String.fromCharCode(i$1) } + // Function keys + for (var i$2 = 1; i$2 <= 12; i$2++) { keyNames[i$2 + 111] = keyNames[i$2 + 63235] = "F" + i$2 } + + var keyMap = {} + + keyMap.basic = { + "Left": "goCharLeft", "Right": "goCharRight", "Up": "goLineUp", "Down": "goLineDown", + "End": "goLineEnd", "Home": "goLineStartSmart", "PageUp": "goPageUp", "PageDown": "goPageDown", + "Delete": "delCharAfter", "Backspace": "delCharBefore", "Shift-Backspace": "delCharBefore", + "Tab": "defaultTab", "Shift-Tab": "indentAuto", + "Enter": "newlineAndIndent", "Insert": "toggleOverwrite", + "Esc": "singleSelection" + } + // Note that the save and find-related commands aren't defined by + // default. User code or addons can define them. Unknown commands + // are simply ignored. + keyMap.pcDefault = { + "Ctrl-A": "selectAll", "Ctrl-D": "deleteLine", "Ctrl-Z": "undo", "Shift-Ctrl-Z": "redo", "Ctrl-Y": "redo", + "Ctrl-Home": "goDocStart", "Ctrl-End": "goDocEnd", "Ctrl-Up": "goLineUp", "Ctrl-Down": "goLineDown", + "Ctrl-Left": "goGroupLeft", "Ctrl-Right": "goGroupRight", "Alt-Left": "goLineStart", "Alt-Right": "goLineEnd", + "Ctrl-Backspace": "delGroupBefore", "Ctrl-Delete": "delGroupAfter", "Ctrl-S": "save", "Ctrl-F": "find", + "Ctrl-G": "findNext", "Shift-Ctrl-G": "findPrev", "Shift-Ctrl-F": "replace", "Shift-Ctrl-R": "replaceAll", + "Ctrl-[": "indentLess", "Ctrl-]": "indentMore", + "Ctrl-U": "undoSelection", "Shift-Ctrl-U": "redoSelection", "Alt-U": "redoSelection", + fallthrough: "basic" + } + // Very basic readline/emacs-style bindings, which are standard on Mac. + keyMap.emacsy = { + "Ctrl-F": "goCharRight", "Ctrl-B": "goCharLeft", "Ctrl-P": "goLineUp", "Ctrl-N": "goLineDown", + "Alt-F": "goWordRight", "Alt-B": "goWordLeft", "Ctrl-A": "goLineStart", "Ctrl-E": "goLineEnd", + "Ctrl-V": "goPageDown", "Shift-Ctrl-V": "goPageUp", "Ctrl-D": "delCharAfter", "Ctrl-H": "delCharBefore", + "Alt-D": "delWordAfter", "Alt-Backspace": "delWordBefore", "Ctrl-K": "killLine", "Ctrl-T": "transposeChars", + "Ctrl-O": "openLine" + } + keyMap.macDefault = { + "Cmd-A": "selectAll", "Cmd-D": "deleteLine", "Cmd-Z": "undo", "Shift-Cmd-Z": "redo", "Cmd-Y": "redo", + "Cmd-Home": "goDocStart", "Cmd-Up": "goDocStart", "Cmd-End": "goDocEnd", "Cmd-Down": "goDocEnd", "Alt-Left": "goGroupLeft", + "Alt-Right": "goGroupRight", "Cmd-Left": "goLineLeft", "Cmd-Right": "goLineRight", "Alt-Backspace": "delGroupBefore", + "Ctrl-Alt-Backspace": "delGroupAfter", "Alt-Delete": "delGroupAfter", "Cmd-S": "save", "Cmd-F": "find", + "Cmd-G": "findNext", "Shift-Cmd-G": "findPrev", "Cmd-Alt-F": "replace", "Shift-Cmd-Alt-F": "replaceAll", + "Cmd-[": "indentLess", "Cmd-]": "indentMore", "Cmd-Backspace": "delWrappedLineLeft", "Cmd-Delete": "delWrappedLineRight", + "Cmd-U": "undoSelection", "Shift-Cmd-U": "redoSelection", "Ctrl-Up": "goDocStart", "Ctrl-Down": "goDocEnd", + fallthrough: ["basic", "emacsy"] + } + keyMap["default"] = mac ? keyMap.macDefault : keyMap.pcDefault + + // KEYMAP DISPATCH + + function normalizeKeyName(name) { + var parts = name.split(/-(?!$)/) + name = parts[parts.length - 1] + var alt, ctrl, shift, cmd + for (var i = 0; i < parts.length - 1; i++) { + var mod = parts[i] + if (/^(cmd|meta|m)$/i.test(mod)) { cmd = true } + else if (/^a(lt)?$/i.test(mod)) { alt = true } + else if (/^(c|ctrl|control)$/i.test(mod)) { ctrl = true } + else if (/^s(hift)?$/i.test(mod)) { shift = true } + else { throw new Error("Unrecognized modifier name: " + mod) } + } + if (alt) { name = "Alt-" + name } + if (ctrl) { name = "Ctrl-" + name } + if (cmd) { name = "Cmd-" + name } + if (shift) { name = "Shift-" + name } + return name + } + + // This is a kludge to keep keymaps mostly working as raw objects + // (backwards compatibility) while at the same time support features + // like normalization and multi-stroke key bindings. It compiles a + // new normalized keymap, and then updates the old object to reflect + // this. + function normalizeKeyMap(keymap) { + var copy = {} + for (var keyname in keymap) { if (keymap.hasOwnProperty(keyname)) { + var value = keymap[keyname] + if (/^(name|fallthrough|(de|at)tach)$/.test(keyname)) { continue } + if (value == "...") { delete keymap[keyname]; continue } + + var keys = map(keyname.split(" "), normalizeKeyName) + for (var i = 0; i < keys.length; i++) { + var val = (void 0), name = (void 0) + if (i == keys.length - 1) { + name = keys.join(" ") + val = value + } else { + name = keys.slice(0, i + 1).join(" ") + val = "..." + } + var prev = copy[name] + if (!prev) { copy[name] = val } + else if (prev != val) { throw new Error("Inconsistent bindings for " + name) } + } + delete keymap[keyname] + } } + for (var prop in copy) { keymap[prop] = copy[prop] } + return keymap + } + + function lookupKey(key, map, handle, context) { + map = getKeyMap(map) + var found = map.call ? map.call(key, context) : map[key] + if (found === false) { return "nothing" } + if (found === "...") { return "multi" } + if (found != null && handle(found)) { return "handled" } + + if (map.fallthrough) { + if (Object.prototype.toString.call(map.fallthrough) != "[object Array]") + { return lookupKey(key, map.fallthrough, handle, context) } + for (var i = 0; i < map.fallthrough.length; i++) { + var result = lookupKey(key, map.fallthrough[i], handle, context) + if (result) { return result } + } + } + } + + // Modifier key presses don't count as 'real' key presses for the + // purpose of keymap fallthrough. + function isModifierKey(value) { + var name = typeof value == "string" ? value : keyNames[value.keyCode] + return name == "Ctrl" || name == "Alt" || name == "Shift" || name == "Mod" + } + + function addModifierNames(name, event, noShift) { + var base = name + if (event.altKey && base != "Alt") { name = "Alt-" + name } + if ((flipCtrlCmd ? event.metaKey : event.ctrlKey) && base != "Ctrl") { name = "Ctrl-" + name } + if ((flipCtrlCmd ? event.ctrlKey : event.metaKey) && base != "Cmd") { name = "Cmd-" + name } + if (!noShift && event.shiftKey && base != "Shift") { name = "Shift-" + name } + return name + } + + // Look up the name of a key as indicated by an event object. + function keyName(event, noShift) { + if (presto && event.keyCode == 34 && event["char"]) { return false } + var name = keyNames[event.keyCode] + if (name == null || event.altGraphKey) { return false } + // Ctrl-ScrollLock has keyCode 3, same as Ctrl-Pause, + // so we'll use event.code when available (Chrome 48+, FF 38+, Safari 10.1+) + if (event.keyCode == 3 && event.code) { name = event.code } + return addModifierNames(name, event, noShift) + } + + function getKeyMap(val) { + return typeof val == "string" ? keyMap[val] : val + } + + // Helper for deleting text near the selection(s), used to implement + // backspace, delete, and similar functionality. + function deleteNearSelection(cm, compute) { + var ranges = cm.doc.sel.ranges, kill = [] + // Build up a set of ranges to kill first, merging overlapping + // ranges. + for (var i = 0; i < ranges.length; i++) { + var toKill = compute(ranges[i]) + while (kill.length && cmp(toKill.from, lst(kill).to) <= 0) { + var replaced = kill.pop() + if (cmp(replaced.from, toKill.from) < 0) { + toKill.from = replaced.from + break + } + } + kill.push(toKill) + } + // Next, remove those actual ranges. + runInOp(cm, function () { + for (var i = kill.length - 1; i >= 0; i--) + { replaceRange(cm.doc, "", kill[i].from, kill[i].to, "+delete") } + ensureCursorVisible(cm) + }) + } + + function moveCharLogically(line, ch, dir) { + var target = skipExtendingChars(line.text, ch + dir, dir) + return target < 0 || target > line.text.length ? null : target + } + + function moveLogically(line, start, dir) { + var ch = moveCharLogically(line, start.ch, dir) + return ch == null ? null : new Pos(start.line, ch, dir < 0 ? "after" : "before") + } + + function endOfLine(visually, cm, lineObj, lineNo, dir) { + if (visually) { + var order = getOrder(lineObj, cm.doc.direction) + if (order) { + var part = dir < 0 ? lst(order) : order[0] + var moveInStorageOrder = (dir < 0) == (part.level == 1) + var sticky = moveInStorageOrder ? "after" : "before" + var ch + // With a wrapped rtl chunk (possibly spanning multiple bidi parts), + // it could be that the last bidi part is not on the last visual line, + // since visual lines contain content order-consecutive chunks. + // Thus, in rtl, we are looking for the first (content-order) character + // in the rtl chunk that is on the last line (that is, the same line + // as the last (content-order) character). + if (part.level > 0 || cm.doc.direction == "rtl") { + var prep = prepareMeasureForLine(cm, lineObj) + ch = dir < 0 ? lineObj.text.length - 1 : 0 + var targetTop = measureCharPrepared(cm, prep, ch).top + ch = findFirst(function (ch) { return measureCharPrepared(cm, prep, ch).top == targetTop; }, (dir < 0) == (part.level == 1) ? part.from : part.to - 1, ch) + if (sticky == "before") { ch = moveCharLogically(lineObj, ch, 1) } + } else { ch = dir < 0 ? part.to : part.from } + return new Pos(lineNo, ch, sticky) + } + } + return new Pos(lineNo, dir < 0 ? lineObj.text.length : 0, dir < 0 ? "before" : "after") + } + + function moveVisually(cm, line, start, dir) { + var bidi = getOrder(line, cm.doc.direction) + if (!bidi) { return moveLogically(line, start, dir) } + if (start.ch >= line.text.length) { + start.ch = line.text.length + start.sticky = "before" + } else if (start.ch <= 0) { + start.ch = 0 + start.sticky = "after" + } + var partPos = getBidiPartAt(bidi, start.ch, start.sticky), part = bidi[partPos] + if (cm.doc.direction == "ltr" && part.level % 2 == 0 && (dir > 0 ? part.to > start.ch : part.from < start.ch)) { + // Case 1: We move within an ltr part in an ltr editor. Even with wrapped lines, + // nothing interesting happens. + return moveLogically(line, start, dir) + } + + var mv = function (pos, dir) { return moveCharLogically(line, pos instanceof Pos ? pos.ch : pos, dir); } + var prep + var getWrappedLineExtent = function (ch) { + if (!cm.options.lineWrapping) { return {begin: 0, end: line.text.length} } + prep = prep || prepareMeasureForLine(cm, line) + return wrappedLineExtentChar(cm, line, prep, ch) + } + var wrappedLineExtent = getWrappedLineExtent(start.sticky == "before" ? mv(start, -1) : start.ch) + + if (cm.doc.direction == "rtl" || part.level == 1) { + var moveInStorageOrder = (part.level == 1) == (dir < 0) + var ch = mv(start, moveInStorageOrder ? 1 : -1) + if (ch != null && (!moveInStorageOrder ? ch >= part.from && ch >= wrappedLineExtent.begin : ch <= part.to && ch <= wrappedLineExtent.end)) { + // Case 2: We move within an rtl part or in an rtl editor on the same visual line + var sticky = moveInStorageOrder ? "before" : "after" + return new Pos(start.line, ch, sticky) + } + } + + // Case 3: Could not move within this bidi part in this visual line, so leave + // the current bidi part + + var searchInVisualLine = function (partPos, dir, wrappedLineExtent) { + var getRes = function (ch, moveInStorageOrder) { return moveInStorageOrder + ? new Pos(start.line, mv(ch, 1), "before") + : new Pos(start.line, ch, "after"); } + + for (; partPos >= 0 && partPos < bidi.length; partPos += dir) { + var part = bidi[partPos] + var moveInStorageOrder = (dir > 0) == (part.level != 1) + var ch = moveInStorageOrder ? wrappedLineExtent.begin : mv(wrappedLineExtent.end, -1) + if (part.from <= ch && ch < part.to) { return getRes(ch, moveInStorageOrder) } + ch = moveInStorageOrder ? part.from : mv(part.to, -1) + if (wrappedLineExtent.begin <= ch && ch < wrappedLineExtent.end) { return getRes(ch, moveInStorageOrder) } + } + } + + // Case 3a: Look for other bidi parts on the same visual line + var res = searchInVisualLine(partPos + dir, dir, wrappedLineExtent) + if (res) { return res } + + // Case 3b: Look for other bidi parts on the next visual line + var nextCh = dir > 0 ? wrappedLineExtent.end : mv(wrappedLineExtent.begin, -1) + if (nextCh != null && !(dir > 0 && nextCh == line.text.length)) { + res = searchInVisualLine(dir > 0 ? 0 : bidi.length - 1, dir, getWrappedLineExtent(nextCh)) + if (res) { return res } + } + + // Case 4: Nowhere to move + return null + } + + // Commands are parameter-less actions that can be performed on an + // editor, mostly used for keybindings. + var commands = { + selectAll: selectAll, + singleSelection: function (cm) { return cm.setSelection(cm.getCursor("anchor"), cm.getCursor("head"), sel_dontScroll); }, + killLine: function (cm) { return deleteNearSelection(cm, function (range) { + if (range.empty()) { + var len = getLine(cm.doc, range.head.line).text.length + if (range.head.ch == len && range.head.line < cm.lastLine()) + { return {from: range.head, to: Pos(range.head.line + 1, 0)} } + else + { return {from: range.head, to: Pos(range.head.line, len)} } + } else { + return {from: range.from(), to: range.to()} + } + }); }, + deleteLine: function (cm) { return deleteNearSelection(cm, function (range) { return ({ + from: Pos(range.from().line, 0), + to: clipPos(cm.doc, Pos(range.to().line + 1, 0)) + }); }); }, + delLineLeft: function (cm) { return deleteNearSelection(cm, function (range) { return ({ + from: Pos(range.from().line, 0), to: range.from() + }); }); }, + delWrappedLineLeft: function (cm) { return deleteNearSelection(cm, function (range) { + var top = cm.charCoords(range.head, "div").top + 5 + var leftPos = cm.coordsChar({left: 0, top: top}, "div") + return {from: leftPos, to: range.from()} + }); }, + delWrappedLineRight: function (cm) { return deleteNearSelection(cm, function (range) { + var top = cm.charCoords(range.head, "div").top + 5 + var rightPos = cm.coordsChar({left: cm.display.lineDiv.offsetWidth + 100, top: top}, "div") + return {from: range.from(), to: rightPos } + }); }, + undo: function (cm) { return cm.undo(); }, + redo: function (cm) { return cm.redo(); }, + undoSelection: function (cm) { return cm.undoSelection(); }, + redoSelection: function (cm) { return cm.redoSelection(); }, + goDocStart: function (cm) { return cm.extendSelection(Pos(cm.firstLine(), 0)); }, + goDocEnd: function (cm) { return cm.extendSelection(Pos(cm.lastLine())); }, + goLineStart: function (cm) { return cm.extendSelectionsBy(function (range) { return lineStart(cm, range.head.line); }, + {origin: "+move", bias: 1} + ); }, + goLineStartSmart: function (cm) { return cm.extendSelectionsBy(function (range) { return lineStartSmart(cm, range.head); }, + {origin: "+move", bias: 1} + ); }, + goLineEnd: function (cm) { return cm.extendSelectionsBy(function (range) { return lineEnd(cm, range.head.line); }, + {origin: "+move", bias: -1} + ); }, + goLineRight: function (cm) { return cm.extendSelectionsBy(function (range) { + var top = cm.cursorCoords(range.head, "div").top + 5 + return cm.coordsChar({left: cm.display.lineDiv.offsetWidth + 100, top: top}, "div") + }, sel_move); }, + goLineLeft: function (cm) { return cm.extendSelectionsBy(function (range) { + var top = cm.cursorCoords(range.head, "div").top + 5 + return cm.coordsChar({left: 0, top: top}, "div") + }, sel_move); }, + goLineLeftSmart: function (cm) { return cm.extendSelectionsBy(function (range) { + var top = cm.cursorCoords(range.head, "div").top + 5 + var pos = cm.coordsChar({left: 0, top: top}, "div") + if (pos.ch < cm.getLine(pos.line).search(/\S/)) { return lineStartSmart(cm, range.head) } + return pos + }, sel_move); }, + goLineUp: function (cm) { return cm.moveV(-1, "line"); }, + goLineDown: function (cm) { return cm.moveV(1, "line"); }, + goPageUp: function (cm) { return cm.moveV(-1, "page"); }, + goPageDown: function (cm) { return cm.moveV(1, "page"); }, + goCharLeft: function (cm) { return cm.moveH(-1, "char"); }, + goCharRight: function (cm) { return cm.moveH(1, "char"); }, + goColumnLeft: function (cm) { return cm.moveH(-1, "column"); }, + goColumnRight: function (cm) { return cm.moveH(1, "column"); }, + goWordLeft: function (cm) { return cm.moveH(-1, "word"); }, + goGroupRight: function (cm) { return cm.moveH(1, "group"); }, + goGroupLeft: function (cm) { return cm.moveH(-1, "group"); }, + goWordRight: function (cm) { return cm.moveH(1, "word"); }, + delCharBefore: function (cm) { return cm.deleteH(-1, "char"); }, + delCharAfter: function (cm) { return cm.deleteH(1, "char"); }, + delWordBefore: function (cm) { return cm.deleteH(-1, "word"); }, + delWordAfter: function (cm) { return cm.deleteH(1, "word"); }, + delGroupBefore: function (cm) { return cm.deleteH(-1, "group"); }, + delGroupAfter: function (cm) { return cm.deleteH(1, "group"); }, + indentAuto: function (cm) { return cm.indentSelection("smart"); }, + indentMore: function (cm) { return cm.indentSelection("add"); }, + indentLess: function (cm) { return cm.indentSelection("subtract"); }, + insertTab: function (cm) { return cm.replaceSelection("\t"); }, + insertSoftTab: function (cm) { + var spaces = [], ranges = cm.listSelections(), tabSize = cm.options.tabSize + for (var i = 0; i < ranges.length; i++) { + var pos = ranges[i].from() + var col = countColumn(cm.getLine(pos.line), pos.ch, tabSize) + spaces.push(spaceStr(tabSize - col % tabSize)) + } + cm.replaceSelections(spaces) + }, + defaultTab: function (cm) { + if (cm.somethingSelected()) { cm.indentSelection("add") } + else { cm.execCommand("insertTab") } + }, + // Swap the two chars left and right of each selection's head. + // Move cursor behind the two swapped characters afterwards. + // + // Doesn't consider line feeds a character. + // Doesn't scan more than one line above to find a character. + // Doesn't do anything on an empty line. + // Doesn't do anything with non-empty selections. + transposeChars: function (cm) { return runInOp(cm, function () { + var ranges = cm.listSelections(), newSel = [] + for (var i = 0; i < ranges.length; i++) { + if (!ranges[i].empty()) { continue } + var cur = ranges[i].head, line = getLine(cm.doc, cur.line).text + if (line) { + if (cur.ch == line.length) { cur = new Pos(cur.line, cur.ch - 1) } + if (cur.ch > 0) { + cur = new Pos(cur.line, cur.ch + 1) + cm.replaceRange(line.charAt(cur.ch - 1) + line.charAt(cur.ch - 2), + Pos(cur.line, cur.ch - 2), cur, "+transpose") + } else if (cur.line > cm.doc.first) { + var prev = getLine(cm.doc, cur.line - 1).text + if (prev) { + cur = new Pos(cur.line, 1) + cm.replaceRange(line.charAt(0) + cm.doc.lineSeparator() + + prev.charAt(prev.length - 1), + Pos(cur.line - 1, prev.length - 1), cur, "+transpose") + } + } + } + newSel.push(new Range(cur, cur)) + } + cm.setSelections(newSel) + }); }, + newlineAndIndent: function (cm) { return runInOp(cm, function () { + var sels = cm.listSelections() + for (var i = sels.length - 1; i >= 0; i--) + { cm.replaceRange(cm.doc.lineSeparator(), sels[i].anchor, sels[i].head, "+input") } + sels = cm.listSelections() + for (var i$1 = 0; i$1 < sels.length; i$1++) + { cm.indentLine(sels[i$1].from().line, null, true) } + ensureCursorVisible(cm) + }); }, + openLine: function (cm) { return cm.replaceSelection("\n", "start"); }, + toggleOverwrite: function (cm) { return cm.toggleOverwrite(); } + } + + + function lineStart(cm, lineN) { + var line = getLine(cm.doc, lineN) + var visual = visualLine(line) + if (visual != line) { lineN = lineNo(visual) } + return endOfLine(true, cm, visual, lineN, 1) + } + function lineEnd(cm, lineN) { + var line = getLine(cm.doc, lineN) + var visual = visualLineEnd(line) + if (visual != line) { lineN = lineNo(visual) } + return endOfLine(true, cm, line, lineN, -1) + } + function lineStartSmart(cm, pos) { + var start = lineStart(cm, pos.line) + var line = getLine(cm.doc, start.line) + var order = getOrder(line, cm.doc.direction) + if (!order || order[0].level == 0) { + var firstNonWS = Math.max(0, line.text.search(/\S/)) + var inWS = pos.line == start.line && pos.ch <= firstNonWS && pos.ch + return Pos(start.line, inWS ? 0 : firstNonWS, start.sticky) + } + return start + } + + // Run a handler that was bound to a key. + function doHandleBinding(cm, bound, dropShift) { + if (typeof bound == "string") { + bound = commands[bound] + if (!bound) { return false } + } + // Ensure previous input has been read, so that the handler sees a + // consistent view of the document + cm.display.input.ensurePolled() + var prevShift = cm.display.shift, done = false + try { + if (cm.isReadOnly()) { cm.state.suppressEdits = true } + if (dropShift) { cm.display.shift = false } + done = bound(cm) != Pass + } finally { + cm.display.shift = prevShift + cm.state.suppressEdits = false + } + return done + } + + function lookupKeyForEditor(cm, name, handle) { + for (var i = 0; i < cm.state.keyMaps.length; i++) { + var result = lookupKey(name, cm.state.keyMaps[i], handle, cm) + if (result) { return result } + } + return (cm.options.extraKeys && lookupKey(name, cm.options.extraKeys, handle, cm)) + || lookupKey(name, cm.options.keyMap, handle, cm) + } + + // Note that, despite the name, this function is also used to check + // for bound mouse clicks. + + var stopSeq = new Delayed + + function dispatchKey(cm, name, e, handle) { + var seq = cm.state.keySeq + if (seq) { + if (isModifierKey(name)) { return "handled" } + if (/\'$/.test(name)) + { cm.state.keySeq = null } + else + { stopSeq.set(50, function () { + if (cm.state.keySeq == seq) { + cm.state.keySeq = null + cm.display.input.reset() + } + }) } + if (dispatchKeyInner(cm, seq + " " + name, e, handle)) { return true } + } + return dispatchKeyInner(cm, name, e, handle) + } + + function dispatchKeyInner(cm, name, e, handle) { + var result = lookupKeyForEditor(cm, name, handle) + + if (result == "multi") + { cm.state.keySeq = name } + if (result == "handled") + { signalLater(cm, "keyHandled", cm, name, e) } + + if (result == "handled" || result == "multi") { + e_preventDefault(e) + restartBlink(cm) + } + + return !!result + } + + // Handle a key from the keydown event. + function handleKeyBinding(cm, e) { + var name = keyName(e, true) + if (!name) { return false } + + if (e.shiftKey && !cm.state.keySeq) { + // First try to resolve full name (including 'Shift-'). Failing + // that, see if there is a cursor-motion command (starting with + // 'go') bound to the keyname without 'Shift-'. + return dispatchKey(cm, "Shift-" + name, e, function (b) { return doHandleBinding(cm, b, true); }) + || dispatchKey(cm, name, e, function (b) { + if (typeof b == "string" ? /^go[A-Z]/.test(b) : b.motion) + { return doHandleBinding(cm, b) } + }) + } else { + return dispatchKey(cm, name, e, function (b) { return doHandleBinding(cm, b); }) + } + } + + // Handle a key from the keypress event + function handleCharBinding(cm, e, ch) { + return dispatchKey(cm, "'" + ch + "'", e, function (b) { return doHandleBinding(cm, b, true); }) + } + + var lastStoppedKey = null + function onKeyDown(e) { + var cm = this + cm.curOp.focus = activeElt() + if (signalDOMEvent(cm, e)) { return } + // IE does strange things with escape. + if (ie && ie_version < 11 && e.keyCode == 27) { e.returnValue = false } + var code = e.keyCode + cm.display.shift = code == 16 || e.shiftKey + var handled = handleKeyBinding(cm, e) + if (presto) { + lastStoppedKey = handled ? code : null + // Opera has no cut event... we try to at least catch the key combo + if (!handled && code == 88 && !hasCopyEvent && (mac ? e.metaKey : e.ctrlKey)) + { cm.replaceSelection("", null, "cut") } + } + + // Turn mouse into crosshair when Alt is held on Mac. + if (code == 18 && !/\bCodeMirror-crosshair\b/.test(cm.display.lineDiv.className)) + { showCrossHair(cm) } + } + + function showCrossHair(cm) { + var lineDiv = cm.display.lineDiv + addClass(lineDiv, "CodeMirror-crosshair") + + function up(e) { + if (e.keyCode == 18 || !e.altKey) { + rmClass(lineDiv, "CodeMirror-crosshair") + off(document, "keyup", up) + off(document, "mouseover", up) + } + } + on(document, "keyup", up) + on(document, "mouseover", up) + } + + function onKeyUp(e) { + if (e.keyCode == 16) { this.doc.sel.shift = false } + signalDOMEvent(this, e) + } + + function onKeyPress(e) { + var cm = this + if (eventInWidget(cm.display, e) || signalDOMEvent(cm, e) || e.ctrlKey && !e.altKey || mac && e.metaKey) { return } + var keyCode = e.keyCode, charCode = e.charCode + if (presto && keyCode == lastStoppedKey) {lastStoppedKey = null; e_preventDefault(e); return} + if ((presto && (!e.which || e.which < 10)) && handleKeyBinding(cm, e)) { return } + var ch = String.fromCharCode(charCode == null ? keyCode : charCode) + // Some browsers fire keypress events for backspace + if (ch == "\x08") { return } + if (handleCharBinding(cm, e, ch)) { return } + cm.display.input.onKeyPress(e) + } + + var DOUBLECLICK_DELAY = 400 + + var PastClick = function(time, pos, button) { + this.time = time + this.pos = pos + this.button = button + }; + + PastClick.prototype.compare = function (time, pos, button) { + return this.time + DOUBLECLICK_DELAY > time && + cmp(pos, this.pos) == 0 && button == this.button + }; + + var lastClick; + var lastDoubleClick; + function clickRepeat(pos, button) { + var now = +new Date + if (lastDoubleClick && lastDoubleClick.compare(now, pos, button)) { + lastClick = lastDoubleClick = null + return "triple" + } else if (lastClick && lastClick.compare(now, pos, button)) { + lastDoubleClick = new PastClick(now, pos, button) + lastClick = null + return "double" + } else { + lastClick = new PastClick(now, pos, button) + lastDoubleClick = null + return "single" + } + } + + // A mouse down can be a single click, double click, triple click, + // start of selection drag, start of text drag, new cursor + // (ctrl-click), rectangle drag (alt-drag), or xwin + // middle-click-paste. Or it might be a click on something we should + // not interfere with, such as a scrollbar or widget. + function onMouseDown(e) { + var cm = this, display = cm.display + if (signalDOMEvent(cm, e) || display.activeTouch && display.input.supportsTouch()) { return } + display.input.ensurePolled() + display.shift = e.shiftKey + + if (eventInWidget(display, e)) { + if (!webkit) { + // Briefly turn off draggability, to allow widgets to do + // normal dragging things. + display.scroller.draggable = false + setTimeout(function () { return display.scroller.draggable = true; }, 100) + } + return + } + if (clickInGutter(cm, e)) { return } + var pos = posFromMouse(cm, e), button = e_button(e), repeat = pos ? clickRepeat(pos, button) : "single" + window.focus() + + // #3261: make sure, that we're not starting a second selection + if (button == 1 && cm.state.selectingText) + { cm.state.selectingText(e) } + + if (pos && handleMappedButton(cm, button, pos, repeat, e)) { return } + + if (button == 1) { + if (pos) { leftButtonDown(cm, pos, repeat, e) } + else if (e_target(e) == display.scroller) { e_preventDefault(e) } + } else if (button == 2) { + if (pos) { extendSelection(cm.doc, pos) } + setTimeout(function () { return display.input.focus(); }, 20) + } else if (button == 3) { + if (captureRightClick) { onContextMenu(cm, e) } + else { delayBlurEvent(cm) } + } + } + + function handleMappedButton(cm, button, pos, repeat, event) { + var name = "Click" + if (repeat == "double") { name = "Double" + name } + else if (repeat == "triple") { name = "Triple" + name } + name = (button == 1 ? "Left" : button == 2 ? "Middle" : "Right") + name + + return dispatchKey(cm, addModifierNames(name, event), event, function (bound) { + if (typeof bound == "string") { bound = commands[bound] } + if (!bound) { return false } + var done = false + try { + if (cm.isReadOnly()) { cm.state.suppressEdits = true } + done = bound(cm, pos) != Pass + } finally { + cm.state.suppressEdits = false + } + return done + }) + } + + function configureMouse(cm, repeat, event) { + var option = cm.getOption("configureMouse") + var value = option ? option(cm, repeat, event) : {} + if (value.unit == null) { + var rect = chromeOS ? event.shiftKey && event.metaKey : event.altKey + value.unit = rect ? "rectangle" : repeat == "single" ? "char" : repeat == "double" ? "word" : "line" + } + if (value.extend == null || cm.doc.extend) { value.extend = cm.doc.extend || event.shiftKey } + if (value.addNew == null) { value.addNew = mac ? event.metaKey : event.ctrlKey } + if (value.moveOnDrag == null) { value.moveOnDrag = !(mac ? event.altKey : event.ctrlKey) } + return value + } + + function leftButtonDown(cm, pos, repeat, event) { + if (ie) { setTimeout(bind(ensureFocus, cm), 0) } + else { cm.curOp.focus = activeElt() } + + var behavior = configureMouse(cm, repeat, event) + + var sel = cm.doc.sel, contained + if (cm.options.dragDrop && dragAndDrop && !cm.isReadOnly() && + repeat == "single" && (contained = sel.contains(pos)) > -1 && + (cmp((contained = sel.ranges[contained]).from(), pos) < 0 || pos.xRel > 0) && + (cmp(contained.to(), pos) > 0 || pos.xRel < 0)) + { leftButtonStartDrag(cm, event, pos, behavior) } + else + { leftButtonSelect(cm, event, pos, behavior) } + } + + // Start a text drag. When it ends, see if any dragging actually + // happen, and treat as a click if it didn't. + function leftButtonStartDrag(cm, event, pos, behavior) { + var display = cm.display, moved = false + var dragEnd = operation(cm, function (e) { + if (webkit) { display.scroller.draggable = false } + cm.state.draggingText = false + off(display.wrapper.ownerDocument, "mouseup", dragEnd) + off(display.wrapper.ownerDocument, "mousemove", mouseMove) + off(display.scroller, "dragstart", dragStart) + off(display.scroller, "drop", dragEnd) + if (!moved) { + e_preventDefault(e) + if (!behavior.addNew) + { extendSelection(cm.doc, pos, null, null, behavior.extend) } + // Work around unexplainable focus problem in IE9 (#2127) and Chrome (#3081) + if (webkit || ie && ie_version == 9) + { setTimeout(function () {display.wrapper.ownerDocument.body.focus(); display.input.focus()}, 20) } + else + { display.input.focus() } + } + }) + var mouseMove = function(e2) { + moved = moved || Math.abs(event.clientX - e2.clientX) + Math.abs(event.clientY - e2.clientY) >= 10 + } + var dragStart = function () { return moved = true; } + // Let the drag handler handle this. + if (webkit) { display.scroller.draggable = true } + cm.state.draggingText = dragEnd + dragEnd.copy = !behavior.moveOnDrag + // IE's approach to draggable + if (display.scroller.dragDrop) { display.scroller.dragDrop() } + on(display.wrapper.ownerDocument, "mouseup", dragEnd) + on(display.wrapper.ownerDocument, "mousemove", mouseMove) + on(display.scroller, "dragstart", dragStart) + on(display.scroller, "drop", dragEnd) + + delayBlurEvent(cm) + setTimeout(function () { return display.input.focus(); }, 20) + } + + function rangeForUnit(cm, pos, unit) { + if (unit == "char") { return new Range(pos, pos) } + if (unit == "word") { return cm.findWordAt(pos) } + if (unit == "line") { return new Range(Pos(pos.line, 0), clipPos(cm.doc, Pos(pos.line + 1, 0))) } + var result = unit(cm, pos) + return new Range(result.from, result.to) + } + + // Normal selection, as opposed to text dragging. + function leftButtonSelect(cm, event, start, behavior) { + var display = cm.display, doc = cm.doc + e_preventDefault(event) + + var ourRange, ourIndex, startSel = doc.sel, ranges = startSel.ranges + if (behavior.addNew && !behavior.extend) { + ourIndex = doc.sel.contains(start) + if (ourIndex > -1) + { ourRange = ranges[ourIndex] } + else + { ourRange = new Range(start, start) } + } else { + ourRange = doc.sel.primary() + ourIndex = doc.sel.primIndex + } + + if (behavior.unit == "rectangle") { + if (!behavior.addNew) { ourRange = new Range(start, start) } + start = posFromMouse(cm, event, true, true) + ourIndex = -1 + } else { + var range = rangeForUnit(cm, start, behavior.unit) + if (behavior.extend) + { ourRange = extendRange(ourRange, range.anchor, range.head, behavior.extend) } + else + { ourRange = range } + } + + if (!behavior.addNew) { + ourIndex = 0 + setSelection(doc, new Selection([ourRange], 0), sel_mouse) + startSel = doc.sel + } else if (ourIndex == -1) { + ourIndex = ranges.length + setSelection(doc, normalizeSelection(ranges.concat([ourRange]), ourIndex), + {scroll: false, origin: "*mouse"}) + } else if (ranges.length > 1 && ranges[ourIndex].empty() && behavior.unit == "char" && !behavior.extend) { + setSelection(doc, normalizeSelection(ranges.slice(0, ourIndex).concat(ranges.slice(ourIndex + 1)), 0), + {scroll: false, origin: "*mouse"}) + startSel = doc.sel + } else { + replaceOneSelection(doc, ourIndex, ourRange, sel_mouse) + } + + var lastPos = start + function extendTo(pos) { + if (cmp(lastPos, pos) == 0) { return } + lastPos = pos + + if (behavior.unit == "rectangle") { + var ranges = [], tabSize = cm.options.tabSize + var startCol = countColumn(getLine(doc, start.line).text, start.ch, tabSize) + var posCol = countColumn(getLine(doc, pos.line).text, pos.ch, tabSize) + var left = Math.min(startCol, posCol), right = Math.max(startCol, posCol) + for (var line = Math.min(start.line, pos.line), end = Math.min(cm.lastLine(), Math.max(start.line, pos.line)); + line <= end; line++) { + var text = getLine(doc, line).text, leftPos = findColumn(text, left, tabSize) + if (left == right) + { ranges.push(new Range(Pos(line, leftPos), Pos(line, leftPos))) } + else if (text.length > leftPos) + { ranges.push(new Range(Pos(line, leftPos), Pos(line, findColumn(text, right, tabSize)))) } + } + if (!ranges.length) { ranges.push(new Range(start, start)) } + setSelection(doc, normalizeSelection(startSel.ranges.slice(0, ourIndex).concat(ranges), ourIndex), + {origin: "*mouse", scroll: false}) + cm.scrollIntoView(pos) + } else { + var oldRange = ourRange + var range = rangeForUnit(cm, pos, behavior.unit) + var anchor = oldRange.anchor, head + if (cmp(range.anchor, anchor) > 0) { + head = range.head + anchor = minPos(oldRange.from(), range.anchor) + } else { + head = range.anchor + anchor = maxPos(oldRange.to(), range.head) + } + var ranges$1 = startSel.ranges.slice(0) + ranges$1[ourIndex] = bidiSimplify(cm, new Range(clipPos(doc, anchor), head)) + setSelection(doc, normalizeSelection(ranges$1, ourIndex), sel_mouse) + } + } + + var editorSize = display.wrapper.getBoundingClientRect() + // Used to ensure timeout re-tries don't fire when another extend + // happened in the meantime (clearTimeout isn't reliable -- at + // least on Chrome, the timeouts still happen even when cleared, + // if the clear happens after their scheduled firing time). + var counter = 0 + + function extend(e) { + var curCount = ++counter + var cur = posFromMouse(cm, e, true, behavior.unit == "rectangle") + if (!cur) { return } + if (cmp(cur, lastPos) != 0) { + cm.curOp.focus = activeElt() + extendTo(cur) + var visible = visibleLines(display, doc) + if (cur.line >= visible.to || cur.line < visible.from) + { setTimeout(operation(cm, function () {if (counter == curCount) { extend(e) }}), 150) } + } else { + var outside = e.clientY < editorSize.top ? -20 : e.clientY > editorSize.bottom ? 20 : 0 + if (outside) { setTimeout(operation(cm, function () { + if (counter != curCount) { return } + display.scroller.scrollTop += outside + extend(e) + }), 50) } + } + } + + function done(e) { + cm.state.selectingText = false + counter = Infinity + e_preventDefault(e) + display.input.focus() + off(display.wrapper.ownerDocument, "mousemove", move) + off(display.wrapper.ownerDocument, "mouseup", up) + doc.history.lastSelOrigin = null + } + + var move = operation(cm, function (e) { + if (!e_button(e)) { done(e) } + else { extend(e) } + }) + var up = operation(cm, done) + cm.state.selectingText = up + on(display.wrapper.ownerDocument, "mousemove", move) + on(display.wrapper.ownerDocument, "mouseup", up) + } + + // Used when mouse-selecting to adjust the anchor to the proper side + // of a bidi jump depending on the visual position of the head. + function bidiSimplify(cm, range) { + var anchor = range.anchor; + var head = range.head; + var anchorLine = getLine(cm.doc, anchor.line) + if (cmp(anchor, head) == 0 && anchor.sticky == head.sticky) { return range } + var order = getOrder(anchorLine) + if (!order) { return range } + var index = getBidiPartAt(order, anchor.ch, anchor.sticky), part = order[index] + if (part.from != anchor.ch && part.to != anchor.ch) { return range } + var boundary = index + ((part.from == anchor.ch) == (part.level != 1) ? 0 : 1) + if (boundary == 0 || boundary == order.length) { return range } + + // Compute the relative visual position of the head compared to the + // anchor (<0 is to the left, >0 to the right) + var leftSide + if (head.line != anchor.line) { + leftSide = (head.line - anchor.line) * (cm.doc.direction == "ltr" ? 1 : -1) > 0 + } else { + var headIndex = getBidiPartAt(order, head.ch, head.sticky) + var dir = headIndex - index || (head.ch - anchor.ch) * (part.level == 1 ? -1 : 1) + if (headIndex == boundary - 1 || headIndex == boundary) + { leftSide = dir < 0 } + else + { leftSide = dir > 0 } + } + + var usePart = order[boundary + (leftSide ? -1 : 0)] + var from = leftSide == (usePart.level == 1) + var ch = from ? usePart.from : usePart.to, sticky = from ? "after" : "before" + return anchor.ch == ch && anchor.sticky == sticky ? range : new Range(new Pos(anchor.line, ch, sticky), head) + } + + + // Determines whether an event happened in the gutter, and fires the + // handlers for the corresponding event. + function gutterEvent(cm, e, type, prevent) { + var mX, mY + if (e.touches) { + mX = e.touches[0].clientX + mY = e.touches[0].clientY + } else { + try { mX = e.clientX; mY = e.clientY } + catch(e) { return false } + } + if (mX >= Math.floor(cm.display.gutters.getBoundingClientRect().right)) { return false } + if (prevent) { e_preventDefault(e) } + + var display = cm.display + var lineBox = display.lineDiv.getBoundingClientRect() + + if (mY > lineBox.bottom || !hasHandler(cm, type)) { return e_defaultPrevented(e) } + mY -= lineBox.top - display.viewOffset + + for (var i = 0; i < cm.options.gutters.length; ++i) { + var g = display.gutters.childNodes[i] + if (g && g.getBoundingClientRect().right >= mX) { + var line = lineAtHeight(cm.doc, mY) + var gutter = cm.options.gutters[i] + signal(cm, type, cm, line, gutter, e) + return e_defaultPrevented(e) + } + } + } + + function clickInGutter(cm, e) { + return gutterEvent(cm, e, "gutterClick", true) + } + + // CONTEXT MENU HANDLING + + // To make the context menu work, we need to briefly unhide the + // textarea (making it as unobtrusive as possible) to let the + // right-click take effect on it. + function onContextMenu(cm, e) { + if (eventInWidget(cm.display, e) || contextMenuInGutter(cm, e)) { return } + if (signalDOMEvent(cm, e, "contextmenu")) { return } + cm.display.input.onContextMenu(e) + } + + function contextMenuInGutter(cm, e) { + if (!hasHandler(cm, "gutterContextMenu")) { return false } + return gutterEvent(cm, e, "gutterContextMenu", false) + } + + function themeChanged(cm) { + cm.display.wrapper.className = cm.display.wrapper.className.replace(/\s*cm-s-\S+/g, "") + + cm.options.theme.replace(/(^|\s)\s*/g, " cm-s-") + clearCaches(cm) + } + + var Init = {toString: function(){return "CodeMirror.Init"}} + + var defaults = {} + var optionHandlers = {} + + function defineOptions(CodeMirror) { + var optionHandlers = CodeMirror.optionHandlers + + function option(name, deflt, handle, notOnInit) { + CodeMirror.defaults[name] = deflt + if (handle) { optionHandlers[name] = + notOnInit ? function (cm, val, old) {if (old != Init) { handle(cm, val, old) }} : handle } + } + + CodeMirror.defineOption = option + + // Passed to option handlers when there is no old value. + CodeMirror.Init = Init + + // These two are, on init, called from the constructor because they + // have to be initialized before the editor can start at all. + option("value", "", function (cm, val) { return cm.setValue(val); }, true) + option("mode", null, function (cm, val) { + cm.doc.modeOption = val + loadMode(cm) + }, true) + + option("indentUnit", 2, loadMode, true) + option("indentWithTabs", false) + option("smartIndent", true) + option("tabSize", 4, function (cm) { + resetModeState(cm) + clearCaches(cm) + regChange(cm) + }, true) + + option("lineSeparator", null, function (cm, val) { + cm.doc.lineSep = val + if (!val) { return } + var newBreaks = [], lineNo = cm.doc.first + cm.doc.iter(function (line) { + for (var pos = 0;;) { + var found = line.text.indexOf(val, pos) + if (found == -1) { break } + pos = found + val.length + newBreaks.push(Pos(lineNo, found)) + } + lineNo++ + }) + for (var i = newBreaks.length - 1; i >= 0; i--) + { replaceRange(cm.doc, val, newBreaks[i], Pos(newBreaks[i].line, newBreaks[i].ch + val.length)) } + }) + option("specialChars", /[\u0000-\u001f\u007f-\u009f\u00ad\u061c\u200b-\u200f\u2028\u2029\ufeff]/g, function (cm, val, old) { + cm.state.specialChars = new RegExp(val.source + (val.test("\t") ? "" : "|\t"), "g") + if (old != Init) { cm.refresh() } + }) + option("specialCharPlaceholder", defaultSpecialCharPlaceholder, function (cm) { return cm.refresh(); }, true) + option("electricChars", true) + option("inputStyle", mobile ? "contenteditable" : "textarea", function () { + throw new Error("inputStyle can not (yet) be changed in a running editor") // FIXME + }, true) + option("spellcheck", false, function (cm, val) { return cm.getInputField().spellcheck = val; }, true) + option("rtlMoveVisually", !windows) + option("wholeLineUpdateBefore", true) + + option("theme", "default", function (cm) { + themeChanged(cm) + guttersChanged(cm) + }, true) + option("keyMap", "default", function (cm, val, old) { + var next = getKeyMap(val) + var prev = old != Init && getKeyMap(old) + if (prev && prev.detach) { prev.detach(cm, next) } + if (next.attach) { next.attach(cm, prev || null) } + }) + option("extraKeys", null) + option("configureMouse", null) + + option("lineWrapping", false, wrappingChanged, true) + option("gutters", [], function (cm) { + setGuttersForLineNumbers(cm.options) + guttersChanged(cm) + }, true) + option("fixedGutter", true, function (cm, val) { + cm.display.gutters.style.left = val ? compensateForHScroll(cm.display) + "px" : "0" + cm.refresh() + }, true) + option("coverGutterNextToScrollbar", false, function (cm) { return updateScrollbars(cm); }, true) + option("scrollbarStyle", "native", function (cm) { + initScrollbars(cm) + updateScrollbars(cm) + cm.display.scrollbars.setScrollTop(cm.doc.scrollTop) + cm.display.scrollbars.setScrollLeft(cm.doc.scrollLeft) + }, true) + option("lineNumbers", false, function (cm) { + setGuttersForLineNumbers(cm.options) + guttersChanged(cm) + }, true) + option("firstLineNumber", 1, guttersChanged, true) + option("lineNumberFormatter", function (integer) { return integer; }, guttersChanged, true) + option("showCursorWhenSelecting", false, updateSelection, true) + + option("resetSelectionOnContextMenu", true) + option("lineWiseCopyCut", true) + option("pasteLinesPerSelection", true) + + option("readOnly", false, function (cm, val) { + if (val == "nocursor") { + onBlur(cm) + cm.display.input.blur() + } + cm.display.input.readOnlyChanged(val) + }) + option("disableInput", false, function (cm, val) {if (!val) { cm.display.input.reset() }}, true) + option("dragDrop", true, dragDropChanged) + option("allowDropFileTypes", null) + + option("cursorBlinkRate", 530) + option("cursorScrollMargin", 0) + option("cursorHeight", 1, updateSelection, true) + option("singleCursorHeightPerLine", true, updateSelection, true) + option("workTime", 100) + option("workDelay", 100) + option("flattenSpans", true, resetModeState, true) + option("addModeClass", false, resetModeState, true) + option("pollInterval", 100) + option("undoDepth", 200, function (cm, val) { return cm.doc.history.undoDepth = val; }) + option("historyEventDelay", 1250) + option("viewportMargin", 10, function (cm) { return cm.refresh(); }, true) + option("maxHighlightLength", 10000, resetModeState, true) + option("moveInputWithCursor", true, function (cm, val) { + if (!val) { cm.display.input.resetPosition() } + }) + + option("tabindex", null, function (cm, val) { return cm.display.input.getField().tabIndex = val || ""; }) + option("autofocus", null) + option("direction", "ltr", function (cm, val) { return cm.doc.setDirection(val); }, true) + } + + function guttersChanged(cm) { + updateGutters(cm) + regChange(cm) + alignHorizontally(cm) + } + + function dragDropChanged(cm, value, old) { + var wasOn = old && old != Init + if (!value != !wasOn) { + var funcs = cm.display.dragFunctions + var toggle = value ? on : off + toggle(cm.display.scroller, "dragstart", funcs.start) + toggle(cm.display.scroller, "dragenter", funcs.enter) + toggle(cm.display.scroller, "dragover", funcs.over) + toggle(cm.display.scroller, "dragleave", funcs.leave) + toggle(cm.display.scroller, "drop", funcs.drop) + } + } + + function wrappingChanged(cm) { + if (cm.options.lineWrapping) { + addClass(cm.display.wrapper, "CodeMirror-wrap") + cm.display.sizer.style.minWidth = "" + cm.display.sizerWidth = null + } else { + rmClass(cm.display.wrapper, "CodeMirror-wrap") + findMaxLine(cm) + } + estimateLineHeights(cm) + regChange(cm) + clearCaches(cm) + setTimeout(function () { return updateScrollbars(cm); }, 100) + } + + // A CodeMirror instance represents an editor. This is the object + // that user code is usually dealing with. + + function CodeMirror(place, options) { + var this$1 = this; + + if (!(this instanceof CodeMirror)) { return new CodeMirror(place, options) } + + this.options = options = options ? copyObj(options) : {} + // Determine effective options based on given values and defaults. + copyObj(defaults, options, false) + setGuttersForLineNumbers(options) + + var doc = options.value + if (typeof doc == "string") { doc = new Doc(doc, options.mode, null, options.lineSeparator, options.direction) } + this.doc = doc + + var input = new CodeMirror.inputStyles[options.inputStyle](this) + var display = this.display = new Display(place, doc, input) + display.wrapper.CodeMirror = this + updateGutters(this) + themeChanged(this) + if (options.lineWrapping) + { this.display.wrapper.className += " CodeMirror-wrap" } + initScrollbars(this) + + this.state = { + keyMaps: [], // stores maps added by addKeyMap + overlays: [], // highlighting overlays, as added by addOverlay + modeGen: 0, // bumped when mode/overlay changes, used to invalidate highlighting info + overwrite: false, + delayingBlurEvent: false, + focused: false, + suppressEdits: false, // used to disable editing during key handlers when in readOnly mode + pasteIncoming: false, cutIncoming: false, // help recognize paste/cut edits in input.poll + selectingText: false, + draggingText: false, + highlight: new Delayed(), // stores highlight worker timeout + keySeq: null, // Unfinished key sequence + specialChars: null + } + + if (options.autofocus && !mobile) { display.input.focus() } + + // Override magic textarea content restore that IE sometimes does + // on our hidden textarea on reload + if (ie && ie_version < 11) { setTimeout(function () { return this$1.display.input.reset(true); }, 20) } + + registerEventHandlers(this) + ensureGlobalHandlers() + + startOperation(this) + this.curOp.forceUpdate = true + attachDoc(this, doc) + + if ((options.autofocus && !mobile) || this.hasFocus()) + { setTimeout(bind(onFocus, this), 20) } + else + { onBlur(this) } + + for (var opt in optionHandlers) { if (optionHandlers.hasOwnProperty(opt)) + { optionHandlers[opt](this$1, options[opt], Init) } } + maybeUpdateLineNumberWidth(this) + if (options.finishInit) { options.finishInit(this) } + for (var i = 0; i < initHooks.length; ++i) { initHooks[i](this$1) } + endOperation(this) + // Suppress optimizelegibility in Webkit, since it breaks text + // measuring on line wrapping boundaries. + if (webkit && options.lineWrapping && + getComputedStyle(display.lineDiv).textRendering == "optimizelegibility") + { display.lineDiv.style.textRendering = "auto" } + } + + // The default configuration options. + CodeMirror.defaults = defaults + // Functions to run when options are changed. + CodeMirror.optionHandlers = optionHandlers + + // Attach the necessary event handlers when initializing the editor + function registerEventHandlers(cm) { + var d = cm.display + on(d.scroller, "mousedown", operation(cm, onMouseDown)) + // Older IE's will not fire a second mousedown for a double click + if (ie && ie_version < 11) + { on(d.scroller, "dblclick", operation(cm, function (e) { + if (signalDOMEvent(cm, e)) { return } + var pos = posFromMouse(cm, e) + if (!pos || clickInGutter(cm, e) || eventInWidget(cm.display, e)) { return } + e_preventDefault(e) + var word = cm.findWordAt(pos) + extendSelection(cm.doc, word.anchor, word.head) + })) } + else + { on(d.scroller, "dblclick", function (e) { return signalDOMEvent(cm, e) || e_preventDefault(e); }) } + // Some browsers fire contextmenu *after* opening the menu, at + // which point we can't mess with it anymore. Context menu is + // handled in onMouseDown for these browsers. + if (!captureRightClick) { on(d.scroller, "contextmenu", function (e) { return onContextMenu(cm, e); }) } + + // Used to suppress mouse event handling when a touch happens + var touchFinished, prevTouch = {end: 0} + function finishTouch() { + if (d.activeTouch) { + touchFinished = setTimeout(function () { return d.activeTouch = null; }, 1000) + prevTouch = d.activeTouch + prevTouch.end = +new Date + } + } + function isMouseLikeTouchEvent(e) { + if (e.touches.length != 1) { return false } + var touch = e.touches[0] + return touch.radiusX <= 1 && touch.radiusY <= 1 + } + function farAway(touch, other) { + if (other.left == null) { return true } + var dx = other.left - touch.left, dy = other.top - touch.top + return dx * dx + dy * dy > 20 * 20 + } + on(d.scroller, "touchstart", function (e) { + if (!signalDOMEvent(cm, e) && !isMouseLikeTouchEvent(e) && !clickInGutter(cm, e)) { + d.input.ensurePolled() + clearTimeout(touchFinished) + var now = +new Date + d.activeTouch = {start: now, moved: false, + prev: now - prevTouch.end <= 300 ? prevTouch : null} + if (e.touches.length == 1) { + d.activeTouch.left = e.touches[0].pageX + d.activeTouch.top = e.touches[0].pageY + } + } + }) + on(d.scroller, "touchmove", function () { + if (d.activeTouch) { d.activeTouch.moved = true } + }) + on(d.scroller, "touchend", function (e) { + var touch = d.activeTouch + if (touch && !eventInWidget(d, e) && touch.left != null && + !touch.moved && new Date - touch.start < 300) { + var pos = cm.coordsChar(d.activeTouch, "page"), range + if (!touch.prev || farAway(touch, touch.prev)) // Single tap + { range = new Range(pos, pos) } + else if (!touch.prev.prev || farAway(touch, touch.prev.prev)) // Double tap + { range = cm.findWordAt(pos) } + else // Triple tap + { range = new Range(Pos(pos.line, 0), clipPos(cm.doc, Pos(pos.line + 1, 0))) } + cm.setSelection(range.anchor, range.head) + cm.focus() + e_preventDefault(e) + } + finishTouch() + }) + on(d.scroller, "touchcancel", finishTouch) + + // Sync scrolling between fake scrollbars and real scrollable + // area, ensure viewport is updated when scrolling. + on(d.scroller, "scroll", function () { + if (d.scroller.clientHeight) { + updateScrollTop(cm, d.scroller.scrollTop) + setScrollLeft(cm, d.scroller.scrollLeft, true) + signal(cm, "scroll", cm) + } + }) + + // Listen to wheel events in order to try and update the viewport on time. + on(d.scroller, "mousewheel", function (e) { return onScrollWheel(cm, e); }) + on(d.scroller, "DOMMouseScroll", function (e) { return onScrollWheel(cm, e); }) + + // Prevent wrapper from ever scrolling + on(d.wrapper, "scroll", function () { return d.wrapper.scrollTop = d.wrapper.scrollLeft = 0; }) + + d.dragFunctions = { + enter: function (e) {if (!signalDOMEvent(cm, e)) { e_stop(e) }}, + over: function (e) {if (!signalDOMEvent(cm, e)) { onDragOver(cm, e); e_stop(e) }}, + start: function (e) { return onDragStart(cm, e); }, + drop: operation(cm, onDrop), + leave: function (e) {if (!signalDOMEvent(cm, e)) { clearDragCursor(cm) }} + } + + var inp = d.input.getField() + on(inp, "keyup", function (e) { return onKeyUp.call(cm, e); }) + on(inp, "keydown", operation(cm, onKeyDown)) + on(inp, "keypress", operation(cm, onKeyPress)) + on(inp, "focus", function (e) { return onFocus(cm, e); }) + on(inp, "blur", function (e) { return onBlur(cm, e); }) + } + + var initHooks = [] + CodeMirror.defineInitHook = function (f) { return initHooks.push(f); } + + // Indent the given line. The how parameter can be "smart", + // "add"/null, "subtract", or "prev". When aggressive is false + // (typically set to true for forced single-line indents), empty + // lines are not indented, and places where the mode returns Pass + // are left alone. + function indentLine(cm, n, how, aggressive) { + var doc = cm.doc, state + if (how == null) { how = "add" } + if (how == "smart") { + // Fall back to "prev" when the mode doesn't have an indentation + // method. + if (!doc.mode.indent) { how = "prev" } + else { state = getContextBefore(cm, n).state } + } + + var tabSize = cm.options.tabSize + var line = getLine(doc, n), curSpace = countColumn(line.text, null, tabSize) + if (line.stateAfter) { line.stateAfter = null } + var curSpaceString = line.text.match(/^\s*/)[0], indentation + if (!aggressive && !/\S/.test(line.text)) { + indentation = 0 + how = "not" + } else if (how == "smart") { + indentation = doc.mode.indent(state, line.text.slice(curSpaceString.length), line.text) + if (indentation == Pass || indentation > 150) { + if (!aggressive) { return } + how = "prev" + } + } + if (how == "prev") { + if (n > doc.first) { indentation = countColumn(getLine(doc, n-1).text, null, tabSize) } + else { indentation = 0 } + } else if (how == "add") { + indentation = curSpace + cm.options.indentUnit + } else if (how == "subtract") { + indentation = curSpace - cm.options.indentUnit + } else if (typeof how == "number") { + indentation = curSpace + how + } + indentation = Math.max(0, indentation) + + var indentString = "", pos = 0 + if (cm.options.indentWithTabs) + { for (var i = Math.floor(indentation / tabSize); i; --i) {pos += tabSize; indentString += "\t"} } + if (pos < indentation) { indentString += spaceStr(indentation - pos) } + + if (indentString != curSpaceString) { + replaceRange(doc, indentString, Pos(n, 0), Pos(n, curSpaceString.length), "+input") + line.stateAfter = null + return true + } else { + // Ensure that, if the cursor was in the whitespace at the start + // of the line, it is moved to the end of that space. + for (var i$1 = 0; i$1 < doc.sel.ranges.length; i$1++) { + var range = doc.sel.ranges[i$1] + if (range.head.line == n && range.head.ch < curSpaceString.length) { + var pos$1 = Pos(n, curSpaceString.length) + replaceOneSelection(doc, i$1, new Range(pos$1, pos$1)) + break + } + } + } + } + + // This will be set to a {lineWise: bool, text: [string]} object, so + // that, when pasting, we know what kind of selections the copied + // text was made out of. + var lastCopied = null + + function setLastCopied(newLastCopied) { + lastCopied = newLastCopied + } + + function applyTextInput(cm, inserted, deleted, sel, origin) { + var doc = cm.doc + cm.display.shift = false + if (!sel) { sel = doc.sel } + + var paste = cm.state.pasteIncoming || origin == "paste" + var textLines = splitLinesAuto(inserted), multiPaste = null + // When pasting N lines into N selections, insert one line per selection + if (paste && sel.ranges.length > 1) { + if (lastCopied && lastCopied.text.join("\n") == inserted) { + if (sel.ranges.length % lastCopied.text.length == 0) { + multiPaste = [] + for (var i = 0; i < lastCopied.text.length; i++) + { multiPaste.push(doc.splitLines(lastCopied.text[i])) } + } + } else if (textLines.length == sel.ranges.length && cm.options.pasteLinesPerSelection) { + multiPaste = map(textLines, function (l) { return [l]; }) + } + } + + var updateInput + // Normal behavior is to insert the new text into every selection + for (var i$1 = sel.ranges.length - 1; i$1 >= 0; i$1--) { + var range = sel.ranges[i$1] + var from = range.from(), to = range.to() + if (range.empty()) { + if (deleted && deleted > 0) // Handle deletion + { from = Pos(from.line, from.ch - deleted) } + else if (cm.state.overwrite && !paste) // Handle overwrite + { to = Pos(to.line, Math.min(getLine(doc, to.line).text.length, to.ch + lst(textLines).length)) } + else if (lastCopied && lastCopied.lineWise && lastCopied.text.join("\n") == inserted) + { from = to = Pos(from.line, 0) } + } + updateInput = cm.curOp.updateInput + var changeEvent = {from: from, to: to, text: multiPaste ? multiPaste[i$1 % multiPaste.length] : textLines, + origin: origin || (paste ? "paste" : cm.state.cutIncoming ? "cut" : "+input")} + makeChange(cm.doc, changeEvent) + signalLater(cm, "inputRead", cm, changeEvent) + } + if (inserted && !paste) + { triggerElectric(cm, inserted) } + + ensureCursorVisible(cm) + cm.curOp.updateInput = updateInput + cm.curOp.typing = true + cm.state.pasteIncoming = cm.state.cutIncoming = false + } + + function handlePaste(e, cm) { + var pasted = e.clipboardData && e.clipboardData.getData("Text") + if (pasted) { + e.preventDefault() + if (!cm.isReadOnly() && !cm.options.disableInput) + { runInOp(cm, function () { return applyTextInput(cm, pasted, 0, null, "paste"); }) } + return true + } + } + + function triggerElectric(cm, inserted) { + // When an 'electric' character is inserted, immediately trigger a reindent + if (!cm.options.electricChars || !cm.options.smartIndent) { return } + var sel = cm.doc.sel + + for (var i = sel.ranges.length - 1; i >= 0; i--) { + var range = sel.ranges[i] + if (range.head.ch > 100 || (i && sel.ranges[i - 1].head.line == range.head.line)) { continue } + var mode = cm.getModeAt(range.head) + var indented = false + if (mode.electricChars) { + for (var j = 0; j < mode.electricChars.length; j++) + { if (inserted.indexOf(mode.electricChars.charAt(j)) > -1) { + indented = indentLine(cm, range.head.line, "smart") + break + } } + } else if (mode.electricInput) { + if (mode.electricInput.test(getLine(cm.doc, range.head.line).text.slice(0, range.head.ch))) + { indented = indentLine(cm, range.head.line, "smart") } + } + if (indented) { signalLater(cm, "electricInput", cm, range.head.line) } + } + } + + function copyableRanges(cm) { + var text = [], ranges = [] + for (var i = 0; i < cm.doc.sel.ranges.length; i++) { + var line = cm.doc.sel.ranges[i].head.line + var lineRange = {anchor: Pos(line, 0), head: Pos(line + 1, 0)} + ranges.push(lineRange) + text.push(cm.getRange(lineRange.anchor, lineRange.head)) + } + return {text: text, ranges: ranges} + } + + function disableBrowserMagic(field, spellcheck) { + field.setAttribute("autocorrect", "off") + field.setAttribute("autocapitalize", "off") + field.setAttribute("spellcheck", !!spellcheck) + } + + function hiddenTextarea() { + var te = elt("textarea", null, null, "position: absolute; bottom: -1em; padding: 0; width: 1px; height: 1em; outline: none") + var div = elt("div", [te], null, "overflow: hidden; position: relative; width: 3px; height: 0px;") + // The textarea is kept positioned near the cursor to prevent the + // fact that it'll be scrolled into view on input from scrolling + // our fake cursor out of view. On webkit, when wrap=off, paste is + // very slow. So make the area wide instead. + if (webkit) { te.style.width = "1000px" } + else { te.setAttribute("wrap", "off") } + // If border: 0; -- iOS fails to open keyboard (issue #1287) + if (ios) { te.style.border = "1px solid black" } + disableBrowserMagic(te) + return div + } + + // The publicly visible API. Note that methodOp(f) means + // 'wrap f in an operation, performed on its `this` parameter'. + + // This is not the complete set of editor methods. Most of the + // methods defined on the Doc type are also injected into + // CodeMirror.prototype, for backwards compatibility and + // convenience. + + function addEditorMethods(CodeMirror) { + var optionHandlers = CodeMirror.optionHandlers + + var helpers = CodeMirror.helpers = {} + + CodeMirror.prototype = { + constructor: CodeMirror, + focus: function(){window.focus(); this.display.input.focus()}, + + setOption: function(option, value) { + var options = this.options, old = options[option] + if (options[option] == value && option != "mode") { return } + options[option] = value + if (optionHandlers.hasOwnProperty(option)) + { operation(this, optionHandlers[option])(this, value, old) } + signal(this, "optionChange", this, option) + }, + + getOption: function(option) {return this.options[option]}, + getDoc: function() {return this.doc}, + + addKeyMap: function(map, bottom) { + this.state.keyMaps[bottom ? "push" : "unshift"](getKeyMap(map)) + }, + removeKeyMap: function(map) { + var maps = this.state.keyMaps + for (var i = 0; i < maps.length; ++i) + { if (maps[i] == map || maps[i].name == map) { + maps.splice(i, 1) + return true + } } + }, + + addOverlay: methodOp(function(spec, options) { + var mode = spec.token ? spec : CodeMirror.getMode(this.options, spec) + if (mode.startState) { throw new Error("Overlays may not be stateful.") } + insertSorted(this.state.overlays, + {mode: mode, modeSpec: spec, opaque: options && options.opaque, + priority: (options && options.priority) || 0}, + function (overlay) { return overlay.priority; }) + this.state.modeGen++ + regChange(this) + }), + removeOverlay: methodOp(function(spec) { + var this$1 = this; + + var overlays = this.state.overlays + for (var i = 0; i < overlays.length; ++i) { + var cur = overlays[i].modeSpec + if (cur == spec || typeof spec == "string" && cur.name == spec) { + overlays.splice(i, 1) + this$1.state.modeGen++ + regChange(this$1) + return + } + } + }), + + indentLine: methodOp(function(n, dir, aggressive) { + if (typeof dir != "string" && typeof dir != "number") { + if (dir == null) { dir = this.options.smartIndent ? "smart" : "prev" } + else { dir = dir ? "add" : "subtract" } + } + if (isLine(this.doc, n)) { indentLine(this, n, dir, aggressive) } + }), + indentSelection: methodOp(function(how) { + var this$1 = this; + + var ranges = this.doc.sel.ranges, end = -1 + for (var i = 0; i < ranges.length; i++) { + var range = ranges[i] + if (!range.empty()) { + var from = range.from(), to = range.to() + var start = Math.max(end, from.line) + end = Math.min(this$1.lastLine(), to.line - (to.ch ? 0 : 1)) + 1 + for (var j = start; j < end; ++j) + { indentLine(this$1, j, how) } + var newRanges = this$1.doc.sel.ranges + if (from.ch == 0 && ranges.length == newRanges.length && newRanges[i].from().ch > 0) + { replaceOneSelection(this$1.doc, i, new Range(from, newRanges[i].to()), sel_dontScroll) } + } else if (range.head.line > end) { + indentLine(this$1, range.head.line, how, true) + end = range.head.line + if (i == this$1.doc.sel.primIndex) { ensureCursorVisible(this$1) } + } + } + }), + + // Fetch the parser token for a given character. Useful for hacks + // that want to inspect the mode state (say, for completion). + getTokenAt: function(pos, precise) { + return takeToken(this, pos, precise) + }, + + getLineTokens: function(line, precise) { + return takeToken(this, Pos(line), precise, true) + }, + + getTokenTypeAt: function(pos) { + pos = clipPos(this.doc, pos) + var styles = getLineStyles(this, getLine(this.doc, pos.line)) + var before = 0, after = (styles.length - 1) / 2, ch = pos.ch + var type + if (ch == 0) { type = styles[2] } + else { for (;;) { + var mid = (before + after) >> 1 + if ((mid ? styles[mid * 2 - 1] : 0) >= ch) { after = mid } + else if (styles[mid * 2 + 1] < ch) { before = mid + 1 } + else { type = styles[mid * 2 + 2]; break } + } } + var cut = type ? type.indexOf("overlay ") : -1 + return cut < 0 ? type : cut == 0 ? null : type.slice(0, cut - 1) + }, + + getModeAt: function(pos) { + var mode = this.doc.mode + if (!mode.innerMode) { return mode } + return CodeMirror.innerMode(mode, this.getTokenAt(pos).state).mode + }, + + getHelper: function(pos, type) { + return this.getHelpers(pos, type)[0] + }, + + getHelpers: function(pos, type) { + var this$1 = this; + + var found = [] + if (!helpers.hasOwnProperty(type)) { return found } + var help = helpers[type], mode = this.getModeAt(pos) + if (typeof mode[type] == "string") { + if (help[mode[type]]) { found.push(help[mode[type]]) } + } else if (mode[type]) { + for (var i = 0; i < mode[type].length; i++) { + var val = help[mode[type][i]] + if (val) { found.push(val) } + } + } else if (mode.helperType && help[mode.helperType]) { + found.push(help[mode.helperType]) + } else if (help[mode.name]) { + found.push(help[mode.name]) + } + for (var i$1 = 0; i$1 < help._global.length; i$1++) { + var cur = help._global[i$1] + if (cur.pred(mode, this$1) && indexOf(found, cur.val) == -1) + { found.push(cur.val) } + } + return found + }, + + getStateAfter: function(line, precise) { + var doc = this.doc + line = clipLine(doc, line == null ? doc.first + doc.size - 1: line) + return getContextBefore(this, line + 1, precise).state + }, + + cursorCoords: function(start, mode) { + var pos, range = this.doc.sel.primary() + if (start == null) { pos = range.head } + else if (typeof start == "object") { pos = clipPos(this.doc, start) } + else { pos = start ? range.from() : range.to() } + return cursorCoords(this, pos, mode || "page") + }, + + charCoords: function(pos, mode) { + return charCoords(this, clipPos(this.doc, pos), mode || "page") + }, + + coordsChar: function(coords, mode) { + coords = fromCoordSystem(this, coords, mode || "page") + return coordsChar(this, coords.left, coords.top) + }, + + lineAtHeight: function(height, mode) { + height = fromCoordSystem(this, {top: height, left: 0}, mode || "page").top + return lineAtHeight(this.doc, height + this.display.viewOffset) + }, + heightAtLine: function(line, mode, includeWidgets) { + var end = false, lineObj + if (typeof line == "number") { + var last = this.doc.first + this.doc.size - 1 + if (line < this.doc.first) { line = this.doc.first } + else if (line > last) { line = last; end = true } + lineObj = getLine(this.doc, line) + } else { + lineObj = line + } + return intoCoordSystem(this, lineObj, {top: 0, left: 0}, mode || "page", includeWidgets || end).top + + (end ? this.doc.height - heightAtLine(lineObj) : 0) + }, + + defaultTextHeight: function() { return textHeight(this.display) }, + defaultCharWidth: function() { return charWidth(this.display) }, + + getViewport: function() { return {from: this.display.viewFrom, to: this.display.viewTo}}, + + addWidget: function(pos, node, scroll, vert, horiz) { + var display = this.display + pos = cursorCoords(this, clipPos(this.doc, pos)) + var top = pos.bottom, left = pos.left + node.style.position = "absolute" + node.setAttribute("cm-ignore-events", "true") + this.display.input.setUneditable(node) + display.sizer.appendChild(node) + if (vert == "over") { + top = pos.top + } else if (vert == "above" || vert == "near") { + var vspace = Math.max(display.wrapper.clientHeight, this.doc.height), + hspace = Math.max(display.sizer.clientWidth, display.lineSpace.clientWidth) + // Default to positioning above (if specified and possible); otherwise default to positioning below + if ((vert == 'above' || pos.bottom + node.offsetHeight > vspace) && pos.top > node.offsetHeight) + { top = pos.top - node.offsetHeight } + else if (pos.bottom + node.offsetHeight <= vspace) + { top = pos.bottom } + if (left + node.offsetWidth > hspace) + { left = hspace - node.offsetWidth } + } + node.style.top = top + "px" + node.style.left = node.style.right = "" + if (horiz == "right") { + left = display.sizer.clientWidth - node.offsetWidth + node.style.right = "0px" + } else { + if (horiz == "left") { left = 0 } + else if (horiz == "middle") { left = (display.sizer.clientWidth - node.offsetWidth) / 2 } + node.style.left = left + "px" + } + if (scroll) + { scrollIntoView(this, {left: left, top: top, right: left + node.offsetWidth, bottom: top + node.offsetHeight}) } + }, + + triggerOnKeyDown: methodOp(onKeyDown), + triggerOnKeyPress: methodOp(onKeyPress), + triggerOnKeyUp: onKeyUp, + triggerOnMouseDown: methodOp(onMouseDown), + + execCommand: function(cmd) { + if (commands.hasOwnProperty(cmd)) + { return commands[cmd].call(null, this) } + }, + + triggerElectric: methodOp(function(text) { triggerElectric(this, text) }), + + findPosH: function(from, amount, unit, visually) { + var this$1 = this; + + var dir = 1 + if (amount < 0) { dir = -1; amount = -amount } + var cur = clipPos(this.doc, from) + for (var i = 0; i < amount; ++i) { + cur = findPosH(this$1.doc, cur, dir, unit, visually) + if (cur.hitSide) { break } + } + return cur + }, + + moveH: methodOp(function(dir, unit) { + var this$1 = this; + + this.extendSelectionsBy(function (range) { + if (this$1.display.shift || this$1.doc.extend || range.empty()) + { return findPosH(this$1.doc, range.head, dir, unit, this$1.options.rtlMoveVisually) } + else + { return dir < 0 ? range.from() : range.to() } + }, sel_move) + }), + + deleteH: methodOp(function(dir, unit) { + var sel = this.doc.sel, doc = this.doc + if (sel.somethingSelected()) + { doc.replaceSelection("", null, "+delete") } + else + { deleteNearSelection(this, function (range) { + var other = findPosH(doc, range.head, dir, unit, false) + return dir < 0 ? {from: other, to: range.head} : {from: range.head, to: other} + }) } + }), + + findPosV: function(from, amount, unit, goalColumn) { + var this$1 = this; + + var dir = 1, x = goalColumn + if (amount < 0) { dir = -1; amount = -amount } + var cur = clipPos(this.doc, from) + for (var i = 0; i < amount; ++i) { + var coords = cursorCoords(this$1, cur, "div") + if (x == null) { x = coords.left } + else { coords.left = x } + cur = findPosV(this$1, coords, dir, unit) + if (cur.hitSide) { break } + } + return cur + }, + + moveV: methodOp(function(dir, unit) { + var this$1 = this; + + var doc = this.doc, goals = [] + var collapse = !this.display.shift && !doc.extend && doc.sel.somethingSelected() + doc.extendSelectionsBy(function (range) { + if (collapse) + { return dir < 0 ? range.from() : range.to() } + var headPos = cursorCoords(this$1, range.head, "div") + if (range.goalColumn != null) { headPos.left = range.goalColumn } + goals.push(headPos.left) + var pos = findPosV(this$1, headPos, dir, unit) + if (unit == "page" && range == doc.sel.primary()) + { addToScrollTop(this$1, charCoords(this$1, pos, "div").top - headPos.top) } + return pos + }, sel_move) + if (goals.length) { for (var i = 0; i < doc.sel.ranges.length; i++) + { doc.sel.ranges[i].goalColumn = goals[i] } } + }), + + // Find the word at the given position (as returned by coordsChar). + findWordAt: function(pos) { + var doc = this.doc, line = getLine(doc, pos.line).text + var start = pos.ch, end = pos.ch + if (line) { + var helper = this.getHelper(pos, "wordChars") + if ((pos.sticky == "before" || end == line.length) && start) { --start; } else { ++end } + var startChar = line.charAt(start) + var check = isWordChar(startChar, helper) + ? function (ch) { return isWordChar(ch, helper); } + : /\s/.test(startChar) ? function (ch) { return /\s/.test(ch); } + : function (ch) { return (!/\s/.test(ch) && !isWordChar(ch)); } + while (start > 0 && check(line.charAt(start - 1))) { --start } + while (end < line.length && check(line.charAt(end))) { ++end } + } + return new Range(Pos(pos.line, start), Pos(pos.line, end)) + }, + + toggleOverwrite: function(value) { + if (value != null && value == this.state.overwrite) { return } + if (this.state.overwrite = !this.state.overwrite) + { addClass(this.display.cursorDiv, "CodeMirror-overwrite") } + else + { rmClass(this.display.cursorDiv, "CodeMirror-overwrite") } + + signal(this, "overwriteToggle", this, this.state.overwrite) + }, + hasFocus: function() { return this.display.input.getField() == activeElt() }, + isReadOnly: function() { return !!(this.options.readOnly || this.doc.cantEdit) }, + + scrollTo: methodOp(function (x, y) { scrollToCoords(this, x, y) }), + getScrollInfo: function() { + var scroller = this.display.scroller + return {left: scroller.scrollLeft, top: scroller.scrollTop, + height: scroller.scrollHeight - scrollGap(this) - this.display.barHeight, + width: scroller.scrollWidth - scrollGap(this) - this.display.barWidth, + clientHeight: displayHeight(this), clientWidth: displayWidth(this)} + }, + + scrollIntoView: methodOp(function(range, margin) { + if (range == null) { + range = {from: this.doc.sel.primary().head, to: null} + if (margin == null) { margin = this.options.cursorScrollMargin } + } else if (typeof range == "number") { + range = {from: Pos(range, 0), to: null} + } else if (range.from == null) { + range = {from: range, to: null} + } + if (!range.to) { range.to = range.from } + range.margin = margin || 0 + + if (range.from.line != null) { + scrollToRange(this, range) + } else { + scrollToCoordsRange(this, range.from, range.to, range.margin) + } + }), + + setSize: methodOp(function(width, height) { + var this$1 = this; + + var interpret = function (val) { return typeof val == "number" || /^\d+$/.test(String(val)) ? val + "px" : val; } + if (width != null) { this.display.wrapper.style.width = interpret(width) } + if (height != null) { this.display.wrapper.style.height = interpret(height) } + if (this.options.lineWrapping) { clearLineMeasurementCache(this) } + var lineNo = this.display.viewFrom + this.doc.iter(lineNo, this.display.viewTo, function (line) { + if (line.widgets) { for (var i = 0; i < line.widgets.length; i++) + { if (line.widgets[i].noHScroll) { regLineChange(this$1, lineNo, "widget"); break } } } + ++lineNo + }) + this.curOp.forceUpdate = true + signal(this, "refresh", this) + }), + + operation: function(f){return runInOp(this, f)}, + startOperation: function(){return startOperation(this)}, + endOperation: function(){return endOperation(this)}, + + refresh: methodOp(function() { + var oldHeight = this.display.cachedTextHeight + regChange(this) + this.curOp.forceUpdate = true + clearCaches(this) + scrollToCoords(this, this.doc.scrollLeft, this.doc.scrollTop) + updateGutterSpace(this) + if (oldHeight == null || Math.abs(oldHeight - textHeight(this.display)) > .5) + { estimateLineHeights(this) } + signal(this, "refresh", this) + }), + + swapDoc: methodOp(function(doc) { + var old = this.doc + old.cm = null + attachDoc(this, doc) + clearCaches(this) + this.display.input.reset() + scrollToCoords(this, doc.scrollLeft, doc.scrollTop) + this.curOp.forceScroll = true + signalLater(this, "swapDoc", this, old) + return old + }), + + getInputField: function(){return this.display.input.getField()}, + getWrapperElement: function(){return this.display.wrapper}, + getScrollerElement: function(){return this.display.scroller}, + getGutterElement: function(){return this.display.gutters} + } + eventMixin(CodeMirror) + + CodeMirror.registerHelper = function(type, name, value) { + if (!helpers.hasOwnProperty(type)) { helpers[type] = CodeMirror[type] = {_global: []} } + helpers[type][name] = value + } + CodeMirror.registerGlobalHelper = function(type, name, predicate, value) { + CodeMirror.registerHelper(type, name, value) + helpers[type]._global.push({pred: predicate, val: value}) + } + } + + // Used for horizontal relative motion. Dir is -1 or 1 (left or + // right), unit can be "char", "column" (like char, but doesn't + // cross line boundaries), "word" (across next word), or "group" (to + // the start of next group of word or non-word-non-whitespace + // chars). The visually param controls whether, in right-to-left + // text, direction 1 means to move towards the next index in the + // string, or towards the character to the right of the current + // position. The resulting position will have a hitSide=true + // property if it reached the end of the document. + function findPosH(doc, pos, dir, unit, visually) { + var oldPos = pos + var origDir = dir + var lineObj = getLine(doc, pos.line) + function findNextLine() { + var l = pos.line + dir + if (l < doc.first || l >= doc.first + doc.size) { return false } + pos = new Pos(l, pos.ch, pos.sticky) + return lineObj = getLine(doc, l) + } + function moveOnce(boundToLine) { + var next + if (visually) { + next = moveVisually(doc.cm, lineObj, pos, dir) + } else { + next = moveLogically(lineObj, pos, dir) + } + if (next == null) { + if (!boundToLine && findNextLine()) + { pos = endOfLine(visually, doc.cm, lineObj, pos.line, dir) } + else + { return false } + } else { + pos = next + } + return true + } + + if (unit == "char") { + moveOnce() + } else if (unit == "column") { + moveOnce(true) + } else if (unit == "word" || unit == "group") { + var sawType = null, group = unit == "group" + var helper = doc.cm && doc.cm.getHelper(pos, "wordChars") + for (var first = true;; first = false) { + if (dir < 0 && !moveOnce(!first)) { break } + var cur = lineObj.text.charAt(pos.ch) || "\n" + var type = isWordChar(cur, helper) ? "w" + : group && cur == "\n" ? "n" + : !group || /\s/.test(cur) ? null + : "p" + if (group && !first && !type) { type = "s" } + if (sawType && sawType != type) { + if (dir < 0) {dir = 1; moveOnce(); pos.sticky = "after"} + break + } + + if (type) { sawType = type } + if (dir > 0 && !moveOnce(!first)) { break } + } + } + var result = skipAtomic(doc, pos, oldPos, origDir, true) + if (equalCursorPos(oldPos, result)) { result.hitSide = true } + return result + } + + // For relative vertical movement. Dir may be -1 or 1. Unit can be + // "page" or "line". The resulting position will have a hitSide=true + // property if it reached the end of the document. + function findPosV(cm, pos, dir, unit) { + var doc = cm.doc, x = pos.left, y + if (unit == "page") { + var pageSize = Math.min(cm.display.wrapper.clientHeight, window.innerHeight || document.documentElement.clientHeight) + var moveAmount = Math.max(pageSize - .5 * textHeight(cm.display), 3) + y = (dir > 0 ? pos.bottom : pos.top) + dir * moveAmount + + } else if (unit == "line") { + y = dir > 0 ? pos.bottom + 3 : pos.top - 3 + } + var target + for (;;) { + target = coordsChar(cm, x, y) + if (!target.outside) { break } + if (dir < 0 ? y <= 0 : y >= doc.height) { target.hitSide = true; break } + y += dir * 5 + } + return target + } + + // CONTENTEDITABLE INPUT STYLE + + var ContentEditableInput = function(cm) { + this.cm = cm + this.lastAnchorNode = this.lastAnchorOffset = this.lastFocusNode = this.lastFocusOffset = null + this.polling = new Delayed() + this.composing = null + this.gracePeriod = false + this.readDOMTimeout = null + }; + + ContentEditableInput.prototype.init = function (display) { + var this$1 = this; + + var input = this, cm = input.cm + var div = input.div = display.lineDiv + disableBrowserMagic(div, cm.options.spellcheck) + + on(div, "paste", function (e) { + if (signalDOMEvent(cm, e) || handlePaste(e, cm)) { return } + // IE doesn't fire input events, so we schedule a read for the pasted content in this way + if (ie_version <= 11) { setTimeout(operation(cm, function () { return this$1.updateFromDOM(); }), 20) } + }) + + on(div, "compositionstart", function (e) { + this$1.composing = {data: e.data, done: false} + }) + on(div, "compositionupdate", function (e) { + if (!this$1.composing) { this$1.composing = {data: e.data, done: false} } + }) + on(div, "compositionend", function (e) { + if (this$1.composing) { + if (e.data != this$1.composing.data) { this$1.readFromDOMSoon() } + this$1.composing.done = true + } + }) + + on(div, "touchstart", function () { return input.forceCompositionEnd(); }) + + on(div, "input", function () { + if (!this$1.composing) { this$1.readFromDOMSoon() } + }) + + function onCopyCut(e) { + if (signalDOMEvent(cm, e)) { return } + if (cm.somethingSelected()) { + setLastCopied({lineWise: false, text: cm.getSelections()}) + if (e.type == "cut") { cm.replaceSelection("", null, "cut") } + } else if (!cm.options.lineWiseCopyCut) { + return + } else { + var ranges = copyableRanges(cm) + setLastCopied({lineWise: true, text: ranges.text}) + if (e.type == "cut") { + cm.operation(function () { + cm.setSelections(ranges.ranges, 0, sel_dontScroll) + cm.replaceSelection("", null, "cut") + }) + } + } + if (e.clipboardData) { + e.clipboardData.clearData() + var content = lastCopied.text.join("\n") + // iOS exposes the clipboard API, but seems to discard content inserted into it + e.clipboardData.setData("Text", content) + if (e.clipboardData.getData("Text") == content) { + e.preventDefault() + return + } + } + // Old-fashioned briefly-focus-a-textarea hack + var kludge = hiddenTextarea(), te = kludge.firstChild + cm.display.lineSpace.insertBefore(kludge, cm.display.lineSpace.firstChild) + te.value = lastCopied.text.join("\n") + var hadFocus = document.activeElement + selectInput(te) + setTimeout(function () { + cm.display.lineSpace.removeChild(kludge) + hadFocus.focus() + if (hadFocus == div) { input.showPrimarySelection() } + }, 50) + } + on(div, "copy", onCopyCut) + on(div, "cut", onCopyCut) + }; + + ContentEditableInput.prototype.prepareSelection = function () { + var result = prepareSelection(this.cm, false) + result.focus = this.cm.state.focused + return result + }; + + ContentEditableInput.prototype.showSelection = function (info, takeFocus) { + if (!info || !this.cm.display.view.length) { return } + if (info.focus || takeFocus) { this.showPrimarySelection() } + this.showMultipleSelections(info) + }; + + ContentEditableInput.prototype.showPrimarySelection = function () { + var sel = window.getSelection(), cm = this.cm, prim = cm.doc.sel.primary() + var from = prim.from(), to = prim.to() + + if (cm.display.viewTo == cm.display.viewFrom || from.line >= cm.display.viewTo || to.line < cm.display.viewFrom) { + sel.removeAllRanges() + return + } + + var curAnchor = domToPos(cm, sel.anchorNode, sel.anchorOffset) + var curFocus = domToPos(cm, sel.focusNode, sel.focusOffset) + if (curAnchor && !curAnchor.bad && curFocus && !curFocus.bad && + cmp(minPos(curAnchor, curFocus), from) == 0 && + cmp(maxPos(curAnchor, curFocus), to) == 0) + { return } + + var view = cm.display.view + var start = (from.line >= cm.display.viewFrom && posToDOM(cm, from)) || + {node: view[0].measure.map[2], offset: 0} + var end = to.line < cm.display.viewTo && posToDOM(cm, to) + if (!end) { + var measure = view[view.length - 1].measure + var map = measure.maps ? measure.maps[measure.maps.length - 1] : measure.map + end = {node: map[map.length - 1], offset: map[map.length - 2] - map[map.length - 3]} + } + + if (!start || !end) { + sel.removeAllRanges() + return + } + + var old = sel.rangeCount && sel.getRangeAt(0), rng + try { rng = range(start.node, start.offset, end.offset, end.node) } + catch(e) {} // Our model of the DOM might be outdated, in which case the range we try to set can be impossible + if (rng) { + if (!gecko && cm.state.focused) { + sel.collapse(start.node, start.offset) + if (!rng.collapsed) { + sel.removeAllRanges() + sel.addRange(rng) + } + } else { + sel.removeAllRanges() + sel.addRange(rng) + } + if (old && sel.anchorNode == null) { sel.addRange(old) } + else if (gecko) { this.startGracePeriod() } + } + this.rememberSelection() + }; + + ContentEditableInput.prototype.startGracePeriod = function () { + var this$1 = this; + + clearTimeout(this.gracePeriod) + this.gracePeriod = setTimeout(function () { + this$1.gracePeriod = false + if (this$1.selectionChanged()) + { this$1.cm.operation(function () { return this$1.cm.curOp.selectionChanged = true; }) } + }, 20) + }; + + ContentEditableInput.prototype.showMultipleSelections = function (info) { + removeChildrenAndAdd(this.cm.display.cursorDiv, info.cursors) + removeChildrenAndAdd(this.cm.display.selectionDiv, info.selection) + }; + + ContentEditableInput.prototype.rememberSelection = function () { + var sel = window.getSelection() + this.lastAnchorNode = sel.anchorNode; this.lastAnchorOffset = sel.anchorOffset + this.lastFocusNode = sel.focusNode; this.lastFocusOffset = sel.focusOffset + }; + + ContentEditableInput.prototype.selectionInEditor = function () { + var sel = window.getSelection() + if (!sel.rangeCount) { return false } + var node = sel.getRangeAt(0).commonAncestorContainer + return contains(this.div, node) + }; + + ContentEditableInput.prototype.focus = function () { + if (this.cm.options.readOnly != "nocursor") { + if (!this.selectionInEditor()) + { this.showSelection(this.prepareSelection(), true) } + this.div.focus() + } + }; + ContentEditableInput.prototype.blur = function () { this.div.blur() }; + ContentEditableInput.prototype.getField = function () { return this.div }; + + ContentEditableInput.prototype.supportsTouch = function () { return true }; + + ContentEditableInput.prototype.receivedFocus = function () { + var input = this + if (this.selectionInEditor()) + { this.pollSelection() } + else + { runInOp(this.cm, function () { return input.cm.curOp.selectionChanged = true; }) } + + function poll() { + if (input.cm.state.focused) { + input.pollSelection() + input.polling.set(input.cm.options.pollInterval, poll) + } + } + this.polling.set(this.cm.options.pollInterval, poll) + }; + + ContentEditableInput.prototype.selectionChanged = function () { + var sel = window.getSelection() + return sel.anchorNode != this.lastAnchorNode || sel.anchorOffset != this.lastAnchorOffset || + sel.focusNode != this.lastFocusNode || sel.focusOffset != this.lastFocusOffset + }; + + ContentEditableInput.prototype.pollSelection = function () { + if (this.readDOMTimeout != null || this.gracePeriod || !this.selectionChanged()) { return } + var sel = window.getSelection(), cm = this.cm + // On Android Chrome (version 56, at least), backspacing into an + // uneditable block element will put the cursor in that element, + // and then, because it's not editable, hide the virtual keyboard. + // Because Android doesn't allow us to actually detect backspace + // presses in a sane way, this code checks for when that happens + // and simulates a backspace press in this case. + if (android && chrome && this.cm.options.gutters.length && isInGutter(sel.anchorNode)) { + this.cm.triggerOnKeyDown({type: "keydown", keyCode: 8, preventDefault: Math.abs}) + this.blur() + this.focus() + return + } + if (this.composing) { return } + this.rememberSelection() + var anchor = domToPos(cm, sel.anchorNode, sel.anchorOffset) + var head = domToPos(cm, sel.focusNode, sel.focusOffset) + if (anchor && head) { runInOp(cm, function () { + setSelection(cm.doc, simpleSelection(anchor, head), sel_dontScroll) + if (anchor.bad || head.bad) { cm.curOp.selectionChanged = true } + }) } + }; + + ContentEditableInput.prototype.pollContent = function () { + if (this.readDOMTimeout != null) { + clearTimeout(this.readDOMTimeout) + this.readDOMTimeout = null + } + + var cm = this.cm, display = cm.display, sel = cm.doc.sel.primary() + var from = sel.from(), to = sel.to() + if (from.ch == 0 && from.line > cm.firstLine()) + { from = Pos(from.line - 1, getLine(cm.doc, from.line - 1).length) } + if (to.ch == getLine(cm.doc, to.line).text.length && to.line < cm.lastLine()) + { to = Pos(to.line + 1, 0) } + if (from.line < display.viewFrom || to.line > display.viewTo - 1) { return false } + + var fromIndex, fromLine, fromNode + if (from.line == display.viewFrom || (fromIndex = findViewIndex(cm, from.line)) == 0) { + fromLine = lineNo(display.view[0].line) + fromNode = display.view[0].node + } else { + fromLine = lineNo(display.view[fromIndex].line) + fromNode = display.view[fromIndex - 1].node.nextSibling + } + var toIndex = findViewIndex(cm, to.line) + var toLine, toNode + if (toIndex == display.view.length - 1) { + toLine = display.viewTo - 1 + toNode = display.lineDiv.lastChild + } else { + toLine = lineNo(display.view[toIndex + 1].line) - 1 + toNode = display.view[toIndex + 1].node.previousSibling + } + + if (!fromNode) { return false } + var newText = cm.doc.splitLines(domTextBetween(cm, fromNode, toNode, fromLine, toLine)) + var oldText = getBetween(cm.doc, Pos(fromLine, 0), Pos(toLine, getLine(cm.doc, toLine).text.length)) + while (newText.length > 1 && oldText.length > 1) { + if (lst(newText) == lst(oldText)) { newText.pop(); oldText.pop(); toLine-- } + else if (newText[0] == oldText[0]) { newText.shift(); oldText.shift(); fromLine++ } + else { break } + } + + var cutFront = 0, cutEnd = 0 + var newTop = newText[0], oldTop = oldText[0], maxCutFront = Math.min(newTop.length, oldTop.length) + while (cutFront < maxCutFront && newTop.charCodeAt(cutFront) == oldTop.charCodeAt(cutFront)) + { ++cutFront } + var newBot = lst(newText), oldBot = lst(oldText) + var maxCutEnd = Math.min(newBot.length - (newText.length == 1 ? cutFront : 0), + oldBot.length - (oldText.length == 1 ? cutFront : 0)) + while (cutEnd < maxCutEnd && + newBot.charCodeAt(newBot.length - cutEnd - 1) == oldBot.charCodeAt(oldBot.length - cutEnd - 1)) + { ++cutEnd } + // Try to move start of change to start of selection if ambiguous + if (newText.length == 1 && oldText.length == 1 && fromLine == from.line) { + while (cutFront && cutFront > from.ch && + newBot.charCodeAt(newBot.length - cutEnd - 1) == oldBot.charCodeAt(oldBot.length - cutEnd - 1)) { + cutFront-- + cutEnd++ + } + } + + newText[newText.length - 1] = newBot.slice(0, newBot.length - cutEnd).replace(/^\u200b+/, "") + newText[0] = newText[0].slice(cutFront).replace(/\u200b+$/, "") + + var chFrom = Pos(fromLine, cutFront) + var chTo = Pos(toLine, oldText.length ? lst(oldText).length - cutEnd : 0) + if (newText.length > 1 || newText[0] || cmp(chFrom, chTo)) { + replaceRange(cm.doc, newText, chFrom, chTo, "+input") + return true + } + }; + + ContentEditableInput.prototype.ensurePolled = function () { + this.forceCompositionEnd() + }; + ContentEditableInput.prototype.reset = function () { + this.forceCompositionEnd() + }; + ContentEditableInput.prototype.forceCompositionEnd = function () { + if (!this.composing) { return } + clearTimeout(this.readDOMTimeout) + this.composing = null + this.updateFromDOM() + this.div.blur() + this.div.focus() + }; + ContentEditableInput.prototype.readFromDOMSoon = function () { + var this$1 = this; + + if (this.readDOMTimeout != null) { return } + this.readDOMTimeout = setTimeout(function () { + this$1.readDOMTimeout = null + if (this$1.composing) { + if (this$1.composing.done) { this$1.composing = null } + else { return } + } + this$1.updateFromDOM() + }, 80) + }; + + ContentEditableInput.prototype.updateFromDOM = function () { + var this$1 = this; + + if (this.cm.isReadOnly() || !this.pollContent()) + { runInOp(this.cm, function () { return regChange(this$1.cm); }) } + }; + + ContentEditableInput.prototype.setUneditable = function (node) { + node.contentEditable = "false" + }; + + ContentEditableInput.prototype.onKeyPress = function (e) { + if (e.charCode == 0 || this.composing) { return } + e.preventDefault() + if (!this.cm.isReadOnly()) + { operation(this.cm, applyTextInput)(this.cm, String.fromCharCode(e.charCode == null ? e.keyCode : e.charCode), 0) } + }; + + ContentEditableInput.prototype.readOnlyChanged = function (val) { + this.div.contentEditable = String(val != "nocursor") + }; + + ContentEditableInput.prototype.onContextMenu = function () {}; + ContentEditableInput.prototype.resetPosition = function () {}; + + ContentEditableInput.prototype.needsContentAttribute = true + + function posToDOM(cm, pos) { + var view = findViewForLine(cm, pos.line) + if (!view || view.hidden) { return null } + var line = getLine(cm.doc, pos.line) + var info = mapFromLineView(view, line, pos.line) + + var order = getOrder(line, cm.doc.direction), side = "left" + if (order) { + var partPos = getBidiPartAt(order, pos.ch) + side = partPos % 2 ? "right" : "left" + } + var result = nodeAndOffsetInLineMap(info.map, pos.ch, side) + result.offset = result.collapse == "right" ? result.end : result.start + return result + } + + function isInGutter(node) { + for (var scan = node; scan; scan = scan.parentNode) + { if (/CodeMirror-gutter-wrapper/.test(scan.className)) { return true } } + return false + } + + function badPos(pos, bad) { if (bad) { pos.bad = true; } return pos } + + function domTextBetween(cm, from, to, fromLine, toLine) { + var text = "", closing = false, lineSep = cm.doc.lineSeparator() + function recognizeMarker(id) { return function (marker) { return marker.id == id; } } + function close() { + if (closing) { + text += lineSep + closing = false + } + } + function addText(str) { + if (str) { + close() + text += str + } + } + function walk(node) { + if (node.nodeType == 1) { + var cmText = node.getAttribute("cm-text") + if (cmText != null) { + addText(cmText || node.textContent.replace(/\u200b/g, "")) + return + } + var markerID = node.getAttribute("cm-marker"), range + if (markerID) { + var found = cm.findMarks(Pos(fromLine, 0), Pos(toLine + 1, 0), recognizeMarker(+markerID)) + if (found.length && (range = found[0].find(0))) + { addText(getBetween(cm.doc, range.from, range.to).join(lineSep)) } + return + } + if (node.getAttribute("contenteditable") == "false") { return } + var isBlock = /^(pre|div|p)$/i.test(node.nodeName) + if (isBlock) { close() } + for (var i = 0; i < node.childNodes.length; i++) + { walk(node.childNodes[i]) } + if (isBlock) { closing = true } + } else if (node.nodeType == 3) { + addText(node.nodeValue) + } + } + for (;;) { + walk(from) + if (from == to) { break } + from = from.nextSibling + } + return text + } + + function domToPos(cm, node, offset) { + var lineNode + if (node == cm.display.lineDiv) { + lineNode = cm.display.lineDiv.childNodes[offset] + if (!lineNode) { return badPos(cm.clipPos(Pos(cm.display.viewTo - 1)), true) } + node = null; offset = 0 + } else { + for (lineNode = node;; lineNode = lineNode.parentNode) { + if (!lineNode || lineNode == cm.display.lineDiv) { return null } + if (lineNode.parentNode && lineNode.parentNode == cm.display.lineDiv) { break } + } + } + for (var i = 0; i < cm.display.view.length; i++) { + var lineView = cm.display.view[i] + if (lineView.node == lineNode) + { return locateNodeInLineView(lineView, node, offset) } + } + } + + function locateNodeInLineView(lineView, node, offset) { + var wrapper = lineView.text.firstChild, bad = false + if (!node || !contains(wrapper, node)) { return badPos(Pos(lineNo(lineView.line), 0), true) } + if (node == wrapper) { + bad = true + node = wrapper.childNodes[offset] + offset = 0 + if (!node) { + var line = lineView.rest ? lst(lineView.rest) : lineView.line + return badPos(Pos(lineNo(line), line.text.length), bad) + } + } + + var textNode = node.nodeType == 3 ? node : null, topNode = node + if (!textNode && node.childNodes.length == 1 && node.firstChild.nodeType == 3) { + textNode = node.firstChild + if (offset) { offset = textNode.nodeValue.length } + } + while (topNode.parentNode != wrapper) { topNode = topNode.parentNode } + var measure = lineView.measure, maps = measure.maps + + function find(textNode, topNode, offset) { + for (var i = -1; i < (maps ? maps.length : 0); i++) { + var map = i < 0 ? measure.map : maps[i] + for (var j = 0; j < map.length; j += 3) { + var curNode = map[j + 2] + if (curNode == textNode || curNode == topNode) { + var line = lineNo(i < 0 ? lineView.line : lineView.rest[i]) + var ch = map[j] + offset + if (offset < 0 || curNode != textNode) { ch = map[j + (offset ? 1 : 0)] } + return Pos(line, ch) + } + } + } + } + var found = find(textNode, topNode, offset) + if (found) { return badPos(found, bad) } + + // FIXME this is all really shaky. might handle the few cases it needs to handle, but likely to cause problems + for (var after = topNode.nextSibling, dist = textNode ? textNode.nodeValue.length - offset : 0; after; after = after.nextSibling) { + found = find(after, after.firstChild, 0) + if (found) + { return badPos(Pos(found.line, found.ch - dist), bad) } + else + { dist += after.textContent.length } + } + for (var before = topNode.previousSibling, dist$1 = offset; before; before = before.previousSibling) { + found = find(before, before.firstChild, -1) + if (found) + { return badPos(Pos(found.line, found.ch + dist$1), bad) } + else + { dist$1 += before.textContent.length } + } + } + + // TEXTAREA INPUT STYLE + + var TextareaInput = function(cm) { + this.cm = cm + // See input.poll and input.reset + this.prevInput = "" + + // Flag that indicates whether we expect input to appear real soon + // now (after some event like 'keypress' or 'input') and are + // polling intensively. + this.pollingFast = false + // Self-resetting timeout for the poller + this.polling = new Delayed() + // Used to work around IE issue with selection being forgotten when focus moves away from textarea + this.hasSelection = false + this.composing = null + }; + + TextareaInput.prototype.init = function (display) { + var this$1 = this; + + var input = this, cm = this.cm + this.createField(display) + var te = this.textarea + + display.wrapper.insertBefore(this.wrapper, display.wrapper.firstChild) + + // Needed to hide big blue blinking cursor on Mobile Safari (doesn't seem to work in iOS 8 anymore) + if (ios) { te.style.width = "0px" } + + on(te, "input", function () { + if (ie && ie_version >= 9 && this$1.hasSelection) { this$1.hasSelection = null } + input.poll() + }) + + on(te, "paste", function (e) { + if (signalDOMEvent(cm, e) || handlePaste(e, cm)) { return } + + cm.state.pasteIncoming = true + input.fastPoll() + }) + + function prepareCopyCut(e) { + if (signalDOMEvent(cm, e)) { return } + if (cm.somethingSelected()) { + setLastCopied({lineWise: false, text: cm.getSelections()}) + } else if (!cm.options.lineWiseCopyCut) { + return + } else { + var ranges = copyableRanges(cm) + setLastCopied({lineWise: true, text: ranges.text}) + if (e.type == "cut") { + cm.setSelections(ranges.ranges, null, sel_dontScroll) + } else { + input.prevInput = "" + te.value = ranges.text.join("\n") + selectInput(te) + } + } + if (e.type == "cut") { cm.state.cutIncoming = true } + } + on(te, "cut", prepareCopyCut) + on(te, "copy", prepareCopyCut) + + on(display.scroller, "paste", function (e) { + if (eventInWidget(display, e) || signalDOMEvent(cm, e)) { return } + cm.state.pasteIncoming = true + input.focus() + }) + + // Prevent normal selection in the editor (we handle our own) + on(display.lineSpace, "selectstart", function (e) { + if (!eventInWidget(display, e)) { e_preventDefault(e) } + }) + + on(te, "compositionstart", function () { + var start = cm.getCursor("from") + if (input.composing) { input.composing.range.clear() } + input.composing = { + start: start, + range: cm.markText(start, cm.getCursor("to"), {className: "CodeMirror-composing"}) + } + }) + on(te, "compositionend", function () { + if (input.composing) { + input.poll() + input.composing.range.clear() + input.composing = null + } + }) + }; + + TextareaInput.prototype.createField = function (_display) { + // Wraps and hides input textarea + this.wrapper = hiddenTextarea() + // The semihidden textarea that is focused when the editor is + // focused, and receives input. + this.textarea = this.wrapper.firstChild + }; + + TextareaInput.prototype.prepareSelection = function () { + // Redraw the selection and/or cursor + var cm = this.cm, display = cm.display, doc = cm.doc + var result = prepareSelection(cm) + + // Move the hidden textarea near the cursor to prevent scrolling artifacts + if (cm.options.moveInputWithCursor) { + var headPos = cursorCoords(cm, doc.sel.primary().head, "div") + var wrapOff = display.wrapper.getBoundingClientRect(), lineOff = display.lineDiv.getBoundingClientRect() + result.teTop = Math.max(0, Math.min(display.wrapper.clientHeight - 10, + headPos.top + lineOff.top - wrapOff.top)) + result.teLeft = Math.max(0, Math.min(display.wrapper.clientWidth - 10, + headPos.left + lineOff.left - wrapOff.left)) + } + + return result + }; + + TextareaInput.prototype.showSelection = function (drawn) { + var cm = this.cm, display = cm.display + removeChildrenAndAdd(display.cursorDiv, drawn.cursors) + removeChildrenAndAdd(display.selectionDiv, drawn.selection) + if (drawn.teTop != null) { + this.wrapper.style.top = drawn.teTop + "px" + this.wrapper.style.left = drawn.teLeft + "px" + } + }; + + // Reset the input to correspond to the selection (or to be empty, + // when not typing and nothing is selected) + TextareaInput.prototype.reset = function (typing) { + if (this.contextMenuPending || this.composing) { return } + var cm = this.cm + if (cm.somethingSelected()) { + this.prevInput = "" + var content = cm.getSelection() + this.textarea.value = content + if (cm.state.focused) { selectInput(this.textarea) } + if (ie && ie_version >= 9) { this.hasSelection = content } + } else if (!typing) { + this.prevInput = this.textarea.value = "" + if (ie && ie_version >= 9) { this.hasSelection = null } + } + }; + + TextareaInput.prototype.getField = function () { return this.textarea }; + + TextareaInput.prototype.supportsTouch = function () { return false }; + + TextareaInput.prototype.focus = function () { + if (this.cm.options.readOnly != "nocursor" && (!mobile || activeElt() != this.textarea)) { + try { this.textarea.focus() } + catch (e) {} // IE8 will throw if the textarea is display: none or not in DOM + } + }; + + TextareaInput.prototype.blur = function () { this.textarea.blur() }; + + TextareaInput.prototype.resetPosition = function () { + this.wrapper.style.top = this.wrapper.style.left = 0 + }; + + TextareaInput.prototype.receivedFocus = function () { this.slowPoll() }; + + // Poll for input changes, using the normal rate of polling. This + // runs as long as the editor is focused. + TextareaInput.prototype.slowPoll = function () { + var this$1 = this; + + if (this.pollingFast) { return } + this.polling.set(this.cm.options.pollInterval, function () { + this$1.poll() + if (this$1.cm.state.focused) { this$1.slowPoll() } + }) + }; + + // When an event has just come in that is likely to add or change + // something in the input textarea, we poll faster, to ensure that + // the change appears on the screen quickly. + TextareaInput.prototype.fastPoll = function () { + var missed = false, input = this + input.pollingFast = true + function p() { + var changed = input.poll() + if (!changed && !missed) {missed = true; input.polling.set(60, p)} + else {input.pollingFast = false; input.slowPoll()} + } + input.polling.set(20, p) + }; + + // Read input from the textarea, and update the document to match. + // When something is selected, it is present in the textarea, and + // selected (unless it is huge, in which case a placeholder is + // used). When nothing is selected, the cursor sits after previously + // seen text (can be empty), which is stored in prevInput (we must + // not reset the textarea when typing, because that breaks IME). + TextareaInput.prototype.poll = function () { + var this$1 = this; + + var cm = this.cm, input = this.textarea, prevInput = this.prevInput + // Since this is called a *lot*, try to bail out as cheaply as + // possible when it is clear that nothing happened. hasSelection + // will be the case when there is a lot of text in the textarea, + // in which case reading its value would be expensive. + if (this.contextMenuPending || !cm.state.focused || + (hasSelection(input) && !prevInput && !this.composing) || + cm.isReadOnly() || cm.options.disableInput || cm.state.keySeq) + { return false } + + var text = input.value + // If nothing changed, bail. + if (text == prevInput && !cm.somethingSelected()) { return false } + // Work around nonsensical selection resetting in IE9/10, and + // inexplicable appearance of private area unicode characters on + // some key combos in Mac (#2689). + if (ie && ie_version >= 9 && this.hasSelection === text || + mac && /[\uf700-\uf7ff]/.test(text)) { + cm.display.input.reset() + return false + } + + if (cm.doc.sel == cm.display.selForContextMenu) { + var first = text.charCodeAt(0) + if (first == 0x200b && !prevInput) { prevInput = "\u200b" } + if (first == 0x21da) { this.reset(); return this.cm.execCommand("undo") } + } + // Find the part of the input that is actually new + var same = 0, l = Math.min(prevInput.length, text.length) + while (same < l && prevInput.charCodeAt(same) == text.charCodeAt(same)) { ++same } + + runInOp(cm, function () { + applyTextInput(cm, text.slice(same), prevInput.length - same, + null, this$1.composing ? "*compose" : null) + + // Don't leave long text in the textarea, since it makes further polling slow + if (text.length > 1000 || text.indexOf("\n") > -1) { input.value = this$1.prevInput = "" } + else { this$1.prevInput = text } + + if (this$1.composing) { + this$1.composing.range.clear() + this$1.composing.range = cm.markText(this$1.composing.start, cm.getCursor("to"), + {className: "CodeMirror-composing"}) + } + }) + return true + }; + + TextareaInput.prototype.ensurePolled = function () { + if (this.pollingFast && this.poll()) { this.pollingFast = false } + }; + + TextareaInput.prototype.onKeyPress = function () { + if (ie && ie_version >= 9) { this.hasSelection = null } + this.fastPoll() + }; + + TextareaInput.prototype.onContextMenu = function (e) { + var input = this, cm = input.cm, display = cm.display, te = input.textarea + var pos = posFromMouse(cm, e), scrollPos = display.scroller.scrollTop + if (!pos || presto) { return } // Opera is difficult. + + // Reset the current text selection only if the click is done outside of the selection + // and 'resetSelectionOnContextMenu' option is true. + var reset = cm.options.resetSelectionOnContextMenu + if (reset && cm.doc.sel.contains(pos) == -1) + { operation(cm, setSelection)(cm.doc, simpleSelection(pos), sel_dontScroll) } + + var oldCSS = te.style.cssText, oldWrapperCSS = input.wrapper.style.cssText + input.wrapper.style.cssText = "position: absolute" + var wrapperBox = input.wrapper.getBoundingClientRect() + te.style.cssText = "position: absolute; width: 30px; height: 30px;\n top: " + (e.clientY - wrapperBox.top - 5) + "px; left: " + (e.clientX - wrapperBox.left - 5) + "px;\n z-index: 1000; background: " + (ie ? "rgba(255, 255, 255, .05)" : "transparent") + ";\n outline: none; border-width: 0; outline: none; overflow: hidden; opacity: .05; filter: alpha(opacity=5);" + var oldScrollY + if (webkit) { oldScrollY = window.scrollY } // Work around Chrome issue (#2712) + display.input.focus() + if (webkit) { window.scrollTo(null, oldScrollY) } + display.input.reset() + // Adds "Select all" to context menu in FF + if (!cm.somethingSelected()) { te.value = input.prevInput = " " } + input.contextMenuPending = true + display.selForContextMenu = cm.doc.sel + clearTimeout(display.detectingSelectAll) + + // Select-all will be greyed out if there's nothing to select, so + // this adds a zero-width space so that we can later check whether + // it got selected. + function prepareSelectAllHack() { + if (te.selectionStart != null) { + var selected = cm.somethingSelected() + var extval = "\u200b" + (selected ? te.value : "") + te.value = "\u21da" // Used to catch context-menu undo + te.value = extval + input.prevInput = selected ? "" : "\u200b" + te.selectionStart = 1; te.selectionEnd = extval.length + // Re-set this, in case some other handler touched the + // selection in the meantime. + display.selForContextMenu = cm.doc.sel + } + } + function rehide() { + input.contextMenuPending = false + input.wrapper.style.cssText = oldWrapperCSS + te.style.cssText = oldCSS + if (ie && ie_version < 9) { display.scrollbars.setScrollTop(display.scroller.scrollTop = scrollPos) } + + // Try to detect the user choosing select-all + if (te.selectionStart != null) { + if (!ie || (ie && ie_version < 9)) { prepareSelectAllHack() } + var i = 0, poll = function () { + if (display.selForContextMenu == cm.doc.sel && te.selectionStart == 0 && + te.selectionEnd > 0 && input.prevInput == "\u200b") { + operation(cm, selectAll)(cm) + } else if (i++ < 10) { + display.detectingSelectAll = setTimeout(poll, 500) + } else { + display.selForContextMenu = null + display.input.reset() + } + } + display.detectingSelectAll = setTimeout(poll, 200) + } + } + + if (ie && ie_version >= 9) { prepareSelectAllHack() } + if (captureRightClick) { + e_stop(e) + var mouseup = function () { + off(window, "mouseup", mouseup) + setTimeout(rehide, 20) + } + on(window, "mouseup", mouseup) + } else { + setTimeout(rehide, 50) + } + }; + + TextareaInput.prototype.readOnlyChanged = function (val) { + if (!val) { this.reset() } + this.textarea.disabled = val == "nocursor" + }; + + TextareaInput.prototype.setUneditable = function () {}; + + TextareaInput.prototype.needsContentAttribute = false + + function fromTextArea(textarea, options) { + options = options ? copyObj(options) : {} + options.value = textarea.value + if (!options.tabindex && textarea.tabIndex) + { options.tabindex = textarea.tabIndex } + if (!options.placeholder && textarea.placeholder) + { options.placeholder = textarea.placeholder } + // Set autofocus to true if this textarea is focused, or if it has + // autofocus and no other element is focused. + if (options.autofocus == null) { + var hasFocus = activeElt() + options.autofocus = hasFocus == textarea || + textarea.getAttribute("autofocus") != null && hasFocus == document.body + } + + function save() {textarea.value = cm.getValue()} + + var realSubmit + if (textarea.form) { + on(textarea.form, "submit", save) + // Deplorable hack to make the submit method do the right thing. + if (!options.leaveSubmitMethodAlone) { + var form = textarea.form + realSubmit = form.submit + try { + var wrappedSubmit = form.submit = function () { + save() + form.submit = realSubmit + form.submit() + form.submit = wrappedSubmit + } + } catch(e) {} + } + } + + options.finishInit = function (cm) { + cm.save = save + cm.getTextArea = function () { return textarea; } + cm.toTextArea = function () { + cm.toTextArea = isNaN // Prevent this from being ran twice + save() + textarea.parentNode.removeChild(cm.getWrapperElement()) + textarea.style.display = "" + if (textarea.form) { + off(textarea.form, "submit", save) + if (typeof textarea.form.submit == "function") + { textarea.form.submit = realSubmit } + } + } + } + + textarea.style.display = "none" + var cm = CodeMirror(function (node) { return textarea.parentNode.insertBefore(node, textarea.nextSibling); }, + options) + return cm + } + + function addLegacyProps(CodeMirror) { + CodeMirror.off = off + CodeMirror.on = on + CodeMirror.wheelEventPixels = wheelEventPixels + CodeMirror.Doc = Doc + CodeMirror.splitLines = splitLinesAuto + CodeMirror.countColumn = countColumn + CodeMirror.findColumn = findColumn + CodeMirror.isWordChar = isWordCharBasic + CodeMirror.Pass = Pass + CodeMirror.signal = signal + CodeMirror.Line = Line + CodeMirror.changeEnd = changeEnd + CodeMirror.scrollbarModel = scrollbarModel + CodeMirror.Pos = Pos + CodeMirror.cmpPos = cmp + CodeMirror.modes = modes + CodeMirror.mimeModes = mimeModes + CodeMirror.resolveMode = resolveMode + CodeMirror.getMode = getMode + CodeMirror.modeExtensions = modeExtensions + CodeMirror.extendMode = extendMode + CodeMirror.copyState = copyState + CodeMirror.startState = startState + CodeMirror.innerMode = innerMode + CodeMirror.commands = commands + CodeMirror.keyMap = keyMap + CodeMirror.keyName = keyName + CodeMirror.isModifierKey = isModifierKey + CodeMirror.lookupKey = lookupKey + CodeMirror.normalizeKeyMap = normalizeKeyMap + CodeMirror.StringStream = StringStream + CodeMirror.SharedTextMarker = SharedTextMarker + CodeMirror.TextMarker = TextMarker + CodeMirror.LineWidget = LineWidget + CodeMirror.e_preventDefault = e_preventDefault + CodeMirror.e_stopPropagation = e_stopPropagation + CodeMirror.e_stop = e_stop + CodeMirror.addClass = addClass + CodeMirror.contains = contains + CodeMirror.rmClass = rmClass + CodeMirror.keyNames = keyNames + } + + // EDITOR CONSTRUCTOR + + defineOptions(CodeMirror) + + addEditorMethods(CodeMirror) + + // Set up methods on CodeMirror's prototype to redirect to the editor's document. + var dontDelegate = "iter insert remove copy getEditor constructor".split(" ") + for (var prop in Doc.prototype) { if (Doc.prototype.hasOwnProperty(prop) && indexOf(dontDelegate, prop) < 0) + { CodeMirror.prototype[prop] = (function(method) { + return function() {return method.apply(this.doc, arguments)} + })(Doc.prototype[prop]) } } + + eventMixin(Doc) + + // INPUT HANDLING + + CodeMirror.inputStyles = {"textarea": TextareaInput, "contenteditable": ContentEditableInput} + + // MODE DEFINITION AND QUERYING + + // Extra arguments are stored as the mode's dependencies, which is + // used by (legacy) mechanisms like loadmode.js to automatically + // load a mode. (Preferred mechanism is the require/define calls.) + CodeMirror.defineMode = function(name/*, mode, …*/) { + if (!CodeMirror.defaults.mode && name != "null") { CodeMirror.defaults.mode = name } + defineMode.apply(this, arguments) + } + + CodeMirror.defineMIME = defineMIME + + // Minimal default mode. + CodeMirror.defineMode("null", function () { return ({token: function (stream) { return stream.skipToEnd(); }}); }) + CodeMirror.defineMIME("text/plain", "null") + + // EXTENSIONS + + CodeMirror.defineExtension = function (name, func) { + CodeMirror.prototype[name] = func + } + CodeMirror.defineDocExtension = function (name, func) { + Doc.prototype[name] = func + } + + CodeMirror.fromTextArea = fromTextArea + + addLegacyProps(CodeMirror) + + CodeMirror.version = "5.37.0" + + return CodeMirror; + + }))); + +/***/ }), +/* 3 */ +/***/ (function(module, exports, __webpack_require__) { + + // CodeMirror, copyright (c) by Marijn Haverbeke and others + // Distributed under an MIT license: http://codemirror.net/LICENSE + + (function(mod) { + if (true) // CommonJS + mod(__webpack_require__(2)) + else if (typeof define == "function" && define.amd) // AMD + define(["../../lib/codemirror"], mod) + else // Plain browser env + mod(CodeMirror) + })(function(CodeMirror) { + "use strict" + var Pos = CodeMirror.Pos + + function regexpFlags(regexp) { + var flags = regexp.flags + return flags != null ? flags : (regexp.ignoreCase ? "i" : "") + + (regexp.global ? "g" : "") + + (regexp.multiline ? "m" : "") + } + + function ensureFlags(regexp, flags) { + var current = regexpFlags(regexp), target = current + for (var i = 0; i < flags.length; i++) if (target.indexOf(flags.charAt(i)) == -1) + target += flags.charAt(i) + return current == target ? regexp : new RegExp(regexp.source, target) + } + + function maybeMultiline(regexp) { + return /\\s|\\n|\n|\\W|\\D|\[\^/.test(regexp.source) + } + + function searchRegexpForward(doc, regexp, start) { + regexp = ensureFlags(regexp, "g") + for (var line = start.line, ch = start.ch, last = doc.lastLine(); line <= last; line++, ch = 0) { + regexp.lastIndex = ch + var string = doc.getLine(line), match = regexp.exec(string) + if (match) + return {from: Pos(line, match.index), + to: Pos(line, match.index + match[0].length), + match: match} + } + } + + function searchRegexpForwardMultiline(doc, regexp, start) { + if (!maybeMultiline(regexp)) return searchRegexpForward(doc, regexp, start) + + regexp = ensureFlags(regexp, "gm") + var string, chunk = 1 + for (var line = start.line, last = doc.lastLine(); line <= last;) { + // This grows the search buffer in exponentially-sized chunks + // between matches, so that nearby matches are fast and don't + // require concatenating the whole document (in case we're + // searching for something that has tons of matches), but at the + // same time, the amount of retries is limited. + for (var i = 0; i < chunk; i++) { + if (line > last) break + var curLine = doc.getLine(line++) + string = string == null ? curLine : string + "\n" + curLine + } + chunk = chunk * 2 + regexp.lastIndex = start.ch + var match = regexp.exec(string) + if (match) { + var before = string.slice(0, match.index).split("\n"), inside = match[0].split("\n") + var startLine = start.line + before.length - 1, startCh = before[before.length - 1].length + return {from: Pos(startLine, startCh), + to: Pos(startLine + inside.length - 1, + inside.length == 1 ? startCh + inside[0].length : inside[inside.length - 1].length), + match: match} + } + } + } + + function lastMatchIn(string, regexp) { + var cutOff = 0, match + for (;;) { + regexp.lastIndex = cutOff + var newMatch = regexp.exec(string) + if (!newMatch) return match + match = newMatch + cutOff = match.index + (match[0].length || 1) + if (cutOff == string.length) return match + } + } + + function searchRegexpBackward(doc, regexp, start) { + regexp = ensureFlags(regexp, "g") + for (var line = start.line, ch = start.ch, first = doc.firstLine(); line >= first; line--, ch = -1) { + var string = doc.getLine(line) + if (ch > -1) string = string.slice(0, ch) + var match = lastMatchIn(string, regexp) + if (match) + return {from: Pos(line, match.index), + to: Pos(line, match.index + match[0].length), + match: match} + } + } + + function searchRegexpBackwardMultiline(doc, regexp, start) { + regexp = ensureFlags(regexp, "gm") + var string, chunk = 1 + for (var line = start.line, first = doc.firstLine(); line >= first;) { + for (var i = 0; i < chunk; i++) { + var curLine = doc.getLine(line--) + string = string == null ? curLine.slice(0, start.ch) : curLine + "\n" + string + } + chunk *= 2 + + var match = lastMatchIn(string, regexp) + if (match) { + var before = string.slice(0, match.index).split("\n"), inside = match[0].split("\n") + var startLine = line + before.length, startCh = before[before.length - 1].length + return {from: Pos(startLine, startCh), + to: Pos(startLine + inside.length - 1, + inside.length == 1 ? startCh + inside[0].length : inside[inside.length - 1].length), + match: match} + } + } + } + + var doFold, noFold + if (String.prototype.normalize) { + doFold = function(str) { return str.normalize("NFD").toLowerCase() } + noFold = function(str) { return str.normalize("NFD") } + } else { + doFold = function(str) { return str.toLowerCase() } + noFold = function(str) { return str } + } + + // Maps a position in a case-folded line back to a position in the original line + // (compensating for codepoints increasing in number during folding) + function adjustPos(orig, folded, pos, foldFunc) { + if (orig.length == folded.length) return pos + for (var min = 0, max = pos + Math.max(0, orig.length - folded.length);;) { + if (min == max) return min + var mid = (min + max) >> 1 + var len = foldFunc(orig.slice(0, mid)).length + if (len == pos) return mid + else if (len > pos) max = mid + else min = mid + 1 + } + } + + function searchStringForward(doc, query, start, caseFold) { + // Empty string would match anything and never progress, so we + // define it to match nothing instead. + if (!query.length) return null + var fold = caseFold ? doFold : noFold + var lines = fold(query).split(/\r|\n\r?/) + + search: for (var line = start.line, ch = start.ch, last = doc.lastLine() + 1 - lines.length; line <= last; line++, ch = 0) { + var orig = doc.getLine(line).slice(ch), string = fold(orig) + if (lines.length == 1) { + var found = string.indexOf(lines[0]) + if (found == -1) continue search + var start = adjustPos(orig, string, found, fold) + ch + return {from: Pos(line, adjustPos(orig, string, found, fold) + ch), + to: Pos(line, adjustPos(orig, string, found + lines[0].length, fold) + ch)} + } else { + var cutFrom = string.length - lines[0].length + if (string.slice(cutFrom) != lines[0]) continue search + for (var i = 1; i < lines.length - 1; i++) + if (fold(doc.getLine(line + i)) != lines[i]) continue search + var end = doc.getLine(line + lines.length - 1), endString = fold(end), lastLine = lines[lines.length - 1] + if (endString.slice(0, lastLine.length) != lastLine) continue search + return {from: Pos(line, adjustPos(orig, string, cutFrom, fold) + ch), + to: Pos(line + lines.length - 1, adjustPos(end, endString, lastLine.length, fold))} + } + } + } + + function searchStringBackward(doc, query, start, caseFold) { + if (!query.length) return null + var fold = caseFold ? doFold : noFold + var lines = fold(query).split(/\r|\n\r?/) + + search: for (var line = start.line, ch = start.ch, first = doc.firstLine() - 1 + lines.length; line >= first; line--, ch = -1) { + var orig = doc.getLine(line) + if (ch > -1) orig = orig.slice(0, ch) + var string = fold(orig) + if (lines.length == 1) { + var found = string.lastIndexOf(lines[0]) + if (found == -1) continue search + return {from: Pos(line, adjustPos(orig, string, found, fold)), + to: Pos(line, adjustPos(orig, string, found + lines[0].length, fold))} + } else { + var lastLine = lines[lines.length - 1] + if (string.slice(0, lastLine.length) != lastLine) continue search + for (var i = 1, start = line - lines.length + 1; i < lines.length - 1; i++) + if (fold(doc.getLine(start + i)) != lines[i]) continue search + var top = doc.getLine(line + 1 - lines.length), topString = fold(top) + if (topString.slice(topString.length - lines[0].length) != lines[0]) continue search + return {from: Pos(line + 1 - lines.length, adjustPos(top, topString, top.length - lines[0].length, fold)), + to: Pos(line, adjustPos(orig, string, lastLine.length, fold))} + } + } + } + + function SearchCursor(doc, query, pos, options) { + this.atOccurrence = false + this.doc = doc + pos = pos ? doc.clipPos(pos) : Pos(0, 0) + this.pos = {from: pos, to: pos} + + var caseFold + if (typeof options == "object") { + caseFold = options.caseFold + } else { // Backwards compat for when caseFold was the 4th argument + caseFold = options + options = null + } + + if (typeof query == "string") { + if (caseFold == null) caseFold = false + this.matches = function(reverse, pos) { + return (reverse ? searchStringBackward : searchStringForward)(doc, query, pos, caseFold) + } + } else { + query = ensureFlags(query, "gm") + if (!options || options.multiline !== false) + this.matches = function(reverse, pos) { + return (reverse ? searchRegexpBackwardMultiline : searchRegexpForwardMultiline)(doc, query, pos) + } + else + this.matches = function(reverse, pos) { + return (reverse ? searchRegexpBackward : searchRegexpForward)(doc, query, pos) + } + } + } + + SearchCursor.prototype = { + findNext: function() {return this.find(false)}, + findPrevious: function() {return this.find(true)}, + + find: function(reverse) { + var result = this.matches(reverse, this.doc.clipPos(reverse ? this.pos.from : this.pos.to)) + + // Implements weird auto-growing behavior on null-matches for + // backwards-compatiblity with the vim code (unfortunately) + while (result && CodeMirror.cmpPos(result.from, result.to) == 0) { + if (reverse) { + if (result.from.ch) result.from = Pos(result.from.line, result.from.ch - 1) + else if (result.from.line == this.doc.firstLine()) result = null + else result = this.matches(reverse, this.doc.clipPos(Pos(result.from.line - 1))) + } else { + if (result.to.ch < this.doc.getLine(result.to.line).length) result.to = Pos(result.to.line, result.to.ch + 1) + else if (result.to.line == this.doc.lastLine()) result = null + else result = this.matches(reverse, Pos(result.to.line + 1, 0)) + } + } + + if (result) { + this.pos = result + this.atOccurrence = true + return this.pos.match || true + } else { + var end = Pos(reverse ? this.doc.firstLine() : this.doc.lastLine() + 1, 0) + this.pos = {from: end, to: end} + return this.atOccurrence = false + } + }, + + from: function() {if (this.atOccurrence) return this.pos.from}, + to: function() {if (this.atOccurrence) return this.pos.to}, + + replace: function(newText, origin) { + if (!this.atOccurrence) return + var lines = CodeMirror.splitLines(newText) + this.doc.replaceRange(lines, this.pos.from, this.pos.to, origin) + this.pos.to = Pos(this.pos.from.line + lines.length - 1, + lines[lines.length - 1].length + (lines.length == 1 ? this.pos.from.ch : 0)) + } + } + + CodeMirror.defineExtension("getSearchCursor", function(query, pos, caseFold) { + return new SearchCursor(this.doc, query, pos, caseFold) + }) + CodeMirror.defineDocExtension("getSearchCursor", function(query, pos, caseFold) { + return new SearchCursor(this, query, pos, caseFold) + }) + + CodeMirror.defineExtension("selectMatches", function(query, caseFold) { + var ranges = [] + var cur = this.getSearchCursor(query, this.getCursor("from"), caseFold) + while (cur.findNext()) { + if (CodeMirror.cmpPos(cur.to(), this.getCursor("to")) > 0) break + ranges.push({anchor: cur.from(), head: cur.to()}) + } + if (ranges.length) + this.setSelections(ranges, 0) + }) + }); + + +/***/ }), +/* 4 */ +/***/ (function(module, exports, __webpack_require__) { + + // CodeMirror, copyright (c) by Marijn Haverbeke and others + // Distributed under an MIT license: http://codemirror.net/LICENSE + + // Define search commands. Depends on dialog.js or another + // implementation of the openDialog method. + + // Replace works a little oddly -- it will do the replace on the next + // Ctrl-G (or whatever is bound to findNext) press. You prevent a + // replace by making sure the match is no longer selected when hitting + // Ctrl-G. + + (function(mod) { + if (true) // CommonJS + mod(__webpack_require__(2), __webpack_require__(3), __webpack_require__(1)); + else if (typeof define == "function" && define.amd) // AMD + define(["../../lib/codemirror", "./searchcursor", "../dialog/dialog"], mod); + else // Plain browser env + mod(CodeMirror); + })(function(CodeMirror) { + "use strict"; + + function searchOverlay(query, caseInsensitive) { + if (typeof query == "string") + query = new RegExp(query.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g, "\\$&"), caseInsensitive ? "gi" : "g"); + else if (!query.global) + query = new RegExp(query.source, query.ignoreCase ? "gi" : "g"); + + return {token: function(stream) { + query.lastIndex = stream.pos; + var match = query.exec(stream.string); + if (match && match.index == stream.pos) { + stream.pos += match[0].length || 1; + return "searching"; + } else if (match) { + stream.pos = match.index; + } else { + stream.skipToEnd(); + } + }}; + } + + function SearchState() { + this.posFrom = this.posTo = this.lastQuery = this.query = null; + this.overlay = null; + } + + function getSearchState(cm) { + return cm.state.search || (cm.state.search = new SearchState()); + } + + function queryCaseInsensitive(query) { + return typeof query == "string" && query == query.toLowerCase(); + } + + function getSearchCursor(cm, query, pos) { + // Heuristic: if the query string is all lowercase, do a case insensitive search. + return cm.getSearchCursor(query, pos, {caseFold: queryCaseInsensitive(query), multiline: true}); + } + + function persistentDialog(cm, text, deflt, onEnter, onKeyDown) { + cm.openDialog(text, onEnter, { + value: deflt, + selectValueOnOpen: true, + closeOnEnter: false, + onClose: function() { clearSearch(cm); }, + onKeyDown: onKeyDown + }); + } + + function dialog(cm, text, shortText, deflt, f) { + if (cm.openDialog) cm.openDialog(text, f, {value: deflt, selectValueOnOpen: true}); + else f(prompt(shortText, deflt)); + } + + function confirmDialog(cm, text, shortText, fs) { + if (cm.openConfirm) cm.openConfirm(text, fs); + else if (confirm(shortText)) fs[0](); + } + + function parseString(string) { + return string.replace(/\\(.)/g, function(_, ch) { + if (ch == "n") return "\n" + if (ch == "r") return "\r" + return ch + }) + } + + function parseQuery(query) { + var isRE = query.match(/^\/(.*)\/([a-z]*)$/); + if (isRE) { + try { query = new RegExp(isRE[1], isRE[2].indexOf("i") == -1 ? "" : "i"); } + catch(e) {} // Not a regular expression after all, do a string search + } else { + query = parseString(query) + } + if (typeof query == "string" ? query == "" : query.test("")) + query = /x^/; + return query; + } + + var queryDialog; + + function startSearch(cm, state, query) { + state.queryText = query; + state.query = parseQuery(query); + cm.removeOverlay(state.overlay, queryCaseInsensitive(state.query)); + state.overlay = searchOverlay(state.query, queryCaseInsensitive(state.query)); + cm.addOverlay(state.overlay); + if (cm.showMatchesOnScrollbar) { + if (state.annotate) { state.annotate.clear(); state.annotate = null; } + state.annotate = cm.showMatchesOnScrollbar(state.query, queryCaseInsensitive(state.query)); + } + } + + function doSearch(cm, rev, persistent, immediate) { + if (!queryDialog) { + let doc = cm.getWrapperElement().ownerDocument; + let inp = doc.createElement("input"); + + inp.type = "search"; + inp.placeholder = cm.l10n("findCmd.promptMessage"); + inp.style.marginInlineStart = "1em"; + inp.style.marginInlineEnd = "1em"; + inp.style.flexGrow = "1"; + inp.addEventListener("focus", () => inp.select()); + + queryDialog = doc.createElement("div"); + queryDialog.appendChild(inp); + queryDialog.style.display = "flex"; + } + + var state = getSearchState(cm); + if (state.query) return findNext(cm, rev); + var q = cm.getSelection() || state.lastQuery; + if (q instanceof RegExp && q.source == "x^") q = null + if (persistent && cm.openDialog) { + var hiding = null + var searchNext = function(query, event) { + CodeMirror.e_stop(event); + if (!query) return; + if (query != state.queryText) { + startSearch(cm, state, query); + state.posFrom = state.posTo = cm.getCursor(); + } + if (hiding) hiding.style.opacity = 1 + findNext(cm, event.shiftKey, function(_, to) { + var dialog + if (to.line < 3 && document.querySelector && + (dialog = cm.display.wrapper.querySelector(".CodeMirror-dialog")) && + dialog.getBoundingClientRect().bottom - 4 > cm.cursorCoords(to, "window").top) + (hiding = dialog).style.opacity = .4 + }) + }; + persistentDialog(cm, queryDialog, q, searchNext, function(event, query) { + var keyName = CodeMirror.keyName(event) + var extra = cm.getOption('extraKeys'), cmd = (extra && extra[keyName]) || CodeMirror.keyMap[cm.getOption("keyMap")][keyName] + if (cmd == "findNext" || cmd == "findPrev" || + cmd == "findPersistentNext" || cmd == "findPersistentPrev") { + CodeMirror.e_stop(event); + startSearch(cm, getSearchState(cm), query); + cm.execCommand(cmd); + } else if (cmd == "find" || cmd == "findPersistent") { + CodeMirror.e_stop(event); + searchNext(query, event); + } + }); + if (immediate && q) { + startSearch(cm, state, q); + findNext(cm, rev); + } + } else { + dialog(cm, queryDialog, "Search for:", q, function(query) { + if (query && !state.query) cm.operation(function() { + startSearch(cm, state, query); + state.posFrom = state.posTo = cm.getCursor(); + findNext(cm, rev); + }); + }); + } + } + + function findNext(cm, rev, callback) {cm.operation(function() { + var state = getSearchState(cm); + var cursor = getSearchCursor(cm, state.query, rev ? state.posFrom : state.posTo); + if (!cursor.find(rev)) { + cursor = getSearchCursor(cm, state.query, rev ? CodeMirror.Pos(cm.lastLine()) : CodeMirror.Pos(cm.firstLine(), 0)); + if (!cursor.find(rev)) return; + } + cm.setSelection(cursor.from(), cursor.to()); + cm.scrollIntoView({from: cursor.from(), to: cursor.to()}, 20); + state.posFrom = cursor.from(); state.posTo = cursor.to(); + if (callback) callback(cursor.from(), cursor.to()) + });} + + function clearSearch(cm) {cm.operation(function() { + var state = getSearchState(cm); + state.lastQuery = state.query; + if (!state.query) return; + state.query = state.queryText = null; + cm.removeOverlay(state.overlay); + if (state.annotate) { state.annotate.clear(); state.annotate = null; } + });} + + function replaceAll(cm, query, text) { + cm.operation(function() { + for (var cursor = getSearchCursor(cm, query); cursor.findNext();) { + if (typeof query != "string") { + var match = cm.getRange(cursor.from(), cursor.to()).match(query); + cursor.replace(text.replace(/\$(\d)/g, function(_, i) {return match[i];})); + } else cursor.replace(text); + } + }); + } + + function replace(cm, all) { + if (cm.getOption("readOnly")) return; + var query = cm.getSelection() || getSearchState(cm).lastQuery; + + let doc = cm.getWrapperElement().ownerDocument; + + // `searchLabel` is used as part of `replaceQueryFragment` and as a separate + // argument by itself, so it should be cloned. + let searchLabel = doc.createElement("span"); + searchLabel.classList.add("CodeMirror-search-label"); + searchLabel.textContent = all ? "Replace all:" : "Replace:"; + + let replaceQueryFragment = doc.createDocumentFragment(); + replaceQueryFragment.appendChild(searchLabel.cloneNode(true)); + + let searchField = doc.createElement("input"); + searchField.setAttribute("type", "text"); + searchField.setAttribute("style", "width: 10em"); + searchField.classList.add("CodeMirror-search-field"); + replaceQueryFragment.appendChild(searchField); + + let searchHint = doc.createElement("span"); + searchHint.setAttribute("style", "color: #888"); + searchHint.classList.add("CodeMirror-search-hint"); + searchHint.textContent = "(Use /re/ syntax for regexp search)"; + replaceQueryFragment.appendChild(searchHint); + + dialog(cm, replaceQueryFragment, searchLabel, query, function(query) { + if (!query) return; + query = parseQuery(query); + + let replacementQueryFragment = doc.createDocumentFragment(); + + let replaceWithLabel = searchLabel.cloneNode(false); + replaceWithLabel.textContent = "With:"; + replacementQueryFragment.appendChild(replaceWithLabel); + + let replaceField = doc.createElement("input"); + replaceField.setAttribute("type", "text"); + replaceField.setAttribute("style", "width: 10em"); + replaceField.classList.add("CodeMirror-search-field"); + replacementQueryFragment.appendChild(replaceField); + + dialog(cm, replacementQueryFragment, "Replace with:", "", function(text) { + text = parseString(text) + if (all) { + replaceAll(cm, query, text) + } else { + clearSearch(cm); + var cursor = getSearchCursor(cm, query, cm.getCursor("from")); + var advance = function() { + var start = cursor.from(), match; + if (!(match = cursor.findNext())) { + cursor = getSearchCursor(cm, query); + if (!(match = cursor.findNext()) || + (start && cursor.from().line == start.line && cursor.from().ch == start.ch)) return; + } + cm.setSelection(cursor.from(), cursor.to()); + cm.scrollIntoView({ from: cursor.from(), to: cursor.to() }); + + let replaceConfirmFragment = doc.createDocumentFragment(); + + let replaceConfirmLabel = searchLabel.cloneNode(false); + replaceConfirmLabel.textContent = "Replace?"; + replaceConfirmFragment.appendChild(replaceConfirmLabel); + + let yesButton = doc.createElement("button"); + yesButton.textContent = "Yes"; + replaceConfirmFragment.appendChild(yesButton); + + let noButton = doc.createElement("button"); + noButton.textContent = "No"; + replaceConfirmFragment.appendChild(noButton); + + let allButton = doc.createElement("button"); + allButton.textContent = "All"; + replaceConfirmFragment.appendChild(allButton); + + let stopButton = doc.createElement("button"); + stopButton.textContent = "Stop"; + replaceConfirmFragment.appendChild(stopButton); + + confirmDialog(cm, replaceConfirmFragment, "Replace?", + [function() {doReplace(match);}, advance, + function() {replaceAll(cm, query, text)}]); + }; + var doReplace = function(match) { + cursor.replace(typeof query == "string" ? text : + text.replace(/\$(\d)/g, function(_, i) {return match[i];})); + advance(); + }; + advance(); + } + }); + }); + } + + CodeMirror.commands.find = function(cm) {clearSearch(cm); doSearch(cm);}; + CodeMirror.commands.findPersistent = function(cm) {clearSearch(cm); doSearch(cm, false, true);}; + CodeMirror.commands.findPersistentNext = function(cm) {doSearch(cm, false, true, true);}; + CodeMirror.commands.findPersistentPrev = function(cm) {doSearch(cm, true, true, true);}; + CodeMirror.commands.findNext = doSearch; + CodeMirror.commands.findPrev = function(cm) {doSearch(cm, true);}; + CodeMirror.commands.clearSearch = clearSearch; + CodeMirror.commands.replace = replace; + CodeMirror.commands.replaceAll = function(cm) {replace(cm, true);}; + }); + + +/***/ }), +/* 5 */ +/***/ (function(module, exports, __webpack_require__) { + + // CodeMirror, copyright (c) by Marijn Haverbeke and others + // Distributed under an MIT license: http://codemirror.net/LICENSE + + (function(mod) { + if (true) // CommonJS + mod(__webpack_require__(2)); + else if (typeof define == "function" && define.amd) // AMD + define(["../../lib/codemirror"], mod); + else // Plain browser env + mod(CodeMirror); + })(function(CodeMirror) { + var ie_lt8 = /MSIE \d/.test(navigator.userAgent) && + (document.documentMode == null || document.documentMode < 8); + + var Pos = CodeMirror.Pos; + + var matching = {"(": ")>", ")": "(<", "[": "]>", "]": "[<", "{": "}>", "}": "{<"}; + + function findMatchingBracket(cm, where, config) { + var line = cm.getLineHandle(where.line), pos = where.ch - 1; + var afterCursor = config && config.afterCursor + if (afterCursor == null) + afterCursor = /(^| )cm-fat-cursor($| )/.test(cm.getWrapperElement().className) + + // A cursor is defined as between two characters, but in in vim command mode + // (i.e. not insert mode), the cursor is visually represented as a + // highlighted box on top of the 2nd character. Otherwise, we allow matches + // from before or after the cursor. + var match = (!afterCursor && pos >= 0 && matching[line.text.charAt(pos)]) || + matching[line.text.charAt(++pos)]; + if (!match) return null; + var dir = match.charAt(1) == ">" ? 1 : -1; + if (config && config.strict && (dir > 0) != (pos == where.ch)) return null; + var style = cm.getTokenTypeAt(Pos(where.line, pos + 1)); + + var found = scanForBracket(cm, Pos(where.line, pos + (dir > 0 ? 1 : 0)), dir, style || null, config); + if (found == null) return null; + return {from: Pos(where.line, pos), to: found && found.pos, + match: found && found.ch == match.charAt(0), forward: dir > 0}; + } + + // bracketRegex is used to specify which type of bracket to scan + // should be a regexp, e.g. /[[\]]/ + // + // Note: If "where" is on an open bracket, then this bracket is ignored. + // + // Returns false when no bracket was found, null when it reached + // maxScanLines and gave up + function scanForBracket(cm, where, dir, style, config) { + var maxScanLen = (config && config.maxScanLineLength) || 10000; + var maxScanLines = (config && config.maxScanLines) || 1000; + + var stack = []; + var re = config && config.bracketRegex ? config.bracketRegex : /[(){}[\]]/; + var lineEnd = dir > 0 ? Math.min(where.line + maxScanLines, cm.lastLine() + 1) + : Math.max(cm.firstLine() - 1, where.line - maxScanLines); + for (var lineNo = where.line; lineNo != lineEnd; lineNo += dir) { + var line = cm.getLine(lineNo); + if (!line) continue; + var pos = dir > 0 ? 0 : line.length - 1, end = dir > 0 ? line.length : -1; + if (line.length > maxScanLen) continue; + if (lineNo == where.line) pos = where.ch - (dir < 0 ? 1 : 0); + for (; pos != end; pos += dir) { + var ch = line.charAt(pos); + if (re.test(ch) && (style === undefined || cm.getTokenTypeAt(Pos(lineNo, pos + 1)) == style)) { + var match = matching[ch]; + if ((match.charAt(1) == ">") == (dir > 0)) stack.push(ch); + else if (!stack.length) return {pos: Pos(lineNo, pos), ch: ch}; + else stack.pop(); + } + } + } + return lineNo - dir == (dir > 0 ? cm.lastLine() : cm.firstLine()) ? false : null; + } + + function matchBrackets(cm, autoclear, config) { + // Disable brace matching in long lines, since it'll cause hugely slow updates + var maxHighlightLen = cm.state.matchBrackets.maxHighlightLineLength || 1000; + var marks = [], ranges = cm.listSelections(); + for (var i = 0; i < ranges.length; i++) { + var match = ranges[i].empty() && findMatchingBracket(cm, ranges[i].head, config); + if (match && cm.getLine(match.from.line).length <= maxHighlightLen) { + var style = match.match ? "CodeMirror-matchingbracket" : "CodeMirror-nonmatchingbracket"; + marks.push(cm.markText(match.from, Pos(match.from.line, match.from.ch + 1), {className: style})); + if (match.to && cm.getLine(match.to.line).length <= maxHighlightLen) + marks.push(cm.markText(match.to, Pos(match.to.line, match.to.ch + 1), {className: style})); + } + } + + if (marks.length) { + // Kludge to work around the IE bug from issue #1193, where text + // input stops going to the textare whever this fires. + if (ie_lt8 && cm.state.focused) cm.focus(); + + var clear = function() { + cm.operation(function() { + for (var i = 0; i < marks.length; i++) marks[i].clear(); + }); + }; + if (autoclear) setTimeout(clear, 800); + else return clear; + } + } + + function doMatchBrackets(cm) { + cm.operation(function() { + if (cm.state.matchBrackets.currentlyHighlighted) { + cm.state.matchBrackets.currentlyHighlighted(); + cm.state.matchBrackets.currentlyHighlighted = null; + } + cm.state.matchBrackets.currentlyHighlighted = matchBrackets(cm, false, cm.state.matchBrackets); + }); + } + + CodeMirror.defineOption("matchBrackets", false, function(cm, val, old) { + if (old && old != CodeMirror.Init) { + cm.off("cursorActivity", doMatchBrackets); + if (cm.state.matchBrackets && cm.state.matchBrackets.currentlyHighlighted) { + cm.state.matchBrackets.currentlyHighlighted(); + cm.state.matchBrackets.currentlyHighlighted = null; + } + } + if (val) { + cm.state.matchBrackets = typeof val == "object" ? val : {}; + cm.on("cursorActivity", doMatchBrackets); + } + }); + + CodeMirror.defineExtension("matchBrackets", function() {matchBrackets(this, true);}); + CodeMirror.defineExtension("findMatchingBracket", function(pos, config, oldConfig){ + // Backwards-compatibility kludge + if (oldConfig || typeof config == "boolean") { + if (!oldConfig) { + config = config ? {strict: true} : null + } else { + oldConfig.strict = config + config = oldConfig + } + } + return findMatchingBracket(this, pos, config) + }); + CodeMirror.defineExtension("scanForBracket", function(pos, dir, style, config){ + return scanForBracket(this, pos, dir, style, config); + }); + }); + + +/***/ }), +/* 6 */ +/***/ (function(module, exports, __webpack_require__) { + + // CodeMirror, copyright (c) by Marijn Haverbeke and others + // Distributed under an MIT license: http://codemirror.net/LICENSE + + (function(mod) { + if (true) // CommonJS + mod(__webpack_require__(2)); + else if (typeof define == "function" && define.amd) // AMD + define(["../../lib/codemirror"], mod); + else // Plain browser env + mod(CodeMirror); + })(function(CodeMirror) { + var defaults = { + pairs: "()[]{}''\"\"", + triples: "", + explode: "[]{}" + }; + + var Pos = CodeMirror.Pos; + + CodeMirror.defineOption("autoCloseBrackets", false, function(cm, val, old) { + if (old && old != CodeMirror.Init) { + cm.removeKeyMap(keyMap); + cm.state.closeBrackets = null; + } + if (val) { + ensureBound(getOption(val, "pairs")) + cm.state.closeBrackets = val; + cm.addKeyMap(keyMap); + } + }); + + function getOption(conf, name) { + if (name == "pairs" && typeof conf == "string") return conf; + if (typeof conf == "object" && conf[name] != null) return conf[name]; + return defaults[name]; + } + + var keyMap = {Backspace: handleBackspace, Enter: handleEnter}; + function ensureBound(chars) { + for (var i = 0; i < chars.length; i++) { + var ch = chars.charAt(i), key = "'" + ch + "'" + if (!keyMap[key]) keyMap[key] = handler(ch) + } + } + ensureBound(defaults.pairs + "`") + + function handler(ch) { + return function(cm) { return handleChar(cm, ch); }; + } + + function getConfig(cm) { + var deflt = cm.state.closeBrackets; + if (!deflt || deflt.override) return deflt; + var mode = cm.getModeAt(cm.getCursor()); + return mode.closeBrackets || deflt; + } + + function handleBackspace(cm) { + var conf = getConfig(cm); + if (!conf || cm.getOption("disableInput")) return CodeMirror.Pass; + + var pairs = getOption(conf, "pairs"); + var ranges = cm.listSelections(); + for (var i = 0; i < ranges.length; i++) { + if (!ranges[i].empty()) return CodeMirror.Pass; + var around = charsAround(cm, ranges[i].head); + if (!around || pairs.indexOf(around) % 2 != 0) return CodeMirror.Pass; + } + for (var i = ranges.length - 1; i >= 0; i--) { + var cur = ranges[i].head; + cm.replaceRange("", Pos(cur.line, cur.ch - 1), Pos(cur.line, cur.ch + 1), "+delete"); + } + } + + function handleEnter(cm) { + var conf = getConfig(cm); + var explode = conf && getOption(conf, "explode"); + if (!explode || cm.getOption("disableInput")) return CodeMirror.Pass; + + var ranges = cm.listSelections(); + for (var i = 0; i < ranges.length; i++) { + if (!ranges[i].empty()) return CodeMirror.Pass; + var around = charsAround(cm, ranges[i].head); + if (!around || explode.indexOf(around) % 2 != 0) return CodeMirror.Pass; + } + cm.operation(function() { + var linesep = cm.lineSeparator() || "\n"; + cm.replaceSelection(linesep + linesep, null); + cm.execCommand("goCharLeft"); + ranges = cm.listSelections(); + for (var i = 0; i < ranges.length; i++) { + var line = ranges[i].head.line; + cm.indentLine(line, null, true); + cm.indentLine(line + 1, null, true); + } + }); + } + + function contractSelection(sel) { + var inverted = CodeMirror.cmpPos(sel.anchor, sel.head) > 0; + return {anchor: new Pos(sel.anchor.line, sel.anchor.ch + (inverted ? -1 : 1)), + head: new Pos(sel.head.line, sel.head.ch + (inverted ? 1 : -1))}; + } + + function handleChar(cm, ch) { + var conf = getConfig(cm); + if (!conf || cm.getOption("disableInput")) return CodeMirror.Pass; + + var pairs = getOption(conf, "pairs"); + var pos = pairs.indexOf(ch); + if (pos == -1) return CodeMirror.Pass; + var triples = getOption(conf, "triples"); + + var identical = pairs.charAt(pos + 1) == ch; + var ranges = cm.listSelections(); + var opening = pos % 2 == 0; + + var type; + for (var i = 0; i < ranges.length; i++) { + var range = ranges[i], cur = range.head, curType; + var next = cm.getRange(cur, Pos(cur.line, cur.ch + 1)); + if (opening && !range.empty()) { + curType = "surround"; + } else if ((identical || !opening) && next == ch) { + if (identical && stringStartsAfter(cm, cur)) + curType = "both"; + else if (triples.indexOf(ch) >= 0 && cm.getRange(cur, Pos(cur.line, cur.ch + 3)) == ch + ch + ch) + curType = "skipThree"; + else + curType = "skip"; + } else if (identical && cur.ch > 1 && triples.indexOf(ch) >= 0 && + cm.getRange(Pos(cur.line, cur.ch - 2), cur) == ch + ch) { + if (cur.ch > 2 && /\bstring/.test(cm.getTokenTypeAt(Pos(cur.line, cur.ch - 2)))) return CodeMirror.Pass; + curType = "addFour"; + } else if (identical) { + var prev = cur.ch == 0 ? " " : cm.getRange(Pos(cur.line, cur.ch - 1), cur) + if (!CodeMirror.isWordChar(next) && prev != ch && !CodeMirror.isWordChar(prev)) curType = "both"; + else return CodeMirror.Pass; + } else if (opening && (cm.getLine(cur.line).length == cur.ch || + isClosingBracket(next, pairs) || + /\s/.test(next))) { + curType = "both"; + } else { + return CodeMirror.Pass; + } + if (!type) type = curType; + else if (type != curType) return CodeMirror.Pass; + } + + var left = pos % 2 ? pairs.charAt(pos - 1) : ch; + var right = pos % 2 ? ch : pairs.charAt(pos + 1); + cm.operation(function() { + if (type == "skip") { + cm.execCommand("goCharRight"); + } else if (type == "skipThree") { + for (var i = 0; i < 3; i++) + cm.execCommand("goCharRight"); + } else if (type == "surround") { + var sels = cm.getSelections(); + for (var i = 0; i < sels.length; i++) + sels[i] = left + sels[i] + right; + cm.replaceSelections(sels, "around"); + sels = cm.listSelections().slice(); + for (var i = 0; i < sels.length; i++) + sels[i] = contractSelection(sels[i]); + cm.setSelections(sels); + } else if (type == "both") { + cm.replaceSelection(left + right, null); + cm.triggerElectric(left + right); + cm.execCommand("goCharLeft"); + } else if (type == "addFour") { + cm.replaceSelection(left + left + left + left, "before"); + cm.execCommand("goCharRight"); + } + }); + } + + function isClosingBracket(ch, pairs) { + var pos = pairs.lastIndexOf(ch); + return pos > -1 && pos % 2 == 1; + } + + function charsAround(cm, pos) { + var str = cm.getRange(Pos(pos.line, pos.ch - 1), + Pos(pos.line, pos.ch + 1)); + return str.length == 2 ? str : null; + } + + function stringStartsAfter(cm, pos) { + var token = cm.getTokenAt(Pos(pos.line, pos.ch + 1)) + return /\bstring/.test(token.type) && token.start == pos.ch && + (pos.ch == 0 || !/\bstring/.test(cm.getTokenTypeAt(pos))) + } + }); + + +/***/ }), +/* 7 */ +/***/ (function(module, exports, __webpack_require__) { + + // CodeMirror, copyright (c) by Marijn Haverbeke and others + // Distributed under an MIT license: http://codemirror.net/LICENSE + + (function(mod) { + if (true) // CommonJS + mod(__webpack_require__(2)); + else if (typeof define == "function" && define.amd) // AMD + define(["../../lib/codemirror"], mod); + else // Plain browser env + mod(CodeMirror); + })(function(CodeMirror) { + "use strict"; + + var noOptions = {}; + var nonWS = /[^\s\u00a0]/; + var Pos = CodeMirror.Pos; + + function firstNonWS(str) { + var found = str.search(nonWS); + return found == -1 ? 0 : found; + } + + CodeMirror.commands.toggleComment = function(cm) { + cm.toggleComment(); + }; + + CodeMirror.defineExtension("toggleComment", function(options) { + if (!options) options = noOptions; + var cm = this; + var minLine = Infinity, ranges = this.listSelections(), mode = null; + for (var i = ranges.length - 1; i >= 0; i--) { + var from = ranges[i].from(), to = ranges[i].to(); + if (from.line >= minLine) continue; + if (to.line >= minLine) to = Pos(minLine, 0); + minLine = from.line; + if (mode == null) { + if (cm.uncomment(from, to, options)) mode = "un"; + else { cm.lineComment(from, to, options); mode = "line"; } + } else if (mode == "un") { + cm.uncomment(from, to, options); + } else { + cm.lineComment(from, to, options); + } + } + }); + + // Rough heuristic to try and detect lines that are part of multi-line string + function probablyInsideString(cm, pos, line) { + return /\bstring\b/.test(cm.getTokenTypeAt(Pos(pos.line, 0))) && !/^[\'\"\`]/.test(line) + } + + function getMode(cm, pos) { + var mode = cm.getMode() + return mode.useInnerComments === false || !mode.innerMode ? mode : cm.getModeAt(pos) + } + + CodeMirror.defineExtension("lineComment", function(from, to, options) { + if (!options) options = noOptions; + var self = this, mode = getMode(self, from); + var firstLine = self.getLine(from.line); + if (firstLine == null || probablyInsideString(self, from, firstLine)) return; + + var commentString = options.lineComment || mode.lineComment; + if (!commentString) { + if (options.blockCommentStart || mode.blockCommentStart) { + options.fullLines = true; + self.blockComment(from, to, options); + } + return; + } + + var end = Math.min(to.ch != 0 || to.line == from.line ? to.line + 1 : to.line, self.lastLine() + 1); + var pad = options.padding == null ? " " : options.padding; + var blankLines = options.commentBlankLines || from.line == to.line; + + self.operation(function() { + if (options.indent) { + var baseString = null; + for (var i = from.line; i < end; ++i) { + var line = self.getLine(i); + var whitespace = line.slice(0, firstNonWS(line)); + if (baseString == null || baseString.length > whitespace.length) { + baseString = whitespace; + } + } + for (var i = from.line; i < end; ++i) { + var line = self.getLine(i), cut = baseString.length; + if (!blankLines && !nonWS.test(line)) continue; + if (line.slice(0, cut) != baseString) cut = firstNonWS(line); + self.replaceRange(baseString + commentString + pad, Pos(i, 0), Pos(i, cut)); + } + } else { + for (var i = from.line; i < end; ++i) { + if (blankLines || nonWS.test(self.getLine(i))) + self.replaceRange(commentString + pad, Pos(i, 0)); + } + } + }); + }); + + CodeMirror.defineExtension("blockComment", function(from, to, options) { + if (!options) options = noOptions; + var self = this, mode = getMode(self, from); + var startString = options.blockCommentStart || mode.blockCommentStart; + var endString = options.blockCommentEnd || mode.blockCommentEnd; + if (!startString || !endString) { + if ((options.lineComment || mode.lineComment) && options.fullLines != false) + self.lineComment(from, to, options); + return; + } + if (/\bcomment\b/.test(self.getTokenTypeAt(Pos(from.line, 0)))) return + + var end = Math.min(to.line, self.lastLine()); + if (end != from.line && to.ch == 0 && nonWS.test(self.getLine(end))) --end; + + var pad = options.padding == null ? " " : options.padding; + if (from.line > end) return; + + self.operation(function() { + if (options.fullLines != false) { + var lastLineHasText = nonWS.test(self.getLine(end)); + self.replaceRange(pad + endString, Pos(end)); + self.replaceRange(startString + pad, Pos(from.line, 0)); + var lead = options.blockCommentLead || mode.blockCommentLead; + if (lead != null) for (var i = from.line + 1; i <= end; ++i) + if (i != end || lastLineHasText) + self.replaceRange(lead + pad, Pos(i, 0)); + } else { + self.replaceRange(endString, to); + self.replaceRange(startString, from); + } + }); + }); + + CodeMirror.defineExtension("uncomment", function(from, to, options) { + if (!options) options = noOptions; + var self = this, mode = getMode(self, from); + var end = Math.min(to.ch != 0 || to.line == from.line ? to.line : to.line - 1, self.lastLine()), start = Math.min(from.line, end); + + // Try finding line comments + var lineString = options.lineComment || mode.lineComment, lines = []; + var pad = options.padding == null ? " " : options.padding, didSomething; + lineComment: { + if (!lineString) break lineComment; + for (var i = start; i <= end; ++i) { + var line = self.getLine(i); + var found = line.indexOf(lineString); + if (found > -1 && !/comment/.test(self.getTokenTypeAt(Pos(i, found + 1)))) found = -1; + if (found == -1 && nonWS.test(line)) break lineComment; + if (found > -1 && nonWS.test(line.slice(0, found))) break lineComment; + lines.push(line); + } + self.operation(function() { + for (var i = start; i <= end; ++i) { + var line = lines[i - start]; + var pos = line.indexOf(lineString), endPos = pos + lineString.length; + if (pos < 0) continue; + if (line.slice(endPos, endPos + pad.length) == pad) endPos += pad.length; + didSomething = true; + self.replaceRange("", Pos(i, pos), Pos(i, endPos)); + } + }); + if (didSomething) return true; + } + + // Try block comments + var startString = options.blockCommentStart || mode.blockCommentStart; + var endString = options.blockCommentEnd || mode.blockCommentEnd; + if (!startString || !endString) return false; + var lead = options.blockCommentLead || mode.blockCommentLead; + var startLine = self.getLine(start), open = startLine.indexOf(startString) + if (open == -1) return false + var endLine = end == start ? startLine : self.getLine(end) + var close = endLine.indexOf(endString, end == start ? open + startString.length : 0); + var insideStart = Pos(start, open + 1), insideEnd = Pos(end, close + 1) + if (close == -1 || + !/comment/.test(self.getTokenTypeAt(insideStart)) || + !/comment/.test(self.getTokenTypeAt(insideEnd)) || + self.getRange(insideStart, insideEnd, "\n").indexOf(endString) > -1) + return false; + + // Avoid killing block comments completely outside the selection. + // Positions of the last startString before the start of the selection, and the first endString after it. + var lastStart = startLine.lastIndexOf(startString, from.ch); + var firstEnd = lastStart == -1 ? -1 : startLine.slice(0, from.ch).indexOf(endString, lastStart + startString.length); + if (lastStart != -1 && firstEnd != -1 && firstEnd + endString.length != from.ch) return false; + // Positions of the first endString after the end of the selection, and the last startString before it. + firstEnd = endLine.indexOf(endString, to.ch); + var almostLastStart = endLine.slice(to.ch).lastIndexOf(startString, firstEnd - to.ch); + lastStart = (firstEnd == -1 || almostLastStart == -1) ? -1 : to.ch + almostLastStart; + if (firstEnd != -1 && lastStart != -1 && lastStart != to.ch) return false; + + self.operation(function() { + self.replaceRange("", Pos(end, close - (pad && endLine.slice(close - pad.length, close) == pad ? pad.length : 0)), + Pos(end, close + endString.length)); + var openEnd = open + startString.length; + if (pad && startLine.slice(openEnd, openEnd + pad.length) == pad) openEnd += pad.length; + self.replaceRange("", Pos(start, open), Pos(start, openEnd)); + if (lead) for (var i = start + 1; i <= end; ++i) { + var line = self.getLine(i), found = line.indexOf(lead); + if (found == -1 || nonWS.test(line.slice(0, found))) continue; + var foundEnd = found + lead.length; + if (pad && line.slice(foundEnd, foundEnd + pad.length) == pad) foundEnd += pad.length; + self.replaceRange("", Pos(i, found), Pos(i, foundEnd)); + } + }); + return true; + }); + }); + + +/***/ }), +/* 8 */ +/***/ (function(module, exports, __webpack_require__) { + + // CodeMirror, copyright (c) by Marijn Haverbeke and others + // Distributed under an MIT license: http://codemirror.net/LICENSE + + (function(mod) { + if (true) // CommonJS + mod(__webpack_require__(2)); + else if (typeof define == "function" && define.amd) // AMD + define(["../../lib/codemirror"], mod); + else // Plain browser env + mod(CodeMirror); + })(function(CodeMirror) { + "use strict"; + + CodeMirror.defineMode("javascript", function(config, parserConfig) { + var indentUnit = config.indentUnit; + var statementIndent = parserConfig.statementIndent; + var jsonldMode = parserConfig.jsonld; + var jsonMode = parserConfig.json || jsonldMode; + var isTS = parserConfig.typescript; + var wordRE = parserConfig.wordCharacters || /[\w$\xa1-\uffff]/; + + // Tokenizer + + var keywords = function(){ + function kw(type) {return {type: type, style: "keyword"};} + var A = kw("keyword a"), B = kw("keyword b"), C = kw("keyword c"), D = kw("keyword d"); + var operator = kw("operator"), atom = {type: "atom", style: "atom"}; + + return { + "if": kw("if"), "while": A, "with": A, "else": B, "do": B, "try": B, "finally": B, + "return": D, "break": D, "continue": D, "new": kw("new"), "delete": C, "void": C, "throw": C, + "debugger": kw("debugger"), "var": kw("var"), "const": kw("var"), "let": kw("var"), + "function": kw("function"), "catch": kw("catch"), + "for": kw("for"), "switch": kw("switch"), "case": kw("case"), "default": kw("default"), + "in": operator, "typeof": operator, "instanceof": operator, + "true": atom, "false": atom, "null": atom, "undefined": atom, "NaN": atom, "Infinity": atom, + "this": kw("this"), "class": kw("class"), "super": kw("atom"), + "yield": C, "export": kw("export"), "import": kw("import"), "extends": C, + "await": C + }; + }(); + + var isOperatorChar = /[+\-*&%=<>!?|~^@]/; + var isJsonldKeyword = /^@(context|id|value|language|type|container|list|set|reverse|index|base|vocab|graph)"/; + + function readRegexp(stream) { + var escaped = false, next, inSet = false; + while ((next = stream.next()) != null) { + if (!escaped) { + if (next == "/" && !inSet) return; + if (next == "[") inSet = true; + else if (inSet && next == "]") inSet = false; + } + escaped = !escaped && next == "\\"; + } + } + + // Used as scratch variables to communicate multiple values without + // consing up tons of objects. + var type, content; + function ret(tp, style, cont) { + type = tp; content = cont; + return style; + } + function tokenBase(stream, state) { + var ch = stream.next(); + if (ch == '"' || ch == "'") { + state.tokenize = tokenString(ch); + return state.tokenize(stream, state); + } else if (ch == "." && stream.match(/^\d+(?:[eE][+\-]?\d+)?/)) { + return ret("number", "number"); + } else if (ch == "." && stream.match("..")) { + return ret("spread", "meta"); + } else if (/[\[\]{}\(\),;\:\.]/.test(ch)) { + return ret(ch); + } else if (ch == "=" && stream.eat(">")) { + return ret("=>", "operator"); + } else if (ch == "0" && stream.eat(/x/i)) { + stream.eatWhile(/[\da-f]/i); + return ret("number", "number"); + } else if (ch == "0" && stream.eat(/o/i)) { + stream.eatWhile(/[0-7]/i); + return ret("number", "number"); + } else if (ch == "0" && stream.eat(/b/i)) { + stream.eatWhile(/[01]/i); + return ret("number", "number"); + } else if (/\d/.test(ch)) { + stream.match(/^\d*(?:\.\d*)?(?:[eE][+\-]?\d+)?/); + return ret("number", "number"); + } else if (ch == "/") { + if (stream.eat("*")) { + state.tokenize = tokenComment; + return tokenComment(stream, state); + } else if (stream.eat("/")) { + stream.skipToEnd(); + return ret("comment", "comment"); + } else if (expressionAllowed(stream, state, 1)) { + readRegexp(stream); + stream.match(/^\b(([gimyu])(?![gimyu]*\2))+\b/); + return ret("regexp", "string-2"); + } else { + stream.eat("="); + return ret("operator", "operator", stream.current()); + } + } else if (ch == "`") { + state.tokenize = tokenQuasi; + return tokenQuasi(stream, state); + } else if (ch == "#") { + stream.skipToEnd(); + return ret("error", "error"); + } else if (isOperatorChar.test(ch)) { + if (ch != ">" || !state.lexical || state.lexical.type != ">") { + if (stream.eat("=")) { + if (ch == "!" || ch == "=") stream.eat("=") + } else if (/[<>*+\-]/.test(ch)) { + stream.eat(ch) + if (ch == ">") stream.eat(ch) + } + } + return ret("operator", "operator", stream.current()); + } else if (wordRE.test(ch)) { + stream.eatWhile(wordRE); + var word = stream.current() + if (state.lastType != ".") { + if (keywords.propertyIsEnumerable(word)) { + var kw = keywords[word] + return ret(kw.type, kw.style, word) + } + if (word == "async" && stream.match(/^(\s|\/\*.*?\*\/)*[\[\(\w]/, false)) + return ret("async", "keyword", word) + } + return ret("variable", "variable", word) + } + } + + function tokenString(quote) { + return function(stream, state) { + var escaped = false, next; + if (jsonldMode && stream.peek() == "@" && stream.match(isJsonldKeyword)){ + state.tokenize = tokenBase; + return ret("jsonld-keyword", "meta"); + } + while ((next = stream.next()) != null) { + if (next == quote && !escaped) break; + escaped = !escaped && next == "\\"; + } + if (!escaped) state.tokenize = tokenBase; + return ret("string", "string"); + }; + } + + function tokenComment(stream, state) { + var maybeEnd = false, ch; + while (ch = stream.next()) { + if (ch == "/" && maybeEnd) { + state.tokenize = tokenBase; + break; + } + maybeEnd = (ch == "*"); + } + return ret("comment", "comment"); + } + + function tokenQuasi(stream, state) { + var escaped = false, next; + while ((next = stream.next()) != null) { + if (!escaped && (next == "`" || next == "$" && stream.eat("{"))) { + state.tokenize = tokenBase; + break; + } + escaped = !escaped && next == "\\"; + } + return ret("quasi", "string-2", stream.current()); + } + + var brackets = "([{}])"; + // This is a crude lookahead trick to try and notice that we're + // parsing the argument patterns for a fat-arrow function before we + // actually hit the arrow token. It only works if the arrow is on + // the same line as the arguments and there's no strange noise + // (comments) in between. Fallback is to only notice when we hit the + // arrow, and not declare the arguments as locals for the arrow + // body. + function findFatArrow(stream, state) { + if (state.fatArrowAt) state.fatArrowAt = null; + var arrow = stream.string.indexOf("=>", stream.start); + if (arrow < 0) return; + + if (isTS) { // Try to skip TypeScript return type declarations after the arguments + var m = /:\s*(?:\w+(?:<[^>]*>|\[\])?|\{[^}]*\})\s*$/.exec(stream.string.slice(stream.start, arrow)) + if (m) arrow = m.index + } + + var depth = 0, sawSomething = false; + for (var pos = arrow - 1; pos >= 0; --pos) { + var ch = stream.string.charAt(pos); + var bracket = brackets.indexOf(ch); + if (bracket >= 0 && bracket < 3) { + if (!depth) { ++pos; break; } + if (--depth == 0) { if (ch == "(") sawSomething = true; break; } + } else if (bracket >= 3 && bracket < 6) { + ++depth; + } else if (wordRE.test(ch)) { + sawSomething = true; + } else if (/["'\/]/.test(ch)) { + return; + } else if (sawSomething && !depth) { + ++pos; + break; + } + } + if (sawSomething && !depth) state.fatArrowAt = pos; + } + + // Parser + + var atomicTypes = {"atom": true, "number": true, "variable": true, "string": true, "regexp": true, "this": true, "jsonld-keyword": true}; + + function JSLexical(indented, column, type, align, prev, info) { + this.indented = indented; + this.column = column; + this.type = type; + this.prev = prev; + this.info = info; + if (align != null) this.align = align; + } + + function inScope(state, varname) { + for (var v = state.localVars; v; v = v.next) + if (v.name == varname) return true; + for (var cx = state.context; cx; cx = cx.prev) { + for (var v = cx.vars; v; v = v.next) + if (v.name == varname) return true; + } + } + + function parseJS(state, style, type, content, stream) { + var cc = state.cc; + // Communicate our context to the combinators. + // (Less wasteful than consing up a hundred closures on every call.) + cx.state = state; cx.stream = stream; cx.marked = null, cx.cc = cc; cx.style = style; + + if (!state.lexical.hasOwnProperty("align")) + state.lexical.align = true; + + while(true) { + var combinator = cc.length ? cc.pop() : jsonMode ? expression : statement; + if (combinator(type, content)) { + while(cc.length && cc[cc.length - 1].lex) + cc.pop()(); + if (cx.marked) return cx.marked; + if (type == "variable" && inScope(state, content)) return "variable-2"; + return style; + } + } + } + + // Combinator utils + + var cx = {state: null, column: null, marked: null, cc: null}; + function pass() { + for (var i = arguments.length - 1; i >= 0; i--) cx.cc.push(arguments[i]); + } + function cont() { + pass.apply(null, arguments); + return true; + } + function register(varname) { + function inList(list) { + for (var v = list; v; v = v.next) + if (v.name == varname) return true; + return false; + } + var state = cx.state; + cx.marked = "def"; + if (state.context) { + if (inList(state.localVars)) return; + state.localVars = {name: varname, next: state.localVars}; + } else { + if (inList(state.globalVars)) return; + if (parserConfig.globalVars) + state.globalVars = {name: varname, next: state.globalVars}; + } + } + + function isModifier(name) { + return name == "public" || name == "private" || name == "protected" || name == "abstract" || name == "readonly" + } + + // Combinators + + var defaultVars = {name: "this", next: {name: "arguments"}}; + function pushcontext() { + cx.state.context = {prev: cx.state.context, vars: cx.state.localVars}; + cx.state.localVars = defaultVars; + } + function popcontext() { + cx.state.localVars = cx.state.context.vars; + cx.state.context = cx.state.context.prev; + } + function pushlex(type, info) { + var result = function() { + var state = cx.state, indent = state.indented; + if (state.lexical.type == "stat") indent = state.lexical.indented; + else for (var outer = state.lexical; outer && outer.type == ")" && outer.align; outer = outer.prev) + indent = outer.indented; + state.lexical = new JSLexical(indent, cx.stream.column(), type, null, state.lexical, info); + }; + result.lex = true; + return result; + } + function poplex() { + var state = cx.state; + if (state.lexical.prev) { + if (state.lexical.type == ")") + state.indented = state.lexical.indented; + state.lexical = state.lexical.prev; + } + } + poplex.lex = true; + + function expect(wanted) { + function exp(type) { + if (type == wanted) return cont(); + else if (wanted == ";") return pass(); + else return cont(exp); + }; + return exp; + } + + function statement(type, value) { + if (type == "var") return cont(pushlex("vardef", value.length), vardef, expect(";"), poplex); + if (type == "keyword a") return cont(pushlex("form"), parenExpr, statement, poplex); + if (type == "keyword b") return cont(pushlex("form"), statement, poplex); + if (type == "keyword d") return cx.stream.match(/^\s*$/, false) ? cont() : cont(pushlex("stat"), maybeexpression, expect(";"), poplex); + if (type == "debugger") return cont(expect(";")); + if (type == "{") return cont(pushlex("}"), block, poplex); + if (type == ";") return cont(); + if (type == "if") { + if (cx.state.lexical.info == "else" && cx.state.cc[cx.state.cc.length - 1] == poplex) + cx.state.cc.pop()(); + return cont(pushlex("form"), parenExpr, statement, poplex, maybeelse); + } + if (type == "function") return cont(functiondef); + if (type == "for") return cont(pushlex("form"), forspec, statement, poplex); + if (type == "class" || (isTS && value == "interface")) { cx.marked = "keyword"; return cont(pushlex("form"), className, poplex); } + if (type == "variable") { + if (isTS && value == "declare") { + cx.marked = "keyword" + return cont(statement) + } else if (isTS && (value == "module" || value == "enum" || value == "type") && cx.stream.match(/^\s*\w/, false)) { + cx.marked = "keyword" + if (value == "enum") return cont(enumdef); + else if (value == "type") return cont(typeexpr, expect("operator"), typeexpr, expect(";")); + else return cont(pushlex("form"), pattern, expect("{"), pushlex("}"), block, poplex, poplex) + } else if (isTS && value == "namespace") { + cx.marked = "keyword" + return cont(pushlex("form"), expression, block, poplex) + } else if (isTS && value == "abstract") { + cx.marked = "keyword" + return cont(statement) + } else { + return cont(pushlex("stat"), maybelabel); + } + } + if (type == "switch") return cont(pushlex("form"), parenExpr, expect("{"), pushlex("}", "switch"), + block, poplex, poplex); + if (type == "case") return cont(expression, expect(":")); + if (type == "default") return cont(expect(":")); + if (type == "catch") return cont(pushlex("form"), pushcontext, expect("("), funarg, expect(")"), + statement, poplex, popcontext); + if (type == "export") return cont(pushlex("stat"), afterExport, poplex); + if (type == "import") return cont(pushlex("stat"), afterImport, poplex); + if (type == "async") return cont(statement) + if (value == "@") return cont(expression, statement) + return pass(pushlex("stat"), expression, expect(";"), poplex); + } + function expression(type, value) { + return expressionInner(type, value, false); + } + function expressionNoComma(type, value) { + return expressionInner(type, value, true); + } + function parenExpr(type) { + if (type != "(") return pass() + return cont(pushlex(")"), expression, expect(")"), poplex) + } + function expressionInner(type, value, noComma) { + if (cx.state.fatArrowAt == cx.stream.start) { + var body = noComma ? arrowBodyNoComma : arrowBody; + if (type == "(") return cont(pushcontext, pushlex(")"), commasep(funarg, ")"), poplex, expect("=>"), body, popcontext); + else if (type == "variable") return pass(pushcontext, pattern, expect("=>"), body, popcontext); + } + + var maybeop = noComma ? maybeoperatorNoComma : maybeoperatorComma; + if (atomicTypes.hasOwnProperty(type)) return cont(maybeop); + if (type == "function") return cont(functiondef, maybeop); + if (type == "class" || (isTS && value == "interface")) { cx.marked = "keyword"; return cont(pushlex("form"), classExpression, poplex); } + if (type == "keyword c" || type == "async") return cont(noComma ? expressionNoComma : expression); + if (type == "(") return cont(pushlex(")"), maybeexpression, expect(")"), poplex, maybeop); + if (type == "operator" || type == "spread") return cont(noComma ? expressionNoComma : expression); + if (type == "[") return cont(pushlex("]"), arrayLiteral, poplex, maybeop); + if (type == "{") return contCommasep(objprop, "}", null, maybeop); + if (type == "quasi") return pass(quasi, maybeop); + if (type == "new") return cont(maybeTarget(noComma)); + if (type == "import") return cont(expression); + return cont(); + } + function maybeexpression(type) { + if (type.match(/[;\}\)\],]/)) return pass(); + return pass(expression); + } + + function maybeoperatorComma(type, value) { + if (type == ",") return cont(expression); + return maybeoperatorNoComma(type, value, false); + } + function maybeoperatorNoComma(type, value, noComma) { + var me = noComma == false ? maybeoperatorComma : maybeoperatorNoComma; + var expr = noComma == false ? expression : expressionNoComma; + if (type == "=>") return cont(pushcontext, noComma ? arrowBodyNoComma : arrowBody, popcontext); + if (type == "operator") { + if (/\+\+|--/.test(value) || isTS && value == "!") return cont(me); + if (isTS && value == "<" && cx.stream.match(/^([^>]|<.*?>)*>\s*\(/, false)) + return cont(pushlex(">"), commasep(typeexpr, ">"), poplex, me); + if (value == "?") return cont(expression, expect(":"), expr); + return cont(expr); + } + if (type == "quasi") { return pass(quasi, me); } + if (type == ";") return; + if (type == "(") return contCommasep(expressionNoComma, ")", "call", me); + if (type == ".") return cont(property, me); + if (type == "[") return cont(pushlex("]"), maybeexpression, expect("]"), poplex, me); + if (isTS && value == "as") { cx.marked = "keyword"; return cont(typeexpr, me) } + if (type == "regexp") { + cx.state.lastType = cx.marked = "operator" + cx.stream.backUp(cx.stream.pos - cx.stream.start - 1) + return cont(expr) + } + } + function quasi(type, value) { + if (type != "quasi") return pass(); + if (value.slice(value.length - 2) != "${") return cont(quasi); + return cont(expression, continueQuasi); + } + function continueQuasi(type) { + if (type == "}") { + cx.marked = "string-2"; + cx.state.tokenize = tokenQuasi; + return cont(quasi); + } + } + function arrowBody(type) { + findFatArrow(cx.stream, cx.state); + return pass(type == "{" ? statement : expression); + } + function arrowBodyNoComma(type) { + findFatArrow(cx.stream, cx.state); + return pass(type == "{" ? statement : expressionNoComma); + } + function maybeTarget(noComma) { + return function(type) { + if (type == ".") return cont(noComma ? targetNoComma : target); + else if (type == "variable" && isTS) return cont(maybeTypeArgs, noComma ? maybeoperatorNoComma : maybeoperatorComma) + else return pass(noComma ? expressionNoComma : expression); + }; + } + function target(_, value) { + if (value == "target") { cx.marked = "keyword"; return cont(maybeoperatorComma); } + } + function targetNoComma(_, value) { + if (value == "target") { cx.marked = "keyword"; return cont(maybeoperatorNoComma); } + } + function maybelabel(type) { + if (type == ":") return cont(poplex, statement); + return pass(maybeoperatorComma, expect(";"), poplex); + } + function property(type) { + if (type == "variable") {cx.marked = "property"; return cont();} + } + function objprop(type, value) { + if (type == "async") { + cx.marked = "property"; + return cont(objprop); + } else if (type == "variable" || cx.style == "keyword") { + cx.marked = "property"; + if (value == "get" || value == "set") return cont(getterSetter); + var m // Work around fat-arrow-detection complication for detecting typescript typed arrow params + if (isTS && cx.state.fatArrowAt == cx.stream.start && (m = cx.stream.match(/^\s*:\s*/, false))) + cx.state.fatArrowAt = cx.stream.pos + m[0].length + return cont(afterprop); + } else if (type == "number" || type == "string") { + cx.marked = jsonldMode ? "property" : (cx.style + " property"); + return cont(afterprop); + } else if (type == "jsonld-keyword") { + return cont(afterprop); + } else if (isTS && isModifier(value)) { + cx.marked = "keyword" + return cont(objprop) + } else if (type == "[") { + return cont(expression, maybetype, expect("]"), afterprop); + } else if (type == "spread") { + return cont(expressionNoComma, afterprop); + } else if (value == "*") { + cx.marked = "keyword"; + return cont(objprop); + } else if (type == ":") { + return pass(afterprop) + } + } + function getterSetter(type) { + if (type != "variable") return pass(afterprop); + cx.marked = "property"; + return cont(functiondef); + } + function afterprop(type) { + if (type == ":") return cont(expressionNoComma); + if (type == "(") return pass(functiondef); + } + function commasep(what, end, sep) { + function proceed(type, value) { + if (sep ? sep.indexOf(type) > -1 : type == ",") { + var lex = cx.state.lexical; + if (lex.info == "call") lex.pos = (lex.pos || 0) + 1; + return cont(function(type, value) { + if (type == end || value == end) return pass() + return pass(what) + }, proceed); + } + if (type == end || value == end) return cont(); + return cont(expect(end)); + } + return function(type, value) { + if (type == end || value == end) return cont(); + return pass(what, proceed); + }; + } + function contCommasep(what, end, info) { + for (var i = 3; i < arguments.length; i++) + cx.cc.push(arguments[i]); + return cont(pushlex(end, info), commasep(what, end), poplex); + } + function block(type) { + if (type == "}") return cont(); + return pass(statement, block); + } + function maybetype(type, value) { + if (isTS) { + if (type == ":") return cont(typeexpr); + if (value == "?") return cont(maybetype); + } + } + function mayberettype(type) { + if (isTS && type == ":") { + if (cx.stream.match(/^\s*\w+\s+is\b/, false)) return cont(expression, isKW, typeexpr) + else return cont(typeexpr) + } + } + function isKW(_, value) { + if (value == "is") { + cx.marked = "keyword" + return cont() + } + } + function typeexpr(type, value) { + if (value == "keyof" || value == "typeof") { + cx.marked = "keyword" + return cont(value == "keyof" ? typeexpr : expressionNoComma) + } + if (type == "variable" || value == "void") { + cx.marked = "type" + return cont(afterType) + } + if (type == "string" || type == "number" || type == "atom") return cont(afterType); + if (type == "[") return cont(pushlex("]"), commasep(typeexpr, "]", ","), poplex, afterType) + if (type == "{") return cont(pushlex("}"), commasep(typeprop, "}", ",;"), poplex, afterType) + if (type == "(") return cont(commasep(typearg, ")"), maybeReturnType) + if (type == "<") return cont(commasep(typeexpr, ">"), typeexpr) + } + function maybeReturnType(type) { + if (type == "=>") return cont(typeexpr) + } + function typeprop(type, value) { + if (type == "variable" || cx.style == "keyword") { + cx.marked = "property" + return cont(typeprop) + } else if (value == "?") { + return cont(typeprop) + } else if (type == ":") { + return cont(typeexpr) + } else if (type == "[") { + return cont(expression, maybetype, expect("]"), typeprop) + } + } + function typearg(type, value) { + if (type == "variable" && cx.stream.match(/^\s*[?:]/, false) || value == "?") return cont(typearg) + if (type == ":") return cont(typeexpr) + return pass(typeexpr) + } + function afterType(type, value) { + if (value == "<") return cont(pushlex(">"), commasep(typeexpr, ">"), poplex, afterType) + if (value == "|" || type == "." || value == "&") return cont(typeexpr) + if (type == "[") return cont(expect("]"), afterType) + if (value == "extends" || value == "implements") { cx.marked = "keyword"; return cont(typeexpr) } + } + function maybeTypeArgs(_, value) { + if (value == "<") return cont(pushlex(">"), commasep(typeexpr, ">"), poplex, afterType) + } + function typeparam() { + return pass(typeexpr, maybeTypeDefault) + } + function maybeTypeDefault(_, value) { + if (value == "=") return cont(typeexpr) + } + function vardef(_, value) { + if (value == "enum") {cx.marked = "keyword"; return cont(enumdef)} + return pass(pattern, maybetype, maybeAssign, vardefCont); + } + function pattern(type, value) { + if (isTS && isModifier(value)) { cx.marked = "keyword"; return cont(pattern) } + if (type == "variable") { register(value); return cont(); } + if (type == "spread") return cont(pattern); + if (type == "[") return contCommasep(pattern, "]"); + if (type == "{") return contCommasep(proppattern, "}"); + } + function proppattern(type, value) { + if (type == "variable" && !cx.stream.match(/^\s*:/, false)) { + register(value); + return cont(maybeAssign); + } + if (type == "variable") cx.marked = "property"; + if (type == "spread") return cont(pattern); + if (type == "}") return pass(); + return cont(expect(":"), pattern, maybeAssign); + } + function maybeAssign(_type, value) { + if (value == "=") return cont(expressionNoComma); + } + function vardefCont(type) { + if (type == ",") return cont(vardef); + } + function maybeelse(type, value) { + if (type == "keyword b" && value == "else") return cont(pushlex("form", "else"), statement, poplex); + } + function forspec(type, value) { + if (value == "await") return cont(forspec); + if (type == "(") return cont(pushlex(")"), forspec1, expect(")"), poplex); + } + function forspec1(type) { + if (type == "var") return cont(vardef, expect(";"), forspec2); + if (type == ";") return cont(forspec2); + if (type == "variable") return cont(formaybeinof); + return pass(expression, expect(";"), forspec2); + } + function formaybeinof(_type, value) { + if (value == "in" || value == "of") { cx.marked = "keyword"; return cont(expression); } + return cont(maybeoperatorComma, forspec2); + } + function forspec2(type, value) { + if (type == ";") return cont(forspec3); + if (value == "in" || value == "of") { cx.marked = "keyword"; return cont(expression); } + return pass(expression, expect(";"), forspec3); + } + function forspec3(type) { + if (type != ")") cont(expression); + } + function functiondef(type, value) { + if (value == "*") {cx.marked = "keyword"; return cont(functiondef);} + if (type == "variable") {register(value); return cont(functiondef);} + if (type == "(") return cont(pushcontext, pushlex(")"), commasep(funarg, ")"), poplex, mayberettype, statement, popcontext); + if (isTS && value == "<") return cont(pushlex(">"), commasep(typeparam, ">"), poplex, functiondef) + } + function funarg(type, value) { + if (value == "@") cont(expression, funarg) + if (type == "spread") return cont(funarg); + if (isTS && isModifier(value)) { cx.marked = "keyword"; return cont(funarg); } + return pass(pattern, maybetype, maybeAssign); + } + function classExpression(type, value) { + // Class expressions may have an optional name. + if (type == "variable") return className(type, value); + return classNameAfter(type, value); + } + function className(type, value) { + if (type == "variable") {register(value); return cont(classNameAfter);} + } + function classNameAfter(type, value) { + if (value == "<") return cont(pushlex(">"), commasep(typeparam, ">"), poplex, classNameAfter) + if (value == "extends" || value == "implements" || (isTS && type == ",")) { + if (value == "implements") cx.marked = "keyword"; + return cont(isTS ? typeexpr : expression, classNameAfter); + } + if (type == "{") return cont(pushlex("}"), classBody, poplex); + } + function classBody(type, value) { + if (type == "async" || + (type == "variable" && + (value == "static" || value == "get" || value == "set" || (isTS && isModifier(value))) && + cx.stream.match(/^\s+[\w$\xa1-\uffff]/, false))) { + cx.marked = "keyword"; + return cont(classBody); + } + if (type == "variable" || cx.style == "keyword") { + cx.marked = "property"; + return cont(isTS ? classfield : functiondef, classBody); + } + if (type == "[") + return cont(expression, maybetype, expect("]"), isTS ? classfield : functiondef, classBody) + if (value == "*") { + cx.marked = "keyword"; + return cont(classBody); + } + if (type == ";") return cont(classBody); + if (type == "}") return cont(); + if (value == "@") return cont(expression, classBody) + } + function classfield(type, value) { + if (value == "?") return cont(classfield) + if (type == ":") return cont(typeexpr, maybeAssign) + if (value == "=") return cont(expressionNoComma) + return pass(functiondef) + } + function afterExport(type, value) { + if (value == "*") { cx.marked = "keyword"; return cont(maybeFrom, expect(";")); } + if (value == "default") { cx.marked = "keyword"; return cont(expression, expect(";")); } + if (type == "{") return cont(commasep(exportField, "}"), maybeFrom, expect(";")); + return pass(statement); + } + function exportField(type, value) { + if (value == "as") { cx.marked = "keyword"; return cont(expect("variable")); } + if (type == "variable") return pass(expressionNoComma, exportField); + } + function afterImport(type) { + if (type == "string") return cont(); + if (type == "(") return pass(expression); + return pass(importSpec, maybeMoreImports, maybeFrom); + } + function importSpec(type, value) { + if (type == "{") return contCommasep(importSpec, "}"); + if (type == "variable") register(value); + if (value == "*") cx.marked = "keyword"; + return cont(maybeAs); + } + function maybeMoreImports(type) { + if (type == ",") return cont(importSpec, maybeMoreImports) + } + function maybeAs(_type, value) { + if (value == "as") { cx.marked = "keyword"; return cont(importSpec); } + } + function maybeFrom(_type, value) { + if (value == "from") { cx.marked = "keyword"; return cont(expression); } + } + function arrayLiteral(type) { + if (type == "]") return cont(); + return pass(commasep(expressionNoComma, "]")); + } + function enumdef() { + return pass(pushlex("form"), pattern, expect("{"), pushlex("}"), commasep(enummember, "}"), poplex, poplex) + } + function enummember() { + return pass(pattern, maybeAssign); + } + + function isContinuedStatement(state, textAfter) { + return state.lastType == "operator" || state.lastType == "," || + isOperatorChar.test(textAfter.charAt(0)) || + /[,.]/.test(textAfter.charAt(0)); + } + + function expressionAllowed(stream, state, backUp) { + return state.tokenize == tokenBase && + /^(?:operator|sof|keyword [bcd]|case|new|export|default|spread|[\[{}\(,;:]|=>)$/.test(state.lastType) || + (state.lastType == "quasi" && /\{\s*$/.test(stream.string.slice(0, stream.pos - (backUp || 0)))) + } + + // Interface + + return { + startState: function(basecolumn) { + var state = { + tokenize: tokenBase, + lastType: "sof", + cc: [], + lexical: new JSLexical((basecolumn || 0) - indentUnit, 0, "block", false), + localVars: parserConfig.localVars, + context: parserConfig.localVars && {vars: parserConfig.localVars}, + indented: basecolumn || 0 + }; + if (parserConfig.globalVars && typeof parserConfig.globalVars == "object") + state.globalVars = parserConfig.globalVars; + return state; + }, + + token: function(stream, state) { + if (stream.sol()) { + if (!state.lexical.hasOwnProperty("align")) + state.lexical.align = false; + state.indented = stream.indentation(); + findFatArrow(stream, state); + } + if (state.tokenize != tokenComment && stream.eatSpace()) return null; + var style = state.tokenize(stream, state); + if (type == "comment") return style; + state.lastType = type == "operator" && (content == "++" || content == "--") ? "incdec" : type; + return parseJS(state, style, type, content, stream); + }, + + indent: function(state, textAfter) { + if (state.tokenize == tokenComment) return CodeMirror.Pass; + if (state.tokenize != tokenBase) return 0; + var firstChar = textAfter && textAfter.charAt(0), lexical = state.lexical, top + // Kludge to prevent 'maybelse' from blocking lexical scope pops + if (!/^\s*else\b/.test(textAfter)) for (var i = state.cc.length - 1; i >= 0; --i) { + var c = state.cc[i]; + if (c == poplex) lexical = lexical.prev; + else if (c != maybeelse) break; + } + while ((lexical.type == "stat" || lexical.type == "form") && + (firstChar == "}" || ((top = state.cc[state.cc.length - 1]) && + (top == maybeoperatorComma || top == maybeoperatorNoComma) && + !/^[,\.=+\-*:?[\(]/.test(textAfter)))) + lexical = lexical.prev; + if (statementIndent && lexical.type == ")" && lexical.prev.type == "stat") + lexical = lexical.prev; + var type = lexical.type, closing = firstChar == type; + + if (type == "vardef") return lexical.indented + (state.lastType == "operator" || state.lastType == "," ? lexical.info + 1 : 0); + else if (type == "form" && firstChar == "{") return lexical.indented; + else if (type == "form") return lexical.indented + indentUnit; + else if (type == "stat") + return lexical.indented + (isContinuedStatement(state, textAfter) ? statementIndent || indentUnit : 0); + else if (lexical.info == "switch" && !closing && parserConfig.doubleIndentSwitch != false) + return lexical.indented + (/^(?:case|default)\b/.test(textAfter) ? indentUnit : 2 * indentUnit); + else if (lexical.align) return lexical.column + (closing ? 0 : 1); + else return lexical.indented + (closing ? 0 : indentUnit); + }, + + electricInput: /^\s*(?:case .*?:|default:|\{|\})$/, + blockCommentStart: jsonMode ? null : "/*", + blockCommentEnd: jsonMode ? null : "*/", + blockCommentContinue: jsonMode ? null : " * ", + lineComment: jsonMode ? null : "//", + fold: "brace", + closeBrackets: "()[]{}''\"\"``", + + helperType: jsonMode ? "json" : "javascript", + jsonldMode: jsonldMode, + jsonMode: jsonMode, + + expressionAllowed: expressionAllowed, + + skipExpression: function(state) { + var top = state.cc[state.cc.length - 1] + if (top == expression || top == expressionNoComma) state.cc.pop() + } + }; + }); + + CodeMirror.registerHelper("wordChars", "javascript", /[\w$]/); + + CodeMirror.defineMIME("text/javascript", "javascript"); + CodeMirror.defineMIME("text/ecmascript", "javascript"); + CodeMirror.defineMIME("application/javascript", "javascript"); + CodeMirror.defineMIME("application/x-javascript", "javascript"); + CodeMirror.defineMIME("application/ecmascript", "javascript"); + CodeMirror.defineMIME("application/json", {name: "javascript", json: true}); + CodeMirror.defineMIME("application/x-json", {name: "javascript", json: true}); + CodeMirror.defineMIME("application/ld+json", {name: "javascript", jsonld: true}); + CodeMirror.defineMIME("text/typescript", { name: "javascript", typescript: true }); + CodeMirror.defineMIME("application/typescript", { name: "javascript", typescript: true }); + + }); + + +/***/ }), +/* 9 */ +/***/ (function(module, exports, __webpack_require__) { + + // CodeMirror, copyright (c) by Marijn Haverbeke and others + // Distributed under an MIT license: http://codemirror.net/LICENSE + + (function(mod) { + if (true) // CommonJS + mod(__webpack_require__(2)); + else if (typeof define == "function" && define.amd) // AMD + define(["../../lib/codemirror"], mod); + else // Plain browser env + mod(CodeMirror); + })(function(CodeMirror) { + "use strict"; + + var htmlConfig = { + autoSelfClosers: {'area': true, 'base': true, 'br': true, 'col': true, 'command': true, + 'embed': true, 'frame': true, 'hr': true, 'img': true, 'input': true, + 'keygen': true, 'link': true, 'meta': true, 'param': true, 'source': true, + 'track': true, 'wbr': true, 'menuitem': true}, + implicitlyClosed: {'dd': true, 'li': true, 'optgroup': true, 'option': true, 'p': true, + 'rp': true, 'rt': true, 'tbody': true, 'td': true, 'tfoot': true, + 'th': true, 'tr': true}, + contextGrabbers: { + 'dd': {'dd': true, 'dt': true}, + 'dt': {'dd': true, 'dt': true}, + 'li': {'li': true}, + 'option': {'option': true, 'optgroup': true}, + 'optgroup': {'optgroup': true}, + 'p': {'address': true, 'article': true, 'aside': true, 'blockquote': true, 'dir': true, + 'div': true, 'dl': true, 'fieldset': true, 'footer': true, 'form': true, + 'h1': true, 'h2': true, 'h3': true, 'h4': true, 'h5': true, 'h6': true, + 'header': true, 'hgroup': true, 'hr': true, 'menu': true, 'nav': true, 'ol': true, + 'p': true, 'pre': true, 'section': true, 'table': true, 'ul': true}, + 'rp': {'rp': true, 'rt': true}, + 'rt': {'rp': true, 'rt': true}, + 'tbody': {'tbody': true, 'tfoot': true}, + 'td': {'td': true, 'th': true}, + 'tfoot': {'tbody': true}, + 'th': {'td': true, 'th': true}, + 'thead': {'tbody': true, 'tfoot': true}, + 'tr': {'tr': true} + }, + doNotIndent: {"pre": true}, + allowUnquoted: true, + allowMissing: true, + caseFold: true + } + + var xmlConfig = { + autoSelfClosers: {}, + implicitlyClosed: {}, + contextGrabbers: {}, + doNotIndent: {}, + allowUnquoted: false, + allowMissing: false, + allowMissingTagName: false, + caseFold: false + } + + CodeMirror.defineMode("xml", function(editorConf, config_) { + var indentUnit = editorConf.indentUnit + var config = {} + var defaults = config_.htmlMode ? htmlConfig : xmlConfig + for (var prop in defaults) config[prop] = defaults[prop] + for (var prop in config_) config[prop] = config_[prop] + + // Return variables for tokenizers + var type, setStyle; + + function inText(stream, state) { + function chain(parser) { + state.tokenize = parser; + return parser(stream, state); + } + + var ch = stream.next(); + if (ch == "<") { + if (stream.eat("!")) { + if (stream.eat("[")) { + if (stream.match("CDATA[")) return chain(inBlock("atom", "]]>")); + else return null; + } else if (stream.match("--")) { + return chain(inBlock("comment", "-->")); + } else if (stream.match("DOCTYPE", true, true)) { + stream.eatWhile(/[\w\._\-]/); + return chain(doctype(1)); + } else { + return null; + } + } else if (stream.eat("?")) { + stream.eatWhile(/[\w\._\-]/); + state.tokenize = inBlock("meta", "?>"); + return "meta"; + } else { + type = stream.eat("/") ? "closeTag" : "openTag"; + state.tokenize = inTag; + return "tag bracket"; + } + } else if (ch == "&") { + var ok; + if (stream.eat("#")) { + if (stream.eat("x")) { + ok = stream.eatWhile(/[a-fA-F\d]/) && stream.eat(";"); + } else { + ok = stream.eatWhile(/[\d]/) && stream.eat(";"); + } + } else { + ok = stream.eatWhile(/[\w\.\-:]/) && stream.eat(";"); + } + return ok ? "atom" : "error"; + } else { + stream.eatWhile(/[^&<]/); + return null; + } + } + inText.isInText = true; + + function inTag(stream, state) { + var ch = stream.next(); + if (ch == ">" || (ch == "/" && stream.eat(">"))) { + state.tokenize = inText; + type = ch == ">" ? "endTag" : "selfcloseTag"; + return "tag bracket"; + } else if (ch == "=") { + type = "equals"; + return null; + } else if (ch == "<") { + state.tokenize = inText; + state.state = baseState; + state.tagName = state.tagStart = null; + var next = state.tokenize(stream, state); + return next ? next + " tag error" : "tag error"; + } else if (/[\'\"]/.test(ch)) { + state.tokenize = inAttribute(ch); + state.stringStartCol = stream.column(); + return state.tokenize(stream, state); + } else { + stream.match(/^[^\s\u00a0=<>\"\']*[^\s\u00a0=<>\"\'\/]/); + return "word"; + } + } + + function inAttribute(quote) { + var closure = function(stream, state) { + while (!stream.eol()) { + if (stream.next() == quote) { + state.tokenize = inTag; + break; + } + } + return "string"; + }; + closure.isInAttribute = true; + return closure; + } + + function inBlock(style, terminator) { + return function(stream, state) { + while (!stream.eol()) { + if (stream.match(terminator)) { + state.tokenize = inText; + break; + } + stream.next(); + } + return style; + }; + } + function doctype(depth) { + return function(stream, state) { + var ch; + while ((ch = stream.next()) != null) { + if (ch == "<") { + state.tokenize = doctype(depth + 1); + return state.tokenize(stream, state); + } else if (ch == ">") { + if (depth == 1) { + state.tokenize = inText; + break; + } else { + state.tokenize = doctype(depth - 1); + return state.tokenize(stream, state); + } + } + } + return "meta"; + }; + } + + function Context(state, tagName, startOfLine) { + this.prev = state.context; + this.tagName = tagName; + this.indent = state.indented; + this.startOfLine = startOfLine; + if (config.doNotIndent.hasOwnProperty(tagName) || (state.context && state.context.noIndent)) + this.noIndent = true; + } + function popContext(state) { + if (state.context) state.context = state.context.prev; + } + function maybePopContext(state, nextTagName) { + var parentTagName; + while (true) { + if (!state.context) { + return; + } + parentTagName = state.context.tagName; + if (!config.contextGrabbers.hasOwnProperty(parentTagName) || + !config.contextGrabbers[parentTagName].hasOwnProperty(nextTagName)) { + return; + } + popContext(state); + } + } + + function baseState(type, stream, state) { + if (type == "openTag") { + state.tagStart = stream.column(); + return tagNameState; + } else if (type == "closeTag") { + return closeTagNameState; + } else { + return baseState; + } + } + function tagNameState(type, stream, state) { + if (type == "word") { + state.tagName = stream.current(); + setStyle = "tag"; + return attrState; + } else if (config.allowMissingTagName && type == "endTag") { + setStyle = "tag bracket"; + return attrState(type, stream, state); + } else { + setStyle = "error"; + return tagNameState; + } + } + function closeTagNameState(type, stream, state) { + if (type == "word") { + var tagName = stream.current(); + if (state.context && state.context.tagName != tagName && + config.implicitlyClosed.hasOwnProperty(state.context.tagName)) + popContext(state); + if ((state.context && state.context.tagName == tagName) || config.matchClosing === false) { + setStyle = "tag"; + return closeState; + } else { + setStyle = "tag error"; + return closeStateErr; + } + } else if (config.allowMissingTagName && type == "endTag") { + setStyle = "tag bracket"; + return closeState(type, stream, state); + } else { + setStyle = "error"; + return closeStateErr; + } + } + + function closeState(type, _stream, state) { + if (type != "endTag") { + setStyle = "error"; + return closeState; + } + popContext(state); + return baseState; + } + function closeStateErr(type, stream, state) { + setStyle = "error"; + return closeState(type, stream, state); + } + + function attrState(type, _stream, state) { + if (type == "word") { + setStyle = "attribute"; + return attrEqState; + } else if (type == "endTag" || type == "selfcloseTag") { + var tagName = state.tagName, tagStart = state.tagStart; + state.tagName = state.tagStart = null; + if (type == "selfcloseTag" || + config.autoSelfClosers.hasOwnProperty(tagName)) { + maybePopContext(state, tagName); + } else { + maybePopContext(state, tagName); + state.context = new Context(state, tagName, tagStart == state.indented); + } + return baseState; + } + setStyle = "error"; + return attrState; + } + function attrEqState(type, stream, state) { + if (type == "equals") return attrValueState; + if (!config.allowMissing) setStyle = "error"; + return attrState(type, stream, state); + } + function attrValueState(type, stream, state) { + if (type == "string") return attrContinuedState; + if (type == "word" && config.allowUnquoted) {setStyle = "string"; return attrState;} + setStyle = "error"; + return attrState(type, stream, state); + } + function attrContinuedState(type, stream, state) { + if (type == "string") return attrContinuedState; + return attrState(type, stream, state); + } + + return { + startState: function(baseIndent) { + var state = {tokenize: inText, + state: baseState, + indented: baseIndent || 0, + tagName: null, tagStart: null, + context: null} + if (baseIndent != null) state.baseIndent = baseIndent + return state + }, + + token: function(stream, state) { + if (!state.tagName && stream.sol()) + state.indented = stream.indentation(); + + if (stream.eatSpace()) return null; + type = null; + var style = state.tokenize(stream, state); + if ((style || type) && style != "comment") { + setStyle = null; + state.state = state.state(type || style, stream, state); + if (setStyle) + style = setStyle == "error" ? style + " error" : setStyle; + } + return style; + }, + + indent: function(state, textAfter, fullLine) { + var context = state.context; + // Indent multi-line strings (e.g. css). + if (state.tokenize.isInAttribute) { + if (state.tagStart == state.indented) + return state.stringStartCol + 1; + else + return state.indented + indentUnit; + } + if (context && context.noIndent) return CodeMirror.Pass; + if (state.tokenize != inTag && state.tokenize != inText) + return fullLine ? fullLine.match(/^(\s*)/)[0].length : 0; + // Indent the starts of attribute names. + if (state.tagName) { + if (config.multilineTagIndentPastTag !== false) + return state.tagStart + state.tagName.length + 2; + else + return state.tagStart + indentUnit * (config.multilineTagIndentFactor || 1); + } + if (config.alignCDATA && /$/, + blockCommentStart: "", + + configuration: config.htmlMode ? "html" : "xml", + helperType: config.htmlMode ? "html" : "xml", + + skipAttribute: function(state) { + if (state.state == attrValueState) + state.state = attrState + } + }; + }); + + CodeMirror.defineMIME("text/xml", "xml"); + CodeMirror.defineMIME("application/xml", "xml"); + if (!CodeMirror.mimeModes.hasOwnProperty("text/html")) + CodeMirror.defineMIME("text/html", {name: "xml", htmlMode: true}); + + }); + + +/***/ }), +/* 10 */ +/***/ (function(module, exports, __webpack_require__) { + + // CodeMirror, copyright (c) by Marijn Haverbeke and others + // Distributed under an MIT license: http://codemirror.net/LICENSE + + (function(mod) { + if (true) // CommonJS + mod(__webpack_require__(2)); + else if (typeof define == "function" && define.amd) // AMD + define(["../../lib/codemirror"], mod); + else // Plain browser env + mod(CodeMirror); + })(function(CodeMirror) { + "use strict"; + + CodeMirror.defineMode("css", function(config, parserConfig) { + var inline = parserConfig.inline + if (!parserConfig.propertyKeywords) parserConfig = CodeMirror.resolveMode("text/css"); + + var indentUnit = config.indentUnit, + tokenHooks = parserConfig.tokenHooks, + documentTypes = parserConfig.documentTypes || {}, + mediaTypes = parserConfig.mediaTypes || {}, + mediaFeatures = parserConfig.mediaFeatures || {}, + mediaValueKeywords = parserConfig.mediaValueKeywords || {}, + propertyKeywords = parserConfig.propertyKeywords || {}, + nonStandardPropertyKeywords = parserConfig.nonStandardPropertyKeywords || {}, + fontProperties = parserConfig.fontProperties || {}, + counterDescriptors = parserConfig.counterDescriptors || {}, + colorKeywords = parserConfig.colorKeywords || {}, + valueKeywords = parserConfig.valueKeywords || {}, + allowNested = parserConfig.allowNested, + lineComment = parserConfig.lineComment, + supportsAtComponent = parserConfig.supportsAtComponent === true; + + var type, override; + function ret(style, tp) { type = tp; return style; } + + // Tokenizers + + function tokenBase(stream, state) { + var ch = stream.next(); + if (tokenHooks[ch]) { + var result = tokenHooks[ch](stream, state); + if (result !== false) return result; + } + if (ch == "@") { + stream.eatWhile(/[\w\\\-]/); + return ret("def", stream.current()); + } else if (ch == "=" || (ch == "~" || ch == "|") && stream.eat("=")) { + return ret(null, "compare"); + } else if (ch == "\"" || ch == "'") { + state.tokenize = tokenString(ch); + return state.tokenize(stream, state); + } else if (ch == "#") { + stream.eatWhile(/[\w\\\-]/); + return ret("atom", "hash"); + } else if (ch == "!") { + stream.match(/^\s*\w*/); + return ret("keyword", "important"); + } else if (/\d/.test(ch) || ch == "." && stream.eat(/\d/)) { + stream.eatWhile(/[\w.%]/); + return ret("number", "unit"); + } else if (ch === "-") { + if (/[\d.]/.test(stream.peek())) { + stream.eatWhile(/[\w.%]/); + return ret("number", "unit"); + } else if (stream.match(/^-[\w\\\-]+/)) { + stream.eatWhile(/[\w\\\-]/); + if (stream.match(/^\s*:/, false)) + return ret("variable-2", "variable-definition"); + return ret("variable-2", "variable"); + } else if (stream.match(/^\w+-/)) { + return ret("meta", "meta"); + } + } else if (/[,+>*\/]/.test(ch)) { + return ret(null, "select-op"); + } else if (ch == "." && stream.match(/^-?[_a-z][_a-z0-9-]*/i)) { + return ret("qualifier", "qualifier"); + } else if (/[:;{}\[\]\(\)]/.test(ch)) { + return ret(null, ch); + } else if (((ch == "u" || ch == "U") && stream.match(/rl(-prefix)?\(/i)) || + ((ch == "d" || ch == "D") && stream.match("omain(", true, true)) || + ((ch == "r" || ch == "R") && stream.match("egexp(", true, true))) { + stream.backUp(1); + state.tokenize = tokenParenthesized; + return ret("property", "word"); + } else if (/[\w\\\-]/.test(ch)) { + stream.eatWhile(/[\w\\\-]/); + return ret("property", "word"); + } else { + return ret(null, null); + } + } + + function tokenString(quote) { + return function(stream, state) { + var escaped = false, ch; + while ((ch = stream.next()) != null) { + if (ch == quote && !escaped) { + if (quote == ")") stream.backUp(1); + break; + } + escaped = !escaped && ch == "\\"; + } + if (ch == quote || !escaped && quote != ")") state.tokenize = null; + return ret("string", "string"); + }; + } + + function tokenParenthesized(stream, state) { + stream.next(); // Must be '(' + if (!stream.match(/\s*[\"\')]/, false)) + state.tokenize = tokenString(")"); + else + state.tokenize = null; + return ret(null, "("); + } + + // Context management + + function Context(type, indent, prev) { + this.type = type; + this.indent = indent; + this.prev = prev; + } + + function pushContext(state, stream, type, indent) { + state.context = new Context(type, stream.indentation() + (indent === false ? 0 : indentUnit), state.context); + return type; + } + + function popContext(state) { + if (state.context.prev) + state.context = state.context.prev; + return state.context.type; + } + + function pass(type, stream, state) { + return states[state.context.type](type, stream, state); + } + function popAndPass(type, stream, state, n) { + for (var i = n || 1; i > 0; i--) + state.context = state.context.prev; + return pass(type, stream, state); + } + + // Parser + + function wordAsValue(stream) { + var word = stream.current().toLowerCase(); + if (valueKeywords.hasOwnProperty(word)) + override = "atom"; + else if (colorKeywords.hasOwnProperty(word)) + override = "keyword"; + else + override = "variable"; + } + + var states = {}; + + states.top = function(type, stream, state) { + if (type == "{") { + return pushContext(state, stream, "block"); + } else if (type == "}" && state.context.prev) { + return popContext(state); + } else if (supportsAtComponent && /@component/i.test(type)) { + return pushContext(state, stream, "atComponentBlock"); + } else if (/^@(-moz-)?document$/i.test(type)) { + return pushContext(state, stream, "documentTypes"); + } else if (/^@(media|supports|(-moz-)?document|import)$/i.test(type)) { + return pushContext(state, stream, "atBlock"); + } else if (/^@(font-face|counter-style)/i.test(type)) { + state.stateArg = type; + return "restricted_atBlock_before"; + } else if (/^@(-(moz|ms|o|webkit)-)?keyframes$/i.test(type)) { + return "keyframes"; + } else if (type && type.charAt(0) == "@") { + return pushContext(state, stream, "at"); + } else if (type == "hash") { + override = "builtin"; + } else if (type == "word") { + override = "tag"; + } else if (type == "variable-definition") { + return "maybeprop"; + } else if (type == "interpolation") { + return pushContext(state, stream, "interpolation"); + } else if (type == ":") { + return "pseudo"; + } else if (allowNested && type == "(") { + return pushContext(state, stream, "parens"); + } + return state.context.type; + }; + + states.block = function(type, stream, state) { + if (type == "word") { + var word = stream.current().toLowerCase(); + if (propertyKeywords.hasOwnProperty(word)) { + override = "property"; + return "maybeprop"; + } else if (nonStandardPropertyKeywords.hasOwnProperty(word)) { + override = "string-2"; + return "maybeprop"; + } else if (allowNested) { + override = stream.match(/^\s*:(?:\s|$)/, false) ? "property" : "tag"; + return "block"; + } else { + override += " error"; + return "maybeprop"; + } + } else if (type == "meta") { + return "block"; + } else if (!allowNested && (type == "hash" || type == "qualifier")) { + override = "error"; + return "block"; + } else { + return states.top(type, stream, state); + } + }; + + states.maybeprop = function(type, stream, state) { + if (type == ":") return pushContext(state, stream, "prop"); + return pass(type, stream, state); + }; + + states.prop = function(type, stream, state) { + if (type == ";") return popContext(state); + if (type == "{" && allowNested) return pushContext(state, stream, "propBlock"); + if (type == "}" || type == "{") return popAndPass(type, stream, state); + if (type == "(") return pushContext(state, stream, "parens"); + + if (type == "hash" && !/^#([0-9a-fA-f]{3,4}|[0-9a-fA-f]{6}|[0-9a-fA-f]{8})$/.test(stream.current())) { + override += " error"; + } else if (type == "word") { + wordAsValue(stream); + } else if (type == "interpolation") { + return pushContext(state, stream, "interpolation"); + } + return "prop"; + }; + + states.propBlock = function(type, _stream, state) { + if (type == "}") return popContext(state); + if (type == "word") { override = "property"; return "maybeprop"; } + return state.context.type; + }; + + states.parens = function(type, stream, state) { + if (type == "{" || type == "}") return popAndPass(type, stream, state); + if (type == ")") return popContext(state); + if (type == "(") return pushContext(state, stream, "parens"); + if (type == "interpolation") return pushContext(state, stream, "interpolation"); + if (type == "word") wordAsValue(stream); + return "parens"; + }; + + states.pseudo = function(type, stream, state) { + if (type == "meta") return "pseudo"; + + if (type == "word") { + override = "variable-3"; + return state.context.type; + } + return pass(type, stream, state); + }; + + states.documentTypes = function(type, stream, state) { + if (type == "word" && documentTypes.hasOwnProperty(stream.current())) { + override = "tag"; + return state.context.type; + } else { + return states.atBlock(type, stream, state); + } + }; + + states.atBlock = function(type, stream, state) { + if (type == "(") return pushContext(state, stream, "atBlock_parens"); + if (type == "}" || type == ";") return popAndPass(type, stream, state); + if (type == "{") return popContext(state) && pushContext(state, stream, allowNested ? "block" : "top"); + + if (type == "interpolation") return pushContext(state, stream, "interpolation"); + + if (type == "word") { + var word = stream.current().toLowerCase(); + if (word == "only" || word == "not" || word == "and" || word == "or") + override = "keyword"; + else if (mediaTypes.hasOwnProperty(word)) + override = "attribute"; + else if (mediaFeatures.hasOwnProperty(word)) + override = "property"; + else if (mediaValueKeywords.hasOwnProperty(word)) + override = "keyword"; + else if (propertyKeywords.hasOwnProperty(word)) + override = "property"; + else if (nonStandardPropertyKeywords.hasOwnProperty(word)) + override = "string-2"; + else if (valueKeywords.hasOwnProperty(word)) + override = "atom"; + else if (colorKeywords.hasOwnProperty(word)) + override = "keyword"; + else + override = "error"; + } + return state.context.type; + }; + + states.atComponentBlock = function(type, stream, state) { + if (type == "}") + return popAndPass(type, stream, state); + if (type == "{") + return popContext(state) && pushContext(state, stream, allowNested ? "block" : "top", false); + if (type == "word") + override = "error"; + return state.context.type; + }; + + states.atBlock_parens = function(type, stream, state) { + if (type == ")") return popContext(state); + if (type == "{" || type == "}") return popAndPass(type, stream, state, 2); + return states.atBlock(type, stream, state); + }; + + states.restricted_atBlock_before = function(type, stream, state) { + if (type == "{") + return pushContext(state, stream, "restricted_atBlock"); + if (type == "word" && state.stateArg == "@counter-style") { + override = "variable"; + return "restricted_atBlock_before"; + } + return pass(type, stream, state); + }; + + states.restricted_atBlock = function(type, stream, state) { + if (type == "}") { + state.stateArg = null; + return popContext(state); + } + if (type == "word") { + if ((state.stateArg == "@font-face" && !fontProperties.hasOwnProperty(stream.current().toLowerCase())) || + (state.stateArg == "@counter-style" && !counterDescriptors.hasOwnProperty(stream.current().toLowerCase()))) + override = "error"; + else + override = "property"; + return "maybeprop"; + } + return "restricted_atBlock"; + }; + + states.keyframes = function(type, stream, state) { + if (type == "word") { override = "variable"; return "keyframes"; } + if (type == "{") return pushContext(state, stream, "top"); + return pass(type, stream, state); + }; + + states.at = function(type, stream, state) { + if (type == ";") return popContext(state); + if (type == "{" || type == "}") return popAndPass(type, stream, state); + if (type == "word") override = "tag"; + else if (type == "hash") override = "builtin"; + return "at"; + }; + + states.interpolation = function(type, stream, state) { + if (type == "}") return popContext(state); + if (type == "{" || type == ";") return popAndPass(type, stream, state); + if (type == "word") override = "variable"; + else if (type != "variable" && type != "(" && type != ")") override = "error"; + return "interpolation"; + }; + + return { + startState: function(base) { + return {tokenize: null, + state: inline ? "block" : "top", + stateArg: null, + context: new Context(inline ? "block" : "top", base || 0, null)}; + }, + + token: function(stream, state) { + if (!state.tokenize && stream.eatSpace()) return null; + var style = (state.tokenize || tokenBase)(stream, state); + if (style && typeof style == "object") { + type = style[1]; + style = style[0]; + } + override = style; + if (type != "comment") + state.state = states[state.state](type, stream, state); + return override; + }, + + indent: function(state, textAfter) { + var cx = state.context, ch = textAfter && textAfter.charAt(0); + var indent = cx.indent; + if (cx.type == "prop" && (ch == "}" || ch == ")")) cx = cx.prev; + if (cx.prev) { + if (ch == "}" && (cx.type == "block" || cx.type == "top" || + cx.type == "interpolation" || cx.type == "restricted_atBlock")) { + // Resume indentation from parent context. + cx = cx.prev; + indent = cx.indent; + } else if (ch == ")" && (cx.type == "parens" || cx.type == "atBlock_parens") || + ch == "{" && (cx.type == "at" || cx.type == "atBlock")) { + // Dedent relative to current context. + indent = Math.max(0, cx.indent - indentUnit); + } + } + return indent; + }, + + electricChars: "}", + blockCommentStart: "/*", + blockCommentEnd: "*/", + blockCommentContinue: " * ", + lineComment: lineComment, + fold: "brace" + }; + }); + + function keySet(array) { + var keys = {}; + for (var i = 0; i < array.length; ++i) { + keys[array[i].toLowerCase()] = true; + } + return keys; + } + + var documentTypes_ = [ + "domain", "regexp", "url", "url-prefix" + ], documentTypes = keySet(documentTypes_); + + var mediaTypes_ = [ + "all", "aural", "braille", "handheld", "print", "projection", "screen", + "tty", "tv", "embossed" + ], mediaTypes = keySet(mediaTypes_); + + var mediaFeatures_ = [ + "width", "min-width", "max-width", "height", "min-height", "max-height", + "device-width", "min-device-width", "max-device-width", "device-height", + "min-device-height", "max-device-height", "aspect-ratio", + "min-aspect-ratio", "max-aspect-ratio", "device-aspect-ratio", + "min-device-aspect-ratio", "max-device-aspect-ratio", "color", "min-color", + "max-color", "color-index", "min-color-index", "max-color-index", + "monochrome", "min-monochrome", "max-monochrome", "resolution", + "min-resolution", "max-resolution", "scan", "grid", "orientation", + "device-pixel-ratio", "min-device-pixel-ratio", "max-device-pixel-ratio", + "pointer", "any-pointer", "hover", "any-hover" + ], mediaFeatures = keySet(mediaFeatures_); + + var mediaValueKeywords_ = [ + "landscape", "portrait", "none", "coarse", "fine", "on-demand", "hover", + "interlace", "progressive" + ], mediaValueKeywords = keySet(mediaValueKeywords_); + + var propertyKeywords_ = [ + "align-content", "align-items", "align-self", "alignment-adjust", + "alignment-baseline", "anchor-point", "animation", "animation-delay", + "animation-direction", "animation-duration", "animation-fill-mode", + "animation-iteration-count", "animation-name", "animation-play-state", + "animation-timing-function", "appearance", "azimuth", "backface-visibility", + "background", "background-attachment", "background-blend-mode", "background-clip", + "background-color", "background-image", "background-origin", "background-position", + "background-repeat", "background-size", "baseline-shift", "binding", + "bleed", "bookmark-label", "bookmark-level", "bookmark-state", + "bookmark-target", "border", "border-bottom", "border-bottom-color", + "border-bottom-left-radius", "border-bottom-right-radius", + "border-bottom-style", "border-bottom-width", "border-collapse", + "border-color", "border-image", "border-image-outset", + "border-image-repeat", "border-image-slice", "border-image-source", + "border-image-width", "border-left", "border-left-color", + "border-left-style", "border-left-width", "border-radius", "border-right", + "border-right-color", "border-right-style", "border-right-width", + "border-spacing", "border-style", "border-top", "border-top-color", + "border-top-left-radius", "border-top-right-radius", "border-top-style", + "border-top-width", "border-width", "bottom", "box-decoration-break", + "box-shadow", "box-sizing", "break-after", "break-before", "break-inside", + "caption-side", "caret-color", "clear", "clip", "color", "color-profile", "column-count", + "column-fill", "column-gap", "column-rule", "column-rule-color", + "column-rule-style", "column-rule-width", "column-span", "column-width", + "columns", "content", "counter-increment", "counter-reset", "crop", "cue", + "cue-after", "cue-before", "cursor", "direction", "display", + "dominant-baseline", "drop-initial-after-adjust", + "drop-initial-after-align", "drop-initial-before-adjust", + "drop-initial-before-align", "drop-initial-size", "drop-initial-value", + "elevation", "empty-cells", "fit", "fit-position", "flex", "flex-basis", + "flex-direction", "flex-flow", "flex-grow", "flex-shrink", "flex-wrap", + "float", "float-offset", "flow-from", "flow-into", "font", "font-feature-settings", + "font-family", "font-kerning", "font-language-override", "font-size", "font-size-adjust", + "font-stretch", "font-style", "font-synthesis", "font-variant", + "font-variant-alternates", "font-variant-caps", "font-variant-east-asian", + "font-variant-ligatures", "font-variant-numeric", "font-variant-position", + "font-weight", "grid", "grid-area", "grid-auto-columns", "grid-auto-flow", + "grid-auto-rows", "grid-column", "grid-column-end", "grid-column-gap", + "grid-column-start", "grid-gap", "grid-row", "grid-row-end", "grid-row-gap", + "grid-row-start", "grid-template", "grid-template-areas", "grid-template-columns", + "grid-template-rows", "hanging-punctuation", "height", "hyphens", + "icon", "image-orientation", "image-rendering", "image-resolution", + "inline-box-align", "justify-content", "justify-items", "justify-self", "left", "letter-spacing", + "line-break", "line-height", "line-stacking", "line-stacking-ruby", + "line-stacking-shift", "line-stacking-strategy", "list-style", + "list-style-image", "list-style-position", "list-style-type", "margin", + "margin-bottom", "margin-left", "margin-right", "margin-top", + "marks", "marquee-direction", "marquee-loop", + "marquee-play-count", "marquee-speed", "marquee-style", "max-height", + "max-width", "min-height", "min-width", "move-to", "nav-down", "nav-index", + "nav-left", "nav-right", "nav-up", "object-fit", "object-position", + "opacity", "order", "orphans", "outline", + "outline-color", "outline-offset", "outline-style", "outline-width", + "overflow", "overflow-style", "overflow-wrap", "overflow-x", "overflow-y", + "padding", "padding-bottom", "padding-left", "padding-right", "padding-top", + "page", "page-break-after", "page-break-before", "page-break-inside", + "page-policy", "pause", "pause-after", "pause-before", "perspective", + "perspective-origin", "pitch", "pitch-range", "place-content", "place-items", "place-self", "play-during", "position", + "presentation-level", "punctuation-trim", "quotes", "region-break-after", + "region-break-before", "region-break-inside", "region-fragment", + "rendering-intent", "resize", "rest", "rest-after", "rest-before", "richness", + "right", "rotation", "rotation-point", "ruby-align", "ruby-overhang", + "ruby-position", "ruby-span", "shape-image-threshold", "shape-inside", "shape-margin", + "shape-outside", "size", "speak", "speak-as", "speak-header", + "speak-numeral", "speak-punctuation", "speech-rate", "stress", "string-set", + "tab-size", "table-layout", "target", "target-name", "target-new", + "target-position", "text-align", "text-align-last", "text-decoration", + "text-decoration-color", "text-decoration-line", "text-decoration-skip", + "text-decoration-style", "text-emphasis", "text-emphasis-color", + "text-emphasis-position", "text-emphasis-style", "text-height", + "text-indent", "text-justify", "text-outline", "text-overflow", "text-shadow", + "text-size-adjust", "text-space-collapse", "text-transform", "text-underline-position", + "text-wrap", "top", "transform", "transform-origin", "transform-style", + "transition", "transition-delay", "transition-duration", + "transition-property", "transition-timing-function", "unicode-bidi", + "user-select", "vertical-align", "visibility", "voice-balance", "voice-duration", + "voice-family", "voice-pitch", "voice-range", "voice-rate", "voice-stress", + "voice-volume", "volume", "white-space", "widows", "width", "will-change", "word-break", + "word-spacing", "word-wrap", "z-index", + // SVG-specific + "clip-path", "clip-rule", "mask", "enable-background", "filter", "flood-color", + "flood-opacity", "lighting-color", "stop-color", "stop-opacity", "pointer-events", + "color-interpolation", "color-interpolation-filters", + "color-rendering", "fill", "fill-opacity", "fill-rule", "image-rendering", + "marker", "marker-end", "marker-mid", "marker-start", "shape-rendering", "stroke", + "stroke-dasharray", "stroke-dashoffset", "stroke-linecap", "stroke-linejoin", + "stroke-miterlimit", "stroke-opacity", "stroke-width", "text-rendering", + "baseline-shift", "dominant-baseline", "glyph-orientation-horizontal", + "glyph-orientation-vertical", "text-anchor", "writing-mode" + ], propertyKeywords = keySet(propertyKeywords_); + + var nonStandardPropertyKeywords_ = [ + "scrollbar-arrow-color", "scrollbar-base-color", "scrollbar-dark-shadow-color", + "scrollbar-face-color", "scrollbar-highlight-color", "scrollbar-shadow-color", + "scrollbar-3d-light-color", "scrollbar-track-color", "shape-inside", + "searchfield-cancel-button", "searchfield-decoration", "searchfield-results-button", + "searchfield-results-decoration", "zoom" + ], nonStandardPropertyKeywords = keySet(nonStandardPropertyKeywords_); + + var fontProperties_ = [ + "font-family", "src", "unicode-range", "font-variant", "font-feature-settings", + "font-stretch", "font-weight", "font-style" + ], fontProperties = keySet(fontProperties_); + + var counterDescriptors_ = [ + "additive-symbols", "fallback", "negative", "pad", "prefix", "range", + "speak-as", "suffix", "symbols", "system" + ], counterDescriptors = keySet(counterDescriptors_); + + var colorKeywords_ = [ + "aliceblue", "antiquewhite", "aqua", "aquamarine", "azure", "beige", + "bisque", "black", "blanchedalmond", "blue", "blueviolet", "brown", + "burlywood", "cadetblue", "chartreuse", "chocolate", "coral", "cornflowerblue", + "cornsilk", "crimson", "cyan", "darkblue", "darkcyan", "darkgoldenrod", + "darkgray", "darkgreen", "darkkhaki", "darkmagenta", "darkolivegreen", + "darkorange", "darkorchid", "darkred", "darksalmon", "darkseagreen", + "darkslateblue", "darkslategray", "darkturquoise", "darkviolet", + "deeppink", "deepskyblue", "dimgray", "dodgerblue", "firebrick", + "floralwhite", "forestgreen", "fuchsia", "gainsboro", "ghostwhite", + "gold", "goldenrod", "gray", "grey", "green", "greenyellow", "honeydew", + "hotpink", "indianred", "indigo", "ivory", "khaki", "lavender", + "lavenderblush", "lawngreen", "lemonchiffon", "lightblue", "lightcoral", + "lightcyan", "lightgoldenrodyellow", "lightgray", "lightgreen", "lightpink", + "lightsalmon", "lightseagreen", "lightskyblue", "lightslategray", + "lightsteelblue", "lightyellow", "lime", "limegreen", "linen", "magenta", + "maroon", "mediumaquamarine", "mediumblue", "mediumorchid", "mediumpurple", + "mediumseagreen", "mediumslateblue", "mediumspringgreen", "mediumturquoise", + "mediumvioletred", "midnightblue", "mintcream", "mistyrose", "moccasin", + "navajowhite", "navy", "oldlace", "olive", "olivedrab", "orange", "orangered", + "orchid", "palegoldenrod", "palegreen", "paleturquoise", "palevioletred", + "papayawhip", "peachpuff", "peru", "pink", "plum", "powderblue", + "purple", "rebeccapurple", "red", "rosybrown", "royalblue", "saddlebrown", + "salmon", "sandybrown", "seagreen", "seashell", "sienna", "silver", "skyblue", + "slateblue", "slategray", "snow", "springgreen", "steelblue", "tan", + "teal", "thistle", "tomato", "turquoise", "violet", "wheat", "white", + "whitesmoke", "yellow", "yellowgreen" + ], colorKeywords = keySet(colorKeywords_); + + var valueKeywords_ = [ + "above", "absolute", "activeborder", "additive", "activecaption", "afar", + "after-white-space", "ahead", "alias", "all", "all-scroll", "alphabetic", "alternate", + "always", "amharic", "amharic-abegede", "antialiased", "appworkspace", + "arabic-indic", "armenian", "asterisks", "attr", "auto", "auto-flow", "avoid", "avoid-column", "avoid-page", + "avoid-region", "background", "backwards", "baseline", "below", "bidi-override", "binary", + "bengali", "blink", "block", "block-axis", "bold", "bolder", "border", "border-box", + "both", "bottom", "break", "break-all", "break-word", "bullets", "button", "button-bevel", + "buttonface", "buttonhighlight", "buttonshadow", "buttontext", "calc", "cambodian", + "capitalize", "caps-lock-indicator", "caption", "captiontext", "caret", + "cell", "center", "checkbox", "circle", "cjk-decimal", "cjk-earthly-branch", + "cjk-heavenly-stem", "cjk-ideographic", "clear", "clip", "close-quote", + "col-resize", "collapse", "color", "color-burn", "color-dodge", "column", "column-reverse", + "compact", "condensed", "contain", "content", "contents", + "content-box", "context-menu", "continuous", "copy", "counter", "counters", "cover", "crop", + "cross", "crosshair", "currentcolor", "cursive", "cyclic", "darken", "dashed", "decimal", + "decimal-leading-zero", "default", "default-button", "dense", "destination-atop", + "destination-in", "destination-out", "destination-over", "devanagari", "difference", + "disc", "discard", "disclosure-closed", "disclosure-open", "document", + "dot-dash", "dot-dot-dash", + "dotted", "double", "down", "e-resize", "ease", "ease-in", "ease-in-out", "ease-out", + "element", "ellipse", "ellipsis", "embed", "end", "ethiopic", "ethiopic-abegede", + "ethiopic-abegede-am-et", "ethiopic-abegede-gez", "ethiopic-abegede-ti-er", + "ethiopic-abegede-ti-et", "ethiopic-halehame-aa-er", + "ethiopic-halehame-aa-et", "ethiopic-halehame-am-et", + "ethiopic-halehame-gez", "ethiopic-halehame-om-et", + "ethiopic-halehame-sid-et", "ethiopic-halehame-so-et", + "ethiopic-halehame-ti-er", "ethiopic-halehame-ti-et", "ethiopic-halehame-tig", + "ethiopic-numeric", "ew-resize", "exclusion", "expanded", "extends", "extra-condensed", + "extra-expanded", "fantasy", "fast", "fill", "fixed", "flat", "flex", "flex-end", "flex-start", "footnotes", + "forwards", "from", "geometricPrecision", "georgian", "graytext", "grid", "groove", + "gujarati", "gurmukhi", "hand", "hangul", "hangul-consonant", "hard-light", "hebrew", + "help", "hidden", "hide", "higher", "highlight", "highlighttext", + "hiragana", "hiragana-iroha", "horizontal", "hsl", "hsla", "hue", "icon", "ignore", + "inactiveborder", "inactivecaption", "inactivecaptiontext", "infinite", + "infobackground", "infotext", "inherit", "initial", "inline", "inline-axis", + "inline-block", "inline-flex", "inline-grid", "inline-table", "inset", "inside", "intrinsic", "invert", + "italic", "japanese-formal", "japanese-informal", "justify", "kannada", + "katakana", "katakana-iroha", "keep-all", "khmer", + "korean-hangul-formal", "korean-hanja-formal", "korean-hanja-informal", + "landscape", "lao", "large", "larger", "left", "level", "lighter", "lighten", + "line-through", "linear", "linear-gradient", "lines", "list-item", "listbox", "listitem", + "local", "logical", "loud", "lower", "lower-alpha", "lower-armenian", + "lower-greek", "lower-hexadecimal", "lower-latin", "lower-norwegian", + "lower-roman", "lowercase", "ltr", "luminosity", "malayalam", "match", "matrix", "matrix3d", + "media-controls-background", "media-current-time-display", + "media-fullscreen-button", "media-mute-button", "media-play-button", + "media-return-to-realtime-button", "media-rewind-button", + "media-seek-back-button", "media-seek-forward-button", "media-slider", + "media-sliderthumb", "media-time-remaining-display", "media-volume-slider", + "media-volume-slider-container", "media-volume-sliderthumb", "medium", + "menu", "menulist", "menulist-button", "menulist-text", + "menulist-textfield", "menutext", "message-box", "middle", "min-intrinsic", + "mix", "mongolian", "monospace", "move", "multiple", "multiply", "myanmar", "n-resize", + "narrower", "ne-resize", "nesw-resize", "no-close-quote", "no-drop", + "no-open-quote", "no-repeat", "none", "normal", "not-allowed", "nowrap", + "ns-resize", "numbers", "numeric", "nw-resize", "nwse-resize", "oblique", "octal", "opacity", "open-quote", + "optimizeLegibility", "optimizeSpeed", "oriya", "oromo", "outset", + "outside", "outside-shape", "overlay", "overline", "padding", "padding-box", + "painted", "page", "paused", "persian", "perspective", "plus-darker", "plus-lighter", + "pointer", "polygon", "portrait", "pre", "pre-line", "pre-wrap", "preserve-3d", + "progress", "push-button", "radial-gradient", "radio", "read-only", + "read-write", "read-write-plaintext-only", "rectangle", "region", + "relative", "repeat", "repeating-linear-gradient", + "repeating-radial-gradient", "repeat-x", "repeat-y", "reset", "reverse", + "rgb", "rgba", "ridge", "right", "rotate", "rotate3d", "rotateX", "rotateY", + "rotateZ", "round", "row", "row-resize", "row-reverse", "rtl", "run-in", "running", + "s-resize", "sans-serif", "saturation", "scale", "scale3d", "scaleX", "scaleY", "scaleZ", "screen", + "scroll", "scrollbar", "scroll-position", "se-resize", "searchfield", + "searchfield-cancel-button", "searchfield-decoration", + "searchfield-results-button", "searchfield-results-decoration", "self-start", "self-end", + "semi-condensed", "semi-expanded", "separate", "serif", "show", "sidama", + "simp-chinese-formal", "simp-chinese-informal", "single", + "skew", "skewX", "skewY", "skip-white-space", "slide", "slider-horizontal", + "slider-vertical", "sliderthumb-horizontal", "sliderthumb-vertical", "slow", + "small", "small-caps", "small-caption", "smaller", "soft-light", "solid", "somali", + "source-atop", "source-in", "source-out", "source-over", "space", "space-around", "space-between", "space-evenly", "spell-out", "square", + "square-button", "start", "static", "status-bar", "stretch", "stroke", "sub", + "subpixel-antialiased", "super", "sw-resize", "symbolic", "symbols", "system-ui", "table", + "table-caption", "table-cell", "table-column", "table-column-group", + "table-footer-group", "table-header-group", "table-row", "table-row-group", + "tamil", + "telugu", "text", "text-bottom", "text-top", "textarea", "textfield", "thai", + "thick", "thin", "threeddarkshadow", "threedface", "threedhighlight", + "threedlightshadow", "threedshadow", "tibetan", "tigre", "tigrinya-er", + "tigrinya-er-abegede", "tigrinya-et", "tigrinya-et-abegede", "to", "top", + "trad-chinese-formal", "trad-chinese-informal", "transform", + "translate", "translate3d", "translateX", "translateY", "translateZ", + "transparent", "ultra-condensed", "ultra-expanded", "underline", "unset", "up", + "upper-alpha", "upper-armenian", "upper-greek", "upper-hexadecimal", + "upper-latin", "upper-norwegian", "upper-roman", "uppercase", "urdu", "url", + "var", "vertical", "vertical-text", "visible", "visibleFill", "visiblePainted", + "visibleStroke", "visual", "w-resize", "wait", "wave", "wider", + "window", "windowframe", "windowtext", "words", "wrap", "wrap-reverse", "x-large", "x-small", "xor", + "xx-large", "xx-small" + ], valueKeywords = keySet(valueKeywords_); + + var allWords = documentTypes_.concat(mediaTypes_).concat(mediaFeatures_).concat(mediaValueKeywords_) + .concat(propertyKeywords_).concat(nonStandardPropertyKeywords_).concat(colorKeywords_) + .concat(valueKeywords_); + CodeMirror.registerHelper("hintWords", "css", allWords); + + function tokenCComment(stream, state) { + var maybeEnd = false, ch; + while ((ch = stream.next()) != null) { + if (maybeEnd && ch == "/") { + state.tokenize = null; + break; + } + maybeEnd = (ch == "*"); + } + return ["comment", "comment"]; + } + + CodeMirror.defineMIME("text/css", { + documentTypes: documentTypes, + mediaTypes: mediaTypes, + mediaFeatures: mediaFeatures, + mediaValueKeywords: mediaValueKeywords, + propertyKeywords: propertyKeywords, + nonStandardPropertyKeywords: nonStandardPropertyKeywords, + fontProperties: fontProperties, + counterDescriptors: counterDescriptors, + colorKeywords: colorKeywords, + valueKeywords: valueKeywords, + tokenHooks: { + "/": function(stream, state) { + if (!stream.eat("*")) return false; + state.tokenize = tokenCComment; + return tokenCComment(stream, state); + } + }, + name: "css" + }); + + CodeMirror.defineMIME("text/x-scss", { + mediaTypes: mediaTypes, + mediaFeatures: mediaFeatures, + mediaValueKeywords: mediaValueKeywords, + propertyKeywords: propertyKeywords, + nonStandardPropertyKeywords: nonStandardPropertyKeywords, + colorKeywords: colorKeywords, + valueKeywords: valueKeywords, + fontProperties: fontProperties, + allowNested: true, + lineComment: "//", + tokenHooks: { + "/": function(stream, state) { + if (stream.eat("/")) { + stream.skipToEnd(); + return ["comment", "comment"]; + } else if (stream.eat("*")) { + state.tokenize = tokenCComment; + return tokenCComment(stream, state); + } else { + return ["operator", "operator"]; + } + }, + ":": function(stream) { + if (stream.match(/\s*\{/, false)) + return [null, null] + return false; + }, + "$": function(stream) { + stream.match(/^[\w-]+/); + if (stream.match(/^\s*:/, false)) + return ["variable-2", "variable-definition"]; + return ["variable-2", "variable"]; + }, + "#": function(stream) { + if (!stream.eat("{")) return false; + return [null, "interpolation"]; + } + }, + name: "css", + helperType: "scss" + }); + + CodeMirror.defineMIME("text/x-less", { + mediaTypes: mediaTypes, + mediaFeatures: mediaFeatures, + mediaValueKeywords: mediaValueKeywords, + propertyKeywords: propertyKeywords, + nonStandardPropertyKeywords: nonStandardPropertyKeywords, + colorKeywords: colorKeywords, + valueKeywords: valueKeywords, + fontProperties: fontProperties, + allowNested: true, + lineComment: "//", + tokenHooks: { + "/": function(stream, state) { + if (stream.eat("/")) { + stream.skipToEnd(); + return ["comment", "comment"]; + } else if (stream.eat("*")) { + state.tokenize = tokenCComment; + return tokenCComment(stream, state); + } else { + return ["operator", "operator"]; + } + }, + "@": function(stream) { + if (stream.eat("{")) return [null, "interpolation"]; + if (stream.match(/^(charset|document|font-face|import|(-(moz|ms|o|webkit)-)?keyframes|media|namespace|page|supports)\b/i, false)) return false; + stream.eatWhile(/[\w\\\-]/); + if (stream.match(/^\s*:/, false)) + return ["variable-2", "variable-definition"]; + return ["variable-2", "variable"]; + }, + "&": function() { + return ["atom", "atom"]; + } + }, + name: "css", + helperType: "less" + }); + + CodeMirror.defineMIME("text/x-gss", { + documentTypes: documentTypes, + mediaTypes: mediaTypes, + mediaFeatures: mediaFeatures, + propertyKeywords: propertyKeywords, + nonStandardPropertyKeywords: nonStandardPropertyKeywords, + fontProperties: fontProperties, + counterDescriptors: counterDescriptors, + colorKeywords: colorKeywords, + valueKeywords: valueKeywords, + supportsAtComponent: true, + tokenHooks: { + "/": function(stream, state) { + if (!stream.eat("*")) return false; + state.tokenize = tokenCComment; + return tokenCComment(stream, state); + } + }, + name: "css", + helperType: "gss" + }); + + }); + + +/***/ }), +/* 11 */ +/***/ (function(module, exports, __webpack_require__) { + + // CodeMirror, copyright (c) by Marijn Haverbeke and others + // Distributed under an MIT license: http://codemirror.net/LICENSE + + (function(mod) { + if (true) // CommonJS + mod(__webpack_require__(2), __webpack_require__(9), __webpack_require__(8), __webpack_require__(10)); + else if (typeof define == "function" && define.amd) // AMD + define(["../../lib/codemirror", "../xml/xml", "../javascript/javascript", "../css/css"], mod); + else // Plain browser env + mod(CodeMirror); + })(function(CodeMirror) { + "use strict"; + + var defaultTags = { + script: [ + ["lang", /(javascript|babel)/i, "javascript"], + ["type", /^(?:text|application)\/(?:x-)?(?:java|ecma)script$|^module$|^$/i, "javascript"], + ["type", /./, "text/plain"], + [null, null, "javascript"] + ], + style: [ + ["lang", /^css$/i, "css"], + ["type", /^(text\/)?(x-)?(stylesheet|css)$/i, "css"], + ["type", /./, "text/plain"], + [null, null, "css"] + ] + }; + + function maybeBackup(stream, pat, style) { + var cur = stream.current(), close = cur.search(pat); + if (close > -1) { + stream.backUp(cur.length - close); + } else if (cur.match(/<\/?$/)) { + stream.backUp(cur.length); + if (!stream.match(pat, false)) stream.match(cur); + } + return style; + } + + var attrRegexpCache = {}; + function getAttrRegexp(attr) { + var regexp = attrRegexpCache[attr]; + if (regexp) return regexp; + return attrRegexpCache[attr] = new RegExp("\\s+" + attr + "\\s*=\\s*('|\")?([^'\"]+)('|\")?\\s*"); + } + + function getAttrValue(text, attr) { + var match = text.match(getAttrRegexp(attr)) + return match ? /^\s*(.*?)\s*$/.exec(match[2])[1] : "" + } + + function getTagRegexp(tagName, anchored) { + return new RegExp((anchored ? "^" : "") + "<\/\s*" + tagName + "\s*>", "i"); + } + + function addTags(from, to) { + for (var tag in from) { + var dest = to[tag] || (to[tag] = []); + var source = from[tag]; + for (var i = source.length - 1; i >= 0; i--) + dest.unshift(source[i]) + } + } + + function findMatchingMode(tagInfo, tagText) { + for (var i = 0; i < tagInfo.length; i++) { + var spec = tagInfo[i]; + if (!spec[0] || spec[1].test(getAttrValue(tagText, spec[0]))) return spec[2]; + } + } + + CodeMirror.defineMode("htmlmixed", function (config, parserConfig) { + var htmlMode = CodeMirror.getMode(config, { + name: "xml", + htmlMode: true, + multilineTagIndentFactor: parserConfig.multilineTagIndentFactor, + multilineTagIndentPastTag: parserConfig.multilineTagIndentPastTag + }); + + var tags = {}; + var configTags = parserConfig && parserConfig.tags, configScript = parserConfig && parserConfig.scriptTypes; + addTags(defaultTags, tags); + if (configTags) addTags(configTags, tags); + if (configScript) for (var i = configScript.length - 1; i >= 0; i--) + tags.script.unshift(["type", configScript[i].matches, configScript[i].mode]) + + function html(stream, state) { + var style = htmlMode.token(stream, state.htmlState), tag = /\btag\b/.test(style), tagName + if (tag && !/[<>\s\/]/.test(stream.current()) && + (tagName = state.htmlState.tagName && state.htmlState.tagName.toLowerCase()) && + tags.hasOwnProperty(tagName)) { + state.inTag = tagName + " " + } else if (state.inTag && tag && />$/.test(stream.current())) { + var inTag = /^([\S]+) (.*)/.exec(state.inTag) + state.inTag = null + var modeSpec = stream.current() == ">" && findMatchingMode(tags[inTag[1]], inTag[2]) + var mode = CodeMirror.getMode(config, modeSpec) + var endTagA = getTagRegexp(inTag[1], true), endTag = getTagRegexp(inTag[1], false); + state.token = function (stream, state) { + if (stream.match(endTagA, false)) { + state.token = html; + state.localState = state.localMode = null; + return null; + } + return maybeBackup(stream, endTag, state.localMode.token(stream, state.localState)); + }; + state.localMode = mode; + state.localState = CodeMirror.startState(mode, htmlMode.indent(state.htmlState, "")); + } else if (state.inTag) { + state.inTag += stream.current() + if (stream.eol()) state.inTag += " " + } + return style; + }; + + return { + startState: function () { + var state = CodeMirror.startState(htmlMode); + return {token: html, inTag: null, localMode: null, localState: null, htmlState: state}; + }, + + copyState: function (state) { + var local; + if (state.localState) { + local = CodeMirror.copyState(state.localMode, state.localState); + } + return {token: state.token, inTag: state.inTag, + localMode: state.localMode, localState: local, + htmlState: CodeMirror.copyState(htmlMode, state.htmlState)}; + }, + + token: function (stream, state) { + return state.token(stream, state); + }, + + indent: function (state, textAfter, line) { + if (!state.localMode || /^\s*<\//.test(textAfter)) + return htmlMode.indent(state.htmlState, textAfter); + else if (state.localMode.indent) + return state.localMode.indent(state.localState, textAfter, line); + else + return CodeMirror.Pass; + }, + + innerMode: function (state) { + return {state: state.localState || state.htmlState, mode: state.localMode || htmlMode}; + } + }; + }, "xml", "javascript", "css"); + + CodeMirror.defineMIME("text/html", "htmlmixed"); + }); + + +/***/ }), +/* 12 */ +/***/ (function(module, exports, __webpack_require__) { + + // CodeMirror, copyright (c) by Marijn Haverbeke and others + // Distributed under an MIT license: http://codemirror.net/LICENSE + + (function(mod) { + if (true) // CommonJS + mod(__webpack_require__(2), __webpack_require__(9), __webpack_require__(8)) + else if (typeof define == "function" && define.amd) // AMD + define(["../../lib/codemirror", "../xml/xml", "../javascript/javascript"], mod) + else // Plain browser env + mod(CodeMirror) + })(function(CodeMirror) { + "use strict" + + // Depth means the amount of open braces in JS context, in XML + // context 0 means not in tag, 1 means in tag, and 2 means in tag + // and js block comment. + function Context(state, mode, depth, prev) { + this.state = state; this.mode = mode; this.depth = depth; this.prev = prev + } + + function copyContext(context) { + return new Context(CodeMirror.copyState(context.mode, context.state), + context.mode, + context.depth, + context.prev && copyContext(context.prev)) + } + + CodeMirror.defineMode("jsx", function(config, modeConfig) { + var xmlMode = CodeMirror.getMode(config, {name: "xml", allowMissing: true, multilineTagIndentPastTag: false, allowMissingTagName: true}) + var jsMode = CodeMirror.getMode(config, modeConfig && modeConfig.base || "javascript") + + function flatXMLIndent(state) { + var tagName = state.tagName + state.tagName = null + var result = xmlMode.indent(state, "") + state.tagName = tagName + return result + } + + function token(stream, state) { + if (state.context.mode == xmlMode) + return xmlToken(stream, state, state.context) + else + return jsToken(stream, state, state.context) + } + + function xmlToken(stream, state, cx) { + if (cx.depth == 2) { // Inside a JS /* */ comment + if (stream.match(/^.*?\*\//)) cx.depth = 1 + else stream.skipToEnd() + return "comment" + } + + if (stream.peek() == "{") { + xmlMode.skipAttribute(cx.state) + + var indent = flatXMLIndent(cx.state), xmlContext = cx.state.context + // If JS starts on same line as tag + if (xmlContext && stream.match(/^[^>]*>\s*$/, false)) { + while (xmlContext.prev && !xmlContext.startOfLine) + xmlContext = xmlContext.prev + // If tag starts the line, use XML indentation level + if (xmlContext.startOfLine) indent -= config.indentUnit + // Else use JS indentation level + else if (cx.prev.state.lexical) indent = cx.prev.state.lexical.indented + // Else if inside of tag + } else if (cx.depth == 1) { + indent += config.indentUnit + } + + state.context = new Context(CodeMirror.startState(jsMode, indent), + jsMode, 0, state.context) + return null + } + + if (cx.depth == 1) { // Inside of tag + if (stream.peek() == "<") { // Tag inside of tag + xmlMode.skipAttribute(cx.state) + state.context = new Context(CodeMirror.startState(xmlMode, flatXMLIndent(cx.state)), + xmlMode, 0, state.context) + return null + } else if (stream.match("//")) { + stream.skipToEnd() + return "comment" + } else if (stream.match("/*")) { + cx.depth = 2 + return token(stream, state) + } + } + + var style = xmlMode.token(stream, cx.state), cur = stream.current(), stop + if (/\btag\b/.test(style)) { + if (/>$/.test(cur)) { + if (cx.state.context) cx.depth = 0 + else state.context = state.context.prev + } else if (/^ -1) { + stream.backUp(cur.length - stop) + } + return style + } + + function jsToken(stream, state, cx) { + if (stream.peek() == "<" && jsMode.expressionAllowed(stream, cx.state)) { + jsMode.skipExpression(cx.state) + state.context = new Context(CodeMirror.startState(xmlMode, jsMode.indent(cx.state, "")), + xmlMode, 0, state.context) + return null + } + + var style = jsMode.token(stream, cx.state) + if (!style && cx.depth != null) { + var cur = stream.current() + if (cur == "{") { + cx.depth++ + } else if (cur == "}") { + if (--cx.depth == 0) state.context = state.context.prev + } + } + return style + } + + return { + startState: function() { + return {context: new Context(CodeMirror.startState(jsMode), jsMode)} + }, + + copyState: function(state) { + return {context: copyContext(state.context)} + }, + + token: token, + + indent: function(state, textAfter, fullLine) { + return state.context.mode.indent(state.context.state, textAfter, fullLine) + }, + + innerMode: function(state) { + return state.context + } + } + }, "xml", "javascript") + + CodeMirror.defineMIME("text/jsx", "jsx") + CodeMirror.defineMIME("text/typescript-jsx", {name: "jsx", base: {name: "javascript", typescript: true}}) + }); + + +/***/ }), +/* 13 */ +/***/ (function(module, exports, __webpack_require__) { + + // CodeMirror, copyright (c) by Marijn Haverbeke and others + // Distributed under an MIT license: http://codemirror.net/LICENSE + + /** + * Link to the project's GitHub page: + * https://github.com/pickhardt/coffeescript-codemirror-mode + */ + (function(mod) { + if (true) // CommonJS + mod(__webpack_require__(2)); + else if (typeof define == "function" && define.amd) // AMD + define(["../../lib/codemirror"], mod); + else // Plain browser env + mod(CodeMirror); + })(function(CodeMirror) { + "use strict"; + + CodeMirror.defineMode("coffeescript", function(conf, parserConf) { + var ERRORCLASS = "error"; + + function wordRegexp(words) { + return new RegExp("^((" + words.join(")|(") + "))\\b"); + } + + var operators = /^(?:->|=>|\+[+=]?|-[\-=]?|\*[\*=]?|\/[\/=]?|[=!]=|<[><]?=?|>>?=?|%=?|&=?|\|=?|\^=?|\~|!|\?|(or|and|\|\||&&|\?)=)/; + var delimiters = /^(?:[()\[\]{},:`=;]|\.\.?\.?)/; + var identifiers = /^[_A-Za-z$][_A-Za-z$0-9]*/; + var atProp = /^@[_A-Za-z$][_A-Za-z$0-9]*/; + + var wordOperators = wordRegexp(["and", "or", "not", + "is", "isnt", "in", + "instanceof", "typeof"]); + var indentKeywords = ["for", "while", "loop", "if", "unless", "else", + "switch", "try", "catch", "finally", "class"]; + var commonKeywords = ["break", "by", "continue", "debugger", "delete", + "do", "in", "of", "new", "return", "then", + "this", "@", "throw", "when", "until", "extends"]; + + var keywords = wordRegexp(indentKeywords.concat(commonKeywords)); + + indentKeywords = wordRegexp(indentKeywords); + + + var stringPrefixes = /^('{3}|\"{3}|['\"])/; + var regexPrefixes = /^(\/{3}|\/)/; + var commonConstants = ["Infinity", "NaN", "undefined", "null", "true", "false", "on", "off", "yes", "no"]; + var constants = wordRegexp(commonConstants); + + // Tokenizers + function tokenBase(stream, state) { + // Handle scope changes + if (stream.sol()) { + if (state.scope.align === null) state.scope.align = false; + var scopeOffset = state.scope.offset; + if (stream.eatSpace()) { + var lineOffset = stream.indentation(); + if (lineOffset > scopeOffset && state.scope.type == "coffee") { + return "indent"; + } else if (lineOffset < scopeOffset) { + return "dedent"; + } + return null; + } else { + if (scopeOffset > 0) { + dedent(stream, state); + } + } + } + if (stream.eatSpace()) { + return null; + } + + var ch = stream.peek(); + + // Handle docco title comment (single line) + if (stream.match("####")) { + stream.skipToEnd(); + return "comment"; + } + + // Handle multi line comments + if (stream.match("###")) { + state.tokenize = longComment; + return state.tokenize(stream, state); + } + + // Single line comment + if (ch === "#") { + stream.skipToEnd(); + return "comment"; + } + + // Handle number literals + if (stream.match(/^-?[0-9\.]/, false)) { + var floatLiteral = false; + // Floats + if (stream.match(/^-?\d*\.\d+(e[\+\-]?\d+)?/i)) { + floatLiteral = true; + } + if (stream.match(/^-?\d+\.\d*/)) { + floatLiteral = true; + } + if (stream.match(/^-?\.\d+/)) { + floatLiteral = true; + } + + if (floatLiteral) { + // prevent from getting extra . on 1.. + if (stream.peek() == "."){ + stream.backUp(1); + } + return "number"; + } + // Integers + var intLiteral = false; + // Hex + if (stream.match(/^-?0x[0-9a-f]+/i)) { + intLiteral = true; + } + // Decimal + if (stream.match(/^-?[1-9]\d*(e[\+\-]?\d+)?/)) { + intLiteral = true; + } + // Zero by itself with no other piece of number. + if (stream.match(/^-?0(?![\dx])/i)) { + intLiteral = true; + } + if (intLiteral) { + return "number"; + } + } + + // Handle strings + if (stream.match(stringPrefixes)) { + state.tokenize = tokenFactory(stream.current(), false, "string"); + return state.tokenize(stream, state); + } + // Handle regex literals + if (stream.match(regexPrefixes)) { + if (stream.current() != "/" || stream.match(/^.*\//, false)) { // prevent highlight of division + state.tokenize = tokenFactory(stream.current(), true, "string-2"); + return state.tokenize(stream, state); + } else { + stream.backUp(1); + } + } + + + + // Handle operators and delimiters + if (stream.match(operators) || stream.match(wordOperators)) { + return "operator"; + } + if (stream.match(delimiters)) { + return "punctuation"; + } + + if (stream.match(constants)) { + return "atom"; + } + + if (stream.match(atProp) || state.prop && stream.match(identifiers)) { + return "property"; + } + + if (stream.match(keywords)) { + return "keyword"; + } + + if (stream.match(identifiers)) { + return "variable"; + } + + // Handle non-detected items + stream.next(); + return ERRORCLASS; + } + + function tokenFactory(delimiter, singleline, outclass) { + return function(stream, state) { + while (!stream.eol()) { + stream.eatWhile(/[^'"\/\\]/); + if (stream.eat("\\")) { + stream.next(); + if (singleline && stream.eol()) { + return outclass; + } + } else if (stream.match(delimiter)) { + state.tokenize = tokenBase; + return outclass; + } else { + stream.eat(/['"\/]/); + } + } + if (singleline) { + if (parserConf.singleLineStringErrors) { + outclass = ERRORCLASS; + } else { + state.tokenize = tokenBase; + } + } + return outclass; + }; + } + + function longComment(stream, state) { + while (!stream.eol()) { + stream.eatWhile(/[^#]/); + if (stream.match("###")) { + state.tokenize = tokenBase; + break; + } + stream.eatWhile("#"); + } + return "comment"; + } + + function indent(stream, state, type) { + type = type || "coffee"; + var offset = 0, align = false, alignOffset = null; + for (var scope = state.scope; scope; scope = scope.prev) { + if (scope.type === "coffee" || scope.type == "}") { + offset = scope.offset + conf.indentUnit; + break; + } + } + if (type !== "coffee") { + align = null; + alignOffset = stream.column() + stream.current().length; + } else if (state.scope.align) { + state.scope.align = false; + } + state.scope = { + offset: offset, + type: type, + prev: state.scope, + align: align, + alignOffset: alignOffset + }; + } + + function dedent(stream, state) { + if (!state.scope.prev) return; + if (state.scope.type === "coffee") { + var _indent = stream.indentation(); + var matched = false; + for (var scope = state.scope; scope; scope = scope.prev) { + if (_indent === scope.offset) { + matched = true; + break; + } + } + if (!matched) { + return true; + } + while (state.scope.prev && state.scope.offset !== _indent) { + state.scope = state.scope.prev; + } + return false; + } else { + state.scope = state.scope.prev; + return false; + } + } + + function tokenLexer(stream, state) { + var style = state.tokenize(stream, state); + var current = stream.current(); + + // Handle scope changes. + if (current === "return") { + state.dedent = true; + } + if (((current === "->" || current === "=>") && stream.eol()) + || style === "indent") { + indent(stream, state); + } + var delimiter_index = "[({".indexOf(current); + if (delimiter_index !== -1) { + indent(stream, state, "])}".slice(delimiter_index, delimiter_index+1)); + } + if (indentKeywords.exec(current)){ + indent(stream, state); + } + if (current == "then"){ + dedent(stream, state); + } + + + if (style === "dedent") { + if (dedent(stream, state)) { + return ERRORCLASS; + } + } + delimiter_index = "])}".indexOf(current); + if (delimiter_index !== -1) { + while (state.scope.type == "coffee" && state.scope.prev) + state.scope = state.scope.prev; + if (state.scope.type == current) + state.scope = state.scope.prev; + } + if (state.dedent && stream.eol()) { + if (state.scope.type == "coffee" && state.scope.prev) + state.scope = state.scope.prev; + state.dedent = false; + } + + return style; + } + + var external = { + startState: function(basecolumn) { + return { + tokenize: tokenBase, + scope: {offset:basecolumn || 0, type:"coffee", prev: null, align: false}, + prop: false, + dedent: 0 + }; + }, + + token: function(stream, state) { + var fillAlign = state.scope.align === null && state.scope; + if (fillAlign && stream.sol()) fillAlign.align = false; + + var style = tokenLexer(stream, state); + if (style && style != "comment") { + if (fillAlign) fillAlign.align = true; + state.prop = style == "punctuation" && stream.current() == "." + } + + return style; + }, + + indent: function(state, text) { + if (state.tokenize != tokenBase) return 0; + var scope = state.scope; + var closer = text && "])}".indexOf(text.charAt(0)) > -1; + if (closer) while (scope.type == "coffee" && scope.prev) scope = scope.prev; + var closes = closer && scope.type === text.charAt(0); + if (scope.align) + return scope.alignOffset - (closes ? 1 : 0); + else + return (closes ? scope.prev : scope).offset; + }, + + lineComment: "#", + fold: "indent" + }; + return external; + }); + + // IANA registered media type + // https://www.iana.org/assignments/media-types/ + CodeMirror.defineMIME("application/vnd.coffeescript", "coffeescript"); + + CodeMirror.defineMIME("text/x-coffeescript", "coffeescript"); + CodeMirror.defineMIME("text/coffeescript", "coffeescript"); + + }); + + +/***/ }), +/* 14 */ +/***/ (function(module, exports, __webpack_require__) { + + // CodeMirror, copyright (c) by Marijn Haverbeke and others + // Distributed under an MIT license: http://codemirror.net/LICENSE + + (function(mod) { + if (true) // CommonJS + mod(__webpack_require__(2)); + else if (typeof define == "function" && define.amd) // AMD + define(["../../lib/codemirror"], mod); + else // Plain browser env + mod(CodeMirror); + })(function(CodeMirror) { + "use strict"; + + CodeMirror.defineMode("elm", function() { + + function switchState(source, setState, f) { + setState(f); + return f(source, setState); + } + + // These should all be Unicode extended, as per the Haskell 2010 report + var smallRE = /[a-z_]/; + var largeRE = /[A-Z]/; + var digitRE = /[0-9]/; + var hexitRE = /[0-9A-Fa-f]/; + var octitRE = /[0-7]/; + var idRE = /[a-z_A-Z0-9\']/; + var symbolRE = /[-!#$%&*+.\/<=>?@\\^|~:\u03BB\u2192]/; + var specialRE = /[(),;[\]`{}]/; + var whiteCharRE = /[ \t\v\f]/; // newlines are handled in tokenizer + + function normal() { + return function (source, setState) { + if (source.eatWhile(whiteCharRE)) { + return null; + } + + var ch = source.next(); + if (specialRE.test(ch)) { + if (ch == '{' && source.eat('-')) { + var t = "comment"; + if (source.eat('#')) t = "meta"; + return switchState(source, setState, ncomment(t, 1)); + } + return null; + } + + if (ch == '\'') { + if (source.eat('\\')) + source.next(); // should handle other escapes here + else + source.next(); + + if (source.eat('\'')) + return "string"; + return "error"; + } + + if (ch == '"') { + return switchState(source, setState, stringLiteral); + } + + if (largeRE.test(ch)) { + source.eatWhile(idRE); + if (source.eat('.')) + return "qualifier"; + return "variable-2"; + } + + if (smallRE.test(ch)) { + var isDef = source.pos === 1; + source.eatWhile(idRE); + return isDef ? "type" : "variable"; + } + + if (digitRE.test(ch)) { + if (ch == '0') { + if (source.eat(/[xX]/)) { + source.eatWhile(hexitRE); // should require at least 1 + return "integer"; + } + if (source.eat(/[oO]/)) { + source.eatWhile(octitRE); // should require at least 1 + return "number"; + } + } + source.eatWhile(digitRE); + var t = "number"; + if (source.eat('.')) { + t = "number"; + source.eatWhile(digitRE); // should require at least 1 + } + if (source.eat(/[eE]/)) { + t = "number"; + source.eat(/[-+]/); + source.eatWhile(digitRE); // should require at least 1 + } + return t; + } + + if (symbolRE.test(ch)) { + if (ch == '-' && source.eat(/-/)) { + source.eatWhile(/-/); + if (!source.eat(symbolRE)) { + source.skipToEnd(); + return "comment"; + } + } + source.eatWhile(symbolRE); + return "builtin"; + } + + return "error"; + } + } + + function ncomment(type, nest) { + if (nest == 0) { + return normal(); + } + return function(source, setState) { + var currNest = nest; + while (!source.eol()) { + var ch = source.next(); + if (ch == '{' && source.eat('-')) { + ++currNest; + } else if (ch == '-' && source.eat('}')) { + --currNest; + if (currNest == 0) { + setState(normal()); + return type; + } + } + } + setState(ncomment(type, currNest)); + return type; + } + } + + function stringLiteral(source, setState) { + while (!source.eol()) { + var ch = source.next(); + if (ch == '"') { + setState(normal()); + return "string"; + } + if (ch == '\\') { + if (source.eol() || source.eat(whiteCharRE)) { + setState(stringGap); + return "string"; + } + if (!source.eat('&')) source.next(); // should handle other escapes here + } + } + setState(normal()); + return "error"; + } + + function stringGap(source, setState) { + if (source.eat('\\')) { + return switchState(source, setState, stringLiteral); + } + source.next(); + setState(normal()); + return "error"; + } + + + var wellKnownWords = (function() { + var wkw = {}; + + var keywords = [ + "case", "of", "as", + "if", "then", "else", + "let", "in", + "infix", "infixl", "infixr", + "type", "alias", + "input", "output", "foreign", "loopback", + "module", "where", "import", "exposing", + "_", "..", "|", ":", "=", "\\", "\"", "->", "<-" + ]; + + for (var i = keywords.length; i--;) + wkw[keywords[i]] = "keyword"; + + return wkw; + })(); + + + + return { + startState: function () { return { f: normal() }; }, + copyState: function (s) { return { f: s.f }; }, + + token: function(stream, state) { + var t = state.f(stream, function(s) { state.f = s; }); + var w = stream.current(); + return (wellKnownWords.hasOwnProperty(w)) ? wellKnownWords[w] : t; + } + }; + + }); + + CodeMirror.defineMIME("text/x-elm", "elm"); + }); + + +/***/ }), +/* 15 */ +/***/ (function(module, exports, __webpack_require__) { + + // CodeMirror, copyright (c) by Marijn Haverbeke and others + // Distributed under an MIT license: http://codemirror.net/LICENSE + + (function(mod) { + if (true) // CommonJS + mod(__webpack_require__(2)); + else if (typeof define == "function" && define.amd) // AMD + define(["../../lib/codemirror"], mod); + else // Plain browser env + mod(CodeMirror); + })(function(CodeMirror) { + "use strict"; + + function Context(indented, column, type, info, align, prev) { + this.indented = indented; + this.column = column; + this.type = type; + this.info = info; + this.align = align; + this.prev = prev; + } + function pushContext(state, col, type, info) { + var indent = state.indented; + if (state.context && state.context.type == "statement" && type != "statement") + indent = state.context.indented; + return state.context = new Context(indent, col, type, info, null, state.context); + } + function popContext(state) { + var t = state.context.type; + if (t == ")" || t == "]" || t == "}") + state.indented = state.context.indented; + return state.context = state.context.prev; + } + + function typeBefore(stream, state, pos) { + if (state.prevToken == "variable" || state.prevToken == "type") return true; + if (/\S(?:[^- ]>|[*\]])\s*$|\*$/.test(stream.string.slice(0, pos))) return true; + if (state.typeAtEndOfLine && stream.column() == stream.indentation()) return true; + } + + function isTopScope(context) { + for (;;) { + if (!context || context.type == "top") return true; + if (context.type == "}" && context.prev.info != "namespace") return false; + context = context.prev; + } + } + + CodeMirror.defineMode("clike", function(config, parserConfig) { + var indentUnit = config.indentUnit, + statementIndentUnit = parserConfig.statementIndentUnit || indentUnit, + dontAlignCalls = parserConfig.dontAlignCalls, + keywords = parserConfig.keywords || {}, + types = parserConfig.types || {}, + builtin = parserConfig.builtin || {}, + blockKeywords = parserConfig.blockKeywords || {}, + defKeywords = parserConfig.defKeywords || {}, + atoms = parserConfig.atoms || {}, + hooks = parserConfig.hooks || {}, + multiLineStrings = parserConfig.multiLineStrings, + indentStatements = parserConfig.indentStatements !== false, + indentSwitch = parserConfig.indentSwitch !== false, + namespaceSeparator = parserConfig.namespaceSeparator, + isPunctuationChar = parserConfig.isPunctuationChar || /[\[\]{}\(\),;\:\.]/, + numberStart = parserConfig.numberStart || /[\d\.]/, + number = parserConfig.number || /^(?:0x[a-f\d]+|0b[01]+|(?:\d+\.?\d*|\.\d+)(?:e[-+]?\d+)?)(u|ll?|l|f)?/i, + isOperatorChar = parserConfig.isOperatorChar || /[+\-*&%=<>!?|\/]/, + isIdentifierChar = parserConfig.isIdentifierChar || /[\w\$_\xa1-\uffff]/; + + var curPunc, isDefKeyword; + + function tokenBase(stream, state) { + var ch = stream.next(); + if (hooks[ch]) { + var result = hooks[ch](stream, state); + if (result !== false) return result; + } + if (ch == '"' || ch == "'") { + state.tokenize = tokenString(ch); + return state.tokenize(stream, state); + } + if (isPunctuationChar.test(ch)) { + curPunc = ch; + return null; + } + if (numberStart.test(ch)) { + stream.backUp(1) + if (stream.match(number)) return "number" + stream.next() + } + if (ch == "/") { + if (stream.eat("*")) { + state.tokenize = tokenComment; + return tokenComment(stream, state); + } + if (stream.eat("/")) { + stream.skipToEnd(); + return "comment"; + } + } + if (isOperatorChar.test(ch)) { + while (!stream.match(/^\/[\/*]/, false) && stream.eat(isOperatorChar)) {} + return "operator"; + } + stream.eatWhile(isIdentifierChar); + if (namespaceSeparator) while (stream.match(namespaceSeparator)) + stream.eatWhile(isIdentifierChar); + + var cur = stream.current(); + if (contains(keywords, cur)) { + if (contains(blockKeywords, cur)) curPunc = "newstatement"; + if (contains(defKeywords, cur)) isDefKeyword = true; + return "keyword"; + } + if (contains(types, cur)) return "type"; + if (contains(builtin, cur)) { + if (contains(blockKeywords, cur)) curPunc = "newstatement"; + return "builtin"; + } + if (contains(atoms, cur)) return "atom"; + return "variable"; + } + + function tokenString(quote) { + return function(stream, state) { + var escaped = false, next, end = false; + while ((next = stream.next()) != null) { + if (next == quote && !escaped) {end = true; break;} + escaped = !escaped && next == "\\"; + } + if (end || !(escaped || multiLineStrings)) + state.tokenize = null; + return "string"; + }; + } + + function tokenComment(stream, state) { + var maybeEnd = false, ch; + while (ch = stream.next()) { + if (ch == "/" && maybeEnd) { + state.tokenize = null; + break; + } + maybeEnd = (ch == "*"); + } + return "comment"; + } + + function maybeEOL(stream, state) { + if (parserConfig.typeFirstDefinitions && stream.eol() && isTopScope(state.context)) + state.typeAtEndOfLine = typeBefore(stream, state, stream.pos) + } + + // Interface + + return { + startState: function(basecolumn) { + return { + tokenize: null, + context: new Context((basecolumn || 0) - indentUnit, 0, "top", null, false), + indented: 0, + startOfLine: true, + prevToken: null + }; + }, + + token: function(stream, state) { + var ctx = state.context; + if (stream.sol()) { + if (ctx.align == null) ctx.align = false; + state.indented = stream.indentation(); + state.startOfLine = true; + } + if (stream.eatSpace()) { maybeEOL(stream, state); return null; } + curPunc = isDefKeyword = null; + var style = (state.tokenize || tokenBase)(stream, state); + if (style == "comment" || style == "meta") return style; + if (ctx.align == null) ctx.align = true; + + if (curPunc == ";" || curPunc == ":" || (curPunc == "," && stream.match(/^\s*(?:\/\/.*)?$/, false))) + while (state.context.type == "statement") popContext(state); + else if (curPunc == "{") pushContext(state, stream.column(), "}"); + else if (curPunc == "[") pushContext(state, stream.column(), "]"); + else if (curPunc == "(") pushContext(state, stream.column(), ")"); + else if (curPunc == "}") { + while (ctx.type == "statement") ctx = popContext(state); + if (ctx.type == "}") ctx = popContext(state); + while (ctx.type == "statement") ctx = popContext(state); + } + else if (curPunc == ctx.type) popContext(state); + else if (indentStatements && + (((ctx.type == "}" || ctx.type == "top") && curPunc != ";") || + (ctx.type == "statement" && curPunc == "newstatement"))) { + pushContext(state, stream.column(), "statement", stream.current()); + } + + if (style == "variable" && + ((state.prevToken == "def" || + (parserConfig.typeFirstDefinitions && typeBefore(stream, state, stream.start) && + isTopScope(state.context) && stream.match(/^\s*\(/, false))))) + style = "def"; + + if (hooks.token) { + var result = hooks.token(stream, state, style); + if (result !== undefined) style = result; + } + + if (style == "def" && parserConfig.styleDefs === false) style = "variable"; + + state.startOfLine = false; + state.prevToken = isDefKeyword ? "def" : style || curPunc; + maybeEOL(stream, state); + return style; + }, + + indent: function(state, textAfter) { + if (state.tokenize != tokenBase && state.tokenize != null || state.typeAtEndOfLine) return CodeMirror.Pass; + var ctx = state.context, firstChar = textAfter && textAfter.charAt(0); + if (ctx.type == "statement" && firstChar == "}") ctx = ctx.prev; + if (parserConfig.dontIndentStatements) + while (ctx.type == "statement" && parserConfig.dontIndentStatements.test(ctx.info)) + ctx = ctx.prev + if (hooks.indent) { + var hook = hooks.indent(state, ctx, textAfter); + if (typeof hook == "number") return hook + } + var closing = firstChar == ctx.type; + var switchBlock = ctx.prev && ctx.prev.info == "switch"; + if (parserConfig.allmanIndentation && /[{(]/.test(firstChar)) { + while (ctx.type != "top" && ctx.type != "}") ctx = ctx.prev + return ctx.indented + } + if (ctx.type == "statement") + return ctx.indented + (firstChar == "{" ? 0 : statementIndentUnit); + if (ctx.align && (!dontAlignCalls || ctx.type != ")")) + return ctx.column + (closing ? 0 : 1); + if (ctx.type == ")" && !closing) + return ctx.indented + statementIndentUnit; + + return ctx.indented + (closing ? 0 : indentUnit) + + (!closing && switchBlock && !/^(?:case|default)\b/.test(textAfter) ? indentUnit : 0); + }, + + electricInput: indentSwitch ? /^\s*(?:case .*?:|default:|\{\}?|\})$/ : /^\s*[{}]$/, + blockCommentStart: "/*", + blockCommentEnd: "*/", + blockCommentContinue: " * ", + lineComment: "//", + fold: "brace" + }; + }); + + function words(str) { + var obj = {}, words = str.split(" "); + for (var i = 0; i < words.length; ++i) obj[words[i]] = true; + return obj; + } + function contains(words, word) { + if (typeof words === "function") { + return words(word); + } else { + return words.propertyIsEnumerable(word); + } + } + var cKeywords = "auto if break case register continue return default do sizeof " + + "static else struct switch extern typedef union for goto while enum const volatile"; + var cTypes = "int long char short double float unsigned signed void size_t ptrdiff_t"; + + function cppHook(stream, state) { + if (!state.startOfLine) return false + for (var ch, next = null; ch = stream.peek();) { + if (ch == "\\" && stream.match(/^.$/)) { + next = cppHook + break + } else if (ch == "/" && stream.match(/^\/[\/\*]/, false)) { + break + } + stream.next() + } + state.tokenize = next + return "meta" + } + + function pointerHook(_stream, state) { + if (state.prevToken == "type") return "type"; + return false; + } + + function cpp14Literal(stream) { + stream.eatWhile(/[\w\.']/); + return "number"; + } + + function cpp11StringHook(stream, state) { + stream.backUp(1); + // Raw strings. + if (stream.match(/(R|u8R|uR|UR|LR)/)) { + var match = stream.match(/"([^\s\\()]{0,16})\(/); + if (!match) { + return false; + } + state.cpp11RawStringDelim = match[1]; + state.tokenize = tokenRawString; + return tokenRawString(stream, state); + } + // Unicode strings/chars. + if (stream.match(/(u8|u|U|L)/)) { + if (stream.match(/["']/, /* eat */ false)) { + return "string"; + } + return false; + } + // Ignore this hook. + stream.next(); + return false; + } + + function cppLooksLikeConstructor(word) { + var lastTwo = /(\w+)::~?(\w+)$/.exec(word); + return lastTwo && lastTwo[1] == lastTwo[2]; + } + + // C#-style strings where "" escapes a quote. + function tokenAtString(stream, state) { + var next; + while ((next = stream.next()) != null) { + if (next == '"' && !stream.eat('"')) { + state.tokenize = null; + break; + } + } + return "string"; + } + + // C++11 raw string literal is "( anything )", where + // can be a string up to 16 characters long. + function tokenRawString(stream, state) { + // Escape characters that have special regex meanings. + var delim = state.cpp11RawStringDelim.replace(/[^\w\s]/g, '\\$&'); + var match = stream.match(new RegExp(".*?\\)" + delim + '"')); + if (match) + state.tokenize = null; + else + stream.skipToEnd(); + return "string"; + } + + function def(mimes, mode) { + if (typeof mimes == "string") mimes = [mimes]; + var words = []; + function add(obj) { + if (obj) for (var prop in obj) if (obj.hasOwnProperty(prop)) + words.push(prop); + } + add(mode.keywords); + add(mode.types); + add(mode.builtin); + add(mode.atoms); + if (words.length) { + mode.helperType = mimes[0]; + CodeMirror.registerHelper("hintWords", mimes[0], words); + } + + for (var i = 0; i < mimes.length; ++i) + CodeMirror.defineMIME(mimes[i], mode); + } + + def(["text/x-csrc", "text/x-c", "text/x-chdr"], { + name: "clike", + keywords: words(cKeywords), + types: words(cTypes + " bool _Complex _Bool float_t double_t intptr_t intmax_t " + + "int8_t int16_t int32_t int64_t uintptr_t uintmax_t uint8_t uint16_t " + + "uint32_t uint64_t"), + blockKeywords: words("case do else for if switch while struct"), + defKeywords: words("struct"), + typeFirstDefinitions: true, + atoms: words("NULL true false"), + hooks: {"#": cppHook, "*": pointerHook}, + modeProps: {fold: ["brace", "include"]} + }); + + def(["text/x-c++src", "text/x-c++hdr"], { + name: "clike", + keywords: words(cKeywords + " asm dynamic_cast namespace reinterpret_cast try explicit new " + + "static_cast typeid catch operator template typename class friend private " + + "this using const_cast inline public throw virtual delete mutable protected " + + "alignas alignof constexpr decltype nullptr noexcept thread_local final " + + "static_assert override"), + types: words(cTypes + " bool wchar_t"), + blockKeywords: words("catch class do else finally for if struct switch try while"), + defKeywords: words("class namespace struct enum union"), + typeFirstDefinitions: true, + atoms: words("true false NULL"), + dontIndentStatements: /^template$/, + isIdentifierChar: /[\w\$_~\xa1-\uffff]/, + hooks: { + "#": cppHook, + "*": pointerHook, + "u": cpp11StringHook, + "U": cpp11StringHook, + "L": cpp11StringHook, + "R": cpp11StringHook, + "0": cpp14Literal, + "1": cpp14Literal, + "2": cpp14Literal, + "3": cpp14Literal, + "4": cpp14Literal, + "5": cpp14Literal, + "6": cpp14Literal, + "7": cpp14Literal, + "8": cpp14Literal, + "9": cpp14Literal, + token: function(stream, state, style) { + if (style == "variable" && stream.peek() == "(" && + (state.prevToken == ";" || state.prevToken == null || + state.prevToken == "}") && + cppLooksLikeConstructor(stream.current())) + return "def"; + } + }, + namespaceSeparator: "::", + modeProps: {fold: ["brace", "include"]} + }); + + def("text/x-java", { + name: "clike", + keywords: words("abstract assert break case catch class const continue default " + + "do else enum extends final finally float for goto if implements import " + + "instanceof interface native new package private protected public " + + "return static strictfp super switch synchronized this throw throws transient " + + "try volatile while @interface"), + types: words("byte short int long float double boolean char void Boolean Byte Character Double Float " + + "Integer Long Number Object Short String StringBuffer StringBuilder Void"), + blockKeywords: words("catch class do else finally for if switch try while"), + defKeywords: words("class interface enum @interface"), + typeFirstDefinitions: true, + atoms: words("true false null"), + number: /^(?:0x[a-f\d_]+|0b[01_]+|(?:[\d_]+\.?\d*|\.\d+)(?:e[-+]?[\d_]+)?)(u|ll?|l|f)?/i, + hooks: { + "@": function(stream) { + // Don't match the @interface keyword. + if (stream.match('interface', false)) return false; + + stream.eatWhile(/[\w\$_]/); + return "meta"; + } + }, + modeProps: {fold: ["brace", "import"]} + }); + + def("text/x-csharp", { + name: "clike", + keywords: words("abstract as async await base break case catch checked class const continue" + + " default delegate do else enum event explicit extern finally fixed for" + + " foreach goto if implicit in interface internal is lock namespace new" + + " operator out override params private protected public readonly ref return sealed" + + " sizeof stackalloc static struct switch this throw try typeof unchecked" + + " unsafe using virtual void volatile while add alias ascending descending dynamic from get" + + " global group into join let orderby partial remove select set value var yield"), + types: words("Action Boolean Byte Char DateTime DateTimeOffset Decimal Double Func" + + " Guid Int16 Int32 Int64 Object SByte Single String Task TimeSpan UInt16 UInt32" + + " UInt64 bool byte char decimal double short int long object" + + " sbyte float string ushort uint ulong"), + blockKeywords: words("catch class do else finally for foreach if struct switch try while"), + defKeywords: words("class interface namespace struct var"), + typeFirstDefinitions: true, + atoms: words("true false null"), + hooks: { + "@": function(stream, state) { + if (stream.eat('"')) { + state.tokenize = tokenAtString; + return tokenAtString(stream, state); + } + stream.eatWhile(/[\w\$_]/); + return "meta"; + } + } + }); + + function tokenTripleString(stream, state) { + var escaped = false; + while (!stream.eol()) { + if (!escaped && stream.match('"""')) { + state.tokenize = null; + break; + } + escaped = stream.next() == "\\" && !escaped; + } + return "string"; + } + + function tokenNestedComment(depth) { + return function (stream, state) { + var ch + while (ch = stream.next()) { + if (ch == "*" && stream.eat("/")) { + if (depth == 1) { + state.tokenize = null + break + } else { + state.tokenize = tokenNestedComment(depth - 1) + return state.tokenize(stream, state) + } + } else if (ch == "/" && stream.eat("*")) { + state.tokenize = tokenNestedComment(depth + 1) + return state.tokenize(stream, state) + } + } + return "comment" + } + } + + def("text/x-scala", { + name: "clike", + keywords: words( + + /* scala */ + "abstract case catch class def do else extends final finally for forSome if " + + "implicit import lazy match new null object override package private protected return " + + "sealed super this throw trait try type val var while with yield _ " + + + /* package scala */ + "assert assume require print println printf readLine readBoolean readByte readShort " + + "readChar readInt readLong readFloat readDouble" + ), + types: words( + "AnyVal App Application Array BufferedIterator BigDecimal BigInt Char Console Either " + + "Enumeration Equiv Error Exception Fractional Function IndexedSeq Int Integral Iterable " + + "Iterator List Map Numeric Nil NotNull Option Ordered Ordering PartialFunction PartialOrdering " + + "Product Proxy Range Responder Seq Serializable Set Specializable Stream StringBuilder " + + "StringContext Symbol Throwable Traversable TraversableOnce Tuple Unit Vector " + + + /* package java.lang */ + "Boolean Byte Character CharSequence Class ClassLoader Cloneable Comparable " + + "Compiler Double Exception Float Integer Long Math Number Object Package Pair Process " + + "Runtime Runnable SecurityManager Short StackTraceElement StrictMath String " + + "StringBuffer System Thread ThreadGroup ThreadLocal Throwable Triple Void" + ), + multiLineStrings: true, + blockKeywords: words("catch class enum do else finally for forSome if match switch try while"), + defKeywords: words("class enum def object package trait type val var"), + atoms: words("true false null"), + indentStatements: false, + indentSwitch: false, + isOperatorChar: /[+\-*&%=<>!?|\/#:@]/, + hooks: { + "@": function(stream) { + stream.eatWhile(/[\w\$_]/); + return "meta"; + }, + '"': function(stream, state) { + if (!stream.match('""')) return false; + state.tokenize = tokenTripleString; + return state.tokenize(stream, state); + }, + "'": function(stream) { + stream.eatWhile(/[\w\$_\xa1-\uffff]/); + return "atom"; + }, + "=": function(stream, state) { + var cx = state.context + if (cx.type == "}" && cx.align && stream.eat(">")) { + state.context = new Context(cx.indented, cx.column, cx.type, cx.info, null, cx.prev) + return "operator" + } else { + return false + } + }, + + "/": function(stream, state) { + if (!stream.eat("*")) return false + state.tokenize = tokenNestedComment(1) + return state.tokenize(stream, state) + } + }, + modeProps: {closeBrackets: {triples: '"'}} + }); + + function tokenKotlinString(tripleString){ + return function (stream, state) { + var escaped = false, next, end = false; + while (!stream.eol()) { + if (!tripleString && !escaped && stream.match('"') ) {end = true; break;} + if (tripleString && stream.match('"""')) {end = true; break;} + next = stream.next(); + if(!escaped && next == "$" && stream.match('{')) + stream.skipTo("}"); + escaped = !escaped && next == "\\" && !tripleString; + } + if (end || !tripleString) + state.tokenize = null; + return "string"; + } + } + + def("text/x-kotlin", { + name: "clike", + keywords: words( + /*keywords*/ + "package as typealias class interface this super val operator " + + "var fun for is in This throw return annotation " + + "break continue object if else while do try when !in !is as? " + + + /*soft keywords*/ + "file import where by get set abstract enum open inner override private public internal " + + "protected catch finally out final vararg reified dynamic companion constructor init " + + "sealed field property receiver param sparam lateinit data inline noinline tailrec " + + "external annotation crossinline const operator infix suspend actual expect setparam" + ), + types: words( + /* package java.lang */ + "Boolean Byte Character CharSequence Class ClassLoader Cloneable Comparable " + + "Compiler Double Exception Float Integer Long Math Number Object Package Pair Process " + + "Runtime Runnable SecurityManager Short StackTraceElement StrictMath String " + + "StringBuffer System Thread ThreadGroup ThreadLocal Throwable Triple Void Annotation Any BooleanArray " + + "ByteArray Char CharArray DeprecationLevel DoubleArray Enum FloatArray Function Int IntArray Lazy " + + "LazyThreadSafetyMode LongArray Nothing ShortArray Unit" + ), + intendSwitch: false, + indentStatements: false, + multiLineStrings: true, + number: /^(?:0x[a-f\d_]+|0b[01_]+|(?:[\d_]+(\.\d+)?|\.\d+)(?:e[-+]?[\d_]+)?)(u|ll?|l|f)?/i, + blockKeywords: words("catch class do else finally for if where try while enum"), + defKeywords: words("class val var object interface fun"), + atoms: words("true false null this"), + hooks: { + "@": function(stream) { + stream.eatWhile(/[\w\$_]/); + return "meta"; + }, + '"': function(stream, state) { + state.tokenize = tokenKotlinString(stream.match('""')); + return state.tokenize(stream, state); + } + }, + modeProps: {closeBrackets: {triples: '"'}} + }); + + def(["x-shader/x-vertex", "x-shader/x-fragment"], { + name: "clike", + keywords: words("sampler1D sampler2D sampler3D samplerCube " + + "sampler1DShadow sampler2DShadow " + + "const attribute uniform varying " + + "break continue discard return " + + "for while do if else struct " + + "in out inout"), + types: words("float int bool void " + + "vec2 vec3 vec4 ivec2 ivec3 ivec4 bvec2 bvec3 bvec4 " + + "mat2 mat3 mat4"), + blockKeywords: words("for while do if else struct"), + builtin: words("radians degrees sin cos tan asin acos atan " + + "pow exp log exp2 sqrt inversesqrt " + + "abs sign floor ceil fract mod min max clamp mix step smoothstep " + + "length distance dot cross normalize ftransform faceforward " + + "reflect refract matrixCompMult " + + "lessThan lessThanEqual greaterThan greaterThanEqual " + + "equal notEqual any all not " + + "texture1D texture1DProj texture1DLod texture1DProjLod " + + "texture2D texture2DProj texture2DLod texture2DProjLod " + + "texture3D texture3DProj texture3DLod texture3DProjLod " + + "textureCube textureCubeLod " + + "shadow1D shadow2D shadow1DProj shadow2DProj " + + "shadow1DLod shadow2DLod shadow1DProjLod shadow2DProjLod " + + "dFdx dFdy fwidth " + + "noise1 noise2 noise3 noise4"), + atoms: words("true false " + + "gl_FragColor gl_SecondaryColor gl_Normal gl_Vertex " + + "gl_MultiTexCoord0 gl_MultiTexCoord1 gl_MultiTexCoord2 gl_MultiTexCoord3 " + + "gl_MultiTexCoord4 gl_MultiTexCoord5 gl_MultiTexCoord6 gl_MultiTexCoord7 " + + "gl_FogCoord gl_PointCoord " + + "gl_Position gl_PointSize gl_ClipVertex " + + "gl_FrontColor gl_BackColor gl_FrontSecondaryColor gl_BackSecondaryColor " + + "gl_TexCoord gl_FogFragCoord " + + "gl_FragCoord gl_FrontFacing " + + "gl_FragData gl_FragDepth " + + "gl_ModelViewMatrix gl_ProjectionMatrix gl_ModelViewProjectionMatrix " + + "gl_TextureMatrix gl_NormalMatrix gl_ModelViewMatrixInverse " + + "gl_ProjectionMatrixInverse gl_ModelViewProjectionMatrixInverse " + + "gl_TexureMatrixTranspose gl_ModelViewMatrixInverseTranspose " + + "gl_ProjectionMatrixInverseTranspose " + + "gl_ModelViewProjectionMatrixInverseTranspose " + + "gl_TextureMatrixInverseTranspose " + + "gl_NormalScale gl_DepthRange gl_ClipPlane " + + "gl_Point gl_FrontMaterial gl_BackMaterial gl_LightSource gl_LightModel " + + "gl_FrontLightModelProduct gl_BackLightModelProduct " + + "gl_TextureColor gl_EyePlaneS gl_EyePlaneT gl_EyePlaneR gl_EyePlaneQ " + + "gl_FogParameters " + + "gl_MaxLights gl_MaxClipPlanes gl_MaxTextureUnits gl_MaxTextureCoords " + + "gl_MaxVertexAttribs gl_MaxVertexUniformComponents gl_MaxVaryingFloats " + + "gl_MaxVertexTextureImageUnits gl_MaxTextureImageUnits " + + "gl_MaxFragmentUniformComponents gl_MaxCombineTextureImageUnits " + + "gl_MaxDrawBuffers"), + indentSwitch: false, + hooks: {"#": cppHook}, + modeProps: {fold: ["brace", "include"]} + }); + + def("text/x-nesc", { + name: "clike", + keywords: words(cKeywords + "as atomic async call command component components configuration event generic " + + "implementation includes interface module new norace nx_struct nx_union post provides " + + "signal task uses abstract extends"), + types: words(cTypes), + blockKeywords: words("case do else for if switch while struct"), + atoms: words("null true false"), + hooks: {"#": cppHook}, + modeProps: {fold: ["brace", "include"]} + }); + + def("text/x-objectivec", { + name: "clike", + keywords: words(cKeywords + "inline restrict _Bool _Complex _Imaginary BOOL Class bycopy byref id IMP in " + + "inout nil oneway out Protocol SEL self super atomic nonatomic retain copy readwrite readonly"), + types: words(cTypes), + atoms: words("YES NO NULL NILL ON OFF true false"), + hooks: { + "@": function(stream) { + stream.eatWhile(/[\w\$]/); + return "keyword"; + }, + "#": cppHook, + indent: function(_state, ctx, textAfter) { + if (ctx.type == "statement" && /^@\w/.test(textAfter)) return ctx.indented + } + }, + modeProps: {fold: "brace"} + }); + + def("text/x-squirrel", { + name: "clike", + keywords: words("base break clone continue const default delete enum extends function in class" + + " foreach local resume return this throw typeof yield constructor instanceof static"), + types: words(cTypes), + blockKeywords: words("case catch class else for foreach if switch try while"), + defKeywords: words("function local class"), + typeFirstDefinitions: true, + atoms: words("true false null"), + hooks: {"#": cppHook}, + modeProps: {fold: ["brace", "include"]} + }); + + // Ceylon Strings need to deal with interpolation + var stringTokenizer = null; + function tokenCeylonString(type) { + return function(stream, state) { + var escaped = false, next, end = false; + while (!stream.eol()) { + if (!escaped && stream.match('"') && + (type == "single" || stream.match('""'))) { + end = true; + break; + } + if (!escaped && stream.match('``')) { + stringTokenizer = tokenCeylonString(type); + end = true; + break; + } + next = stream.next(); + escaped = type == "single" && !escaped && next == "\\"; + } + if (end) + state.tokenize = null; + return "string"; + } + } + + def("text/x-ceylon", { + name: "clike", + keywords: words("abstracts alias assembly assert assign break case catch class continue dynamic else" + + " exists extends finally for function given if import in interface is let module new" + + " nonempty object of out outer package return satisfies super switch then this throw" + + " try value void while"), + types: function(word) { + // In Ceylon all identifiers that start with an uppercase are types + var first = word.charAt(0); + return (first === first.toUpperCase() && first !== first.toLowerCase()); + }, + blockKeywords: words("case catch class dynamic else finally for function if interface module new object switch try while"), + defKeywords: words("class dynamic function interface module object package value"), + builtin: words("abstract actual aliased annotation by default deprecated doc final formal late license" + + " native optional sealed see serializable shared suppressWarnings tagged throws variable"), + isPunctuationChar: /[\[\]{}\(\),;\:\.`]/, + isOperatorChar: /[+\-*&%=<>!?|^~:\/]/, + numberStart: /[\d#$]/, + number: /^(?:#[\da-fA-F_]+|\$[01_]+|[\d_]+[kMGTPmunpf]?|[\d_]+\.[\d_]+(?:[eE][-+]?\d+|[kMGTPmunpf]|)|)/i, + multiLineStrings: true, + typeFirstDefinitions: true, + atoms: words("true false null larger smaller equal empty finished"), + indentSwitch: false, + styleDefs: false, + hooks: { + "@": function(stream) { + stream.eatWhile(/[\w\$_]/); + return "meta"; + }, + '"': function(stream, state) { + state.tokenize = tokenCeylonString(stream.match('""') ? "triple" : "single"); + return state.tokenize(stream, state); + }, + '`': function(stream, state) { + if (!stringTokenizer || !stream.match('`')) return false; + state.tokenize = stringTokenizer; + stringTokenizer = null; + return state.tokenize(stream, state); + }, + "'": function(stream) { + stream.eatWhile(/[\w\$_\xa1-\uffff]/); + return "atom"; + }, + token: function(_stream, state, style) { + if ((style == "variable" || style == "type") && + state.prevToken == ".") { + return "variable-2"; + } + } + }, + modeProps: { + fold: ["brace", "import"], + closeBrackets: {triples: '"'} + } + }); + + }); + + +/***/ }), +/* 16 */ +/***/ (function(module, exports, __webpack_require__) { + + var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + + // WebAssembly experimental syntax highlight add-on for CodeMirror. + + (function (root, factory) { + if (true) { + !(__WEBPACK_AMD_DEFINE_ARRAY__ = [__webpack_require__(2)], __WEBPACK_AMD_DEFINE_FACTORY__ = (factory), __WEBPACK_AMD_DEFINE_RESULT__ = (typeof __WEBPACK_AMD_DEFINE_FACTORY__ === 'function' ? (__WEBPACK_AMD_DEFINE_FACTORY__.apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__)) : __WEBPACK_AMD_DEFINE_FACTORY__), __WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__)); + } else if (typeof exports !== 'undefined') { + factory(require("../../lib/codemirror")); + } else { + factory(root.CodeMirror); + } + }(this, function (CodeMirror) { + "use strict"; + + var isWordChar = /[\w\$_\.\\\/@]/; + + function createLookupTable(list) { + var obj = Object.create(null); + list.forEach(function (key) { + obj[key] = true; + }); + return obj; + } + + CodeMirror.defineMode("wasm", function() { + var keywords = createLookupTable([ + "function", "import", "export", "table", "memory", "segment", "as", "type", + "of", "from", "typeof", "br", "br_if", "loop", "br_table", "if", "else", + "call", "call_import", "call_indirect", "nop", "unreachable", "var", + "align", "select", "return"]); + var builtins = createLookupTable([ + "i32:8", "i32:8u", "i32:8s", "i32:16", "i32:16u", "i32:16s", + "i64:8", "i64:8u", "i64:8s", "i64:16", "i64:16u", "i64:16s", + "i64:32", "i64:32u", "i64:32s", + "i32.add", "i32.sub", "i32.mul", "i32.div_s", "i32.div_u", + "i32.rem_s", "i32.rem_u", "i32.and", "i32.or", "i32.xor", + "i32.shl", "i32.shr_u", "i32.shr_s", "i32.rotr", "i32.rotl", + "i32.eq", "i32.ne", "i32.lt_s", "i32.le_s", "i32.lt_u", + "i32.le_u", "i32.gt_s", "i32.ge_s", "i32.gt_u", "i32.ge_u", + "i32.clz", "i32.ctz", "i32.popcnt", "i32.eqz", "i64.add", + "i64.sub", "i64.mul", "i64.div_s", "i64.div_u", "i64.rem_s", + "i64.rem_u", "i64.and", "i64.or", "i64.xor", "i64.shl", + "i64.shr_u", "i64.shr_s", "i64.rotr", "i64.rotl", "i64.eq", + "i64.ne", "i64.lt_s", "i64.le_s", "i64.lt_u", "i64.le_u", + "i64.gt_s", "i64.ge_s", "i64.gt_u", "i64.ge_u", "i64.clz", + "i64.ctz", "i64.popcnt", "i64.eqz", "f32.add", "f32.sub", + "f32.mul", "f32.div", "f32.min", "f32.max", "f32.abs", + "f32.neg", "f32.copysign", "f32.ceil", "f32.floor", "f32.trunc", + "f32.nearest", "f32.sqrt", "f32.eq", "f32.ne", "f32.lt", + "f32.le", "f32.gt", "f32.ge", "f64.add", "f64.sub", "f64.mul", + "f64.div", "f64.min", "f64.max", "f64.abs", "f64.neg", + "f64.copysign", "f64.ceil", "f64.floor", "f64.trunc", "f64.nearest", + "f64.sqrt", "f64.eq", "f64.ne", "f64.lt", "f64.le", "f64.gt", + "f64.ge", "i32.trunc_s/f32", "i32.trunc_s/f64", "i32.trunc_u/f32", + "i32.trunc_u/f64", "i32.wrap/i64", "i64.trunc_s/f32", + "i64.trunc_s/f64", "i64.trunc_u/f32", "i64.trunc_u/f64", + "i64.extend_s/i32", "i64.extend_u/i32", "f32.convert_s/i32", + "f32.convert_u/i32", "f32.convert_s/i64", "f32.convert_u/i64", + "f32.demote/f64", "f32.reinterpret/i32", "f64.convert_s/i32", + "f64.convert_u/i32", "f64.convert_s/i64", "f64.convert_u/i64", + "f64.promote/f32", "f64.reinterpret/i64", "i32.reinterpret/f32", + "i64.reinterpret/f64"]); + var dataTypes = createLookupTable(["i32", "i64", "f32", "f64"]); + var isUnaryOperator = /[\-!]/; + var operators = createLookupTable([ + "+", "-", "*", "/", "/s", "/u", "%", "%s", "%u", + "<<", ">>u", ">>s", ">=", "<=", "==", "!=", + "=s", ">=u", ">s", ">u", + "<", ">", "=", "&", "|", "^", "!"]); + + function tokenBase(stream, state) { + var ch = stream.next(); + if (ch === "$") { + stream.eatWhile(isWordChar); + return "variable"; + } + if (ch === "@") { + stream.eatWhile(isWordChar); + return "meta"; + } + if (ch === '"') { + state.tokenize = tokenString(ch); + return state.tokenize(stream, state); + } + if (ch == "/") { + if (stream.eat("*")) { + state.tokenize = tokenComment; + return tokenComment(stream, state); + } else if (stream.eat("/")) { + stream.skipToEnd(); + return "comment"; + } + } + if (/\d/.test(ch) || + ((ch === "-" || ch === "+") && /\d/.test(stream.peek()))) { + stream.eatWhile(/[\w\._\-+]/); + return "number"; + } + if (/[\[\]\(\)\{\},:]/.test(ch)) { + return null; + } + if (isUnaryOperator.test(ch)) { + return "operator"; + } + stream.eatWhile(isWordChar); + var word = stream.current(); + + if (word in operators) { + return "operator"; + } + if (word in keywords){ + return "keyword"; + } + if (word in dataTypes) { + if (!stream.eat(":")) { + return "builtin"; + } + stream.eatWhile(isWordChar); + word = stream.current(); + // fall thru for "builtin" check + } + if (word in builtins) { + return "builtin"; + } + + if (word === "Temporary") { + // Nightly has header with some text graphics -- skipping it. + state.tokenize = tokenTemporary; + return state.tokenize(stream, state); + } + return null; + } + + function tokenComment(stream, state) { + state.commentDepth = 1; + var next; + while ((next = stream.next()) != null) { + if (next === "*" && stream.eat("/")) { + if (--state.commentDepth === 0) { + state.tokenize = null; + return "comment"; + } + } + if (next === "/" && stream.eat("*")) { + // Nested comment + state.commentDepth++; + } + } + return "comment"; + } + + function tokenTemporary(stream, state) { + var next, endState = state.commentState; + // Skipping until "text support (Work In Progress):" is found. + while ((next = stream.next()) != null) { + if (endState === 0 && next === "t") { + endState = 1; + } else if (endState === 1 && next === ":") { + state.tokenize = null; + state.commentState = 0; + endState = 2; + return "comment"; + } + } + state.commentState = endState; + return "comment"; + } + + function tokenString(quote) { + return function(stream, state) { + var escaped = false, next, end = false; + while ((next = stream.next()) != null) { + if (next == quote && !escaped) { + state.tokenize = null; + return "string"; + } + escaped = !escaped && next === "\\"; + } + return "string"; + }; + } + + return { + startState: function() { + return {tokenize: null, commentState: 0, commentDepth: 0}; + }, + + token: function(stream, state) { + if (stream.eatSpace()) return null; + var style = (state.tokenize || tokenBase)(stream, state); + return style; + } + }; + }); + + CodeMirror.registerHelper("wordChars", "wasm", isWordChar); + + CodeMirror.defineMIME("text/wasm", "wasm"); + + })); + + +/***/ }), +/* 17 */ +/***/ (function(module, exports, __webpack_require__) { + + // CodeMirror, copyright (c) by Marijn Haverbeke and others + // Distributed under an MIT license: http://codemirror.net/LICENSE + + (function(mod) { + if (true) // CommonJS + mod(__webpack_require__(2)); + else if (typeof define == "function" && define.amd) // AMD + define(["../../lib/codemirror"], mod); + else // Plain browser env + mod(CodeMirror); + })(function(CodeMirror) { + "use strict"; + var WRAP_CLASS = "CodeMirror-activeline"; + var BACK_CLASS = "CodeMirror-activeline-background"; + var GUTT_CLASS = "CodeMirror-activeline-gutter"; + + CodeMirror.defineOption("styleActiveLine", false, function(cm, val, old) { + var prev = old == CodeMirror.Init ? false : old; + if (val == prev) return + if (prev) { + cm.off("beforeSelectionChange", selectionChange); + clearActiveLines(cm); + delete cm.state.activeLines; + } + if (val) { + cm.state.activeLines = []; + updateActiveLines(cm, cm.listSelections()); + cm.on("beforeSelectionChange", selectionChange); + } + }); + + function clearActiveLines(cm) { + for (var i = 0; i < cm.state.activeLines.length; i++) { + cm.removeLineClass(cm.state.activeLines[i], "wrap", WRAP_CLASS); + cm.removeLineClass(cm.state.activeLines[i], "background", BACK_CLASS); + cm.removeLineClass(cm.state.activeLines[i], "gutter", GUTT_CLASS); + } + } + + function sameArray(a, b) { + if (a.length != b.length) return false; + for (var i = 0; i < a.length; i++) + if (a[i] != b[i]) return false; + return true; + } + + function updateActiveLines(cm, ranges) { + var active = []; + for (var i = 0; i < ranges.length; i++) { + var range = ranges[i]; + var option = cm.getOption("styleActiveLine"); + if (typeof option == "object" && option.nonEmpty ? range.anchor.line != range.head.line : !range.empty()) + continue + var line = cm.getLineHandleVisualStart(range.head.line); + if (active[active.length - 1] != line) active.push(line); + } + if (sameArray(cm.state.activeLines, active)) return; + cm.operation(function() { + clearActiveLines(cm); + for (var i = 0; i < active.length; i++) { + cm.addLineClass(active[i], "wrap", WRAP_CLASS); + cm.addLineClass(active[i], "background", BACK_CLASS); + cm.addLineClass(active[i], "gutter", GUTT_CLASS); + } + cm.state.activeLines = active; + }); + } + + function selectionChange(cm, sel) { + updateActiveLines(cm, sel.ranges); + } + }); + + +/***/ }), +/* 18 */ +/***/ (function(module, exports, __webpack_require__) { + + // CodeMirror, copyright (c) by Marijn Haverbeke and others + // Distributed under an MIT license: http://codemirror.net/LICENSE + + (function(mod) { + if (true) // CommonJS + mod(__webpack_require__(2)); + else if (typeof define == "function" && define.amd) // AMD + define(["../../lib/codemirror"], mod); + else // Plain browser env + mod(CodeMirror); + })(function(CodeMirror) { + CodeMirror.defineOption("showTrailingSpace", false, function(cm, val, prev) { + if (prev == CodeMirror.Init) prev = false; + if (prev && !val) + cm.removeOverlay("trailingspace"); + else if (!prev && val) + cm.addOverlay({ + token: function(stream) { + for (var l = stream.string.length, i = l; i && /\s/.test(stream.string.charAt(i - 1)); --i) {} + if (i > stream.pos) { stream.pos = i; return null; } + stream.pos = l; + return "trailingspace"; + }, + name: "trailingspace" + }); + }); + }); + + +/***/ }), +/* 19 */ +/***/ (function(module, exports, __webpack_require__) { + + // CodeMirror, copyright (c) by Marijn Haverbeke and others + // Distributed under an MIT license: http://codemirror.net/LICENSE + + (function(mod) { + if (true) // CommonJS + mod(__webpack_require__(2)); + else if (typeof define == "function" && define.amd) // AMD + define(["../lib/codemirror"], mod); + else // Plain browser env + mod(CodeMirror); + })(function(CodeMirror) { + "use strict"; + + var Pos = CodeMirror.Pos; + function posEq(a, b) { return a.line == b.line && a.ch == b.ch; } + + // Kill 'ring' + + var killRing = []; + function addToRing(str) { + killRing.push(str); + if (killRing.length > 50) killRing.shift(); + } + function growRingTop(str) { + if (!killRing.length) return addToRing(str); + killRing[killRing.length - 1] += str; + } + function getFromRing(n) { return killRing[killRing.length - (n ? Math.min(n, 1) : 1)] || ""; } + function popFromRing() { if (killRing.length > 1) killRing.pop(); return getFromRing(); } + + var lastKill = null; + + function kill(cm, from, to, ring, text) { + if (text == null) text = cm.getRange(from, to); + + if (ring == "grow" && lastKill && lastKill.cm == cm && posEq(from, lastKill.pos) && cm.isClean(lastKill.gen)) + growRingTop(text); + else if (ring !== false) + addToRing(text); + cm.replaceRange("", from, to, "+delete"); + + if (ring == "grow") lastKill = {cm: cm, pos: from, gen: cm.changeGeneration()}; + else lastKill = null; + } + + // Boundaries of various units + + function byChar(cm, pos, dir) { + return cm.findPosH(pos, dir, "char", true); + } + + function byWord(cm, pos, dir) { + return cm.findPosH(pos, dir, "word", true); + } + + function byLine(cm, pos, dir) { + return cm.findPosV(pos, dir, "line", cm.doc.sel.goalColumn); + } + + function byPage(cm, pos, dir) { + return cm.findPosV(pos, dir, "page", cm.doc.sel.goalColumn); + } + + function byParagraph(cm, pos, dir) { + var no = pos.line, line = cm.getLine(no); + var sawText = /\S/.test(dir < 0 ? line.slice(0, pos.ch) : line.slice(pos.ch)); + var fst = cm.firstLine(), lst = cm.lastLine(); + for (;;) { + no += dir; + if (no < fst || no > lst) + return cm.clipPos(Pos(no - dir, dir < 0 ? 0 : null)); + line = cm.getLine(no); + var hasText = /\S/.test(line); + if (hasText) sawText = true; + else if (sawText) return Pos(no, 0); + } + } + + function bySentence(cm, pos, dir) { + var line = pos.line, ch = pos.ch; + var text = cm.getLine(pos.line), sawWord = false; + for (;;) { + var next = text.charAt(ch + (dir < 0 ? -1 : 0)); + if (!next) { // End/beginning of line reached + if (line == (dir < 0 ? cm.firstLine() : cm.lastLine())) return Pos(line, ch); + text = cm.getLine(line + dir); + if (!/\S/.test(text)) return Pos(line, ch); + line += dir; + ch = dir < 0 ? text.length : 0; + continue; + } + if (sawWord && /[!?.]/.test(next)) return Pos(line, ch + (dir > 0 ? 1 : 0)); + if (!sawWord) sawWord = /\w/.test(next); + ch += dir; + } + } + + function byExpr(cm, pos, dir) { + var wrap; + if (cm.findMatchingBracket && (wrap = cm.findMatchingBracket(pos, {strict: true})) + && wrap.match && (wrap.forward ? 1 : -1) == dir) + return dir > 0 ? Pos(wrap.to.line, wrap.to.ch + 1) : wrap.to; + + for (var first = true;; first = false) { + var token = cm.getTokenAt(pos); + var after = Pos(pos.line, dir < 0 ? token.start : token.end); + if (first && dir > 0 && token.end == pos.ch || !/\w/.test(token.string)) { + var newPos = cm.findPosH(after, dir, "char"); + if (posEq(after, newPos)) return pos; + else pos = newPos; + } else { + return after; + } + } + } + + // Prefixes (only crudely supported) + + function getPrefix(cm, precise) { + var digits = cm.state.emacsPrefix; + if (!digits) return precise ? null : 1; + clearPrefix(cm); + return digits == "-" ? -1 : Number(digits); + } + + function repeated(cmd) { + var f = typeof cmd == "string" ? function(cm) { cm.execCommand(cmd); } : cmd; + return function(cm) { + var prefix = getPrefix(cm); + f(cm); + for (var i = 1; i < prefix; ++i) f(cm); + }; + } + + function findEnd(cm, pos, by, dir) { + var prefix = getPrefix(cm); + if (prefix < 0) { dir = -dir; prefix = -prefix; } + for (var i = 0; i < prefix; ++i) { + var newPos = by(cm, pos, dir); + if (posEq(newPos, pos)) break; + pos = newPos; + } + return pos; + } + + function move(by, dir) { + var f = function(cm) { + cm.extendSelection(findEnd(cm, cm.getCursor(), by, dir)); + }; + f.motion = true; + return f; + } + + function killTo(cm, by, dir, ring) { + var selections = cm.listSelections(), cursor; + var i = selections.length; + while (i--) { + cursor = selections[i].head; + kill(cm, cursor, findEnd(cm, cursor, by, dir), ring); + } + } + + function killRegion(cm, ring) { + if (cm.somethingSelected()) { + var selections = cm.listSelections(), selection; + var i = selections.length; + while (i--) { + selection = selections[i]; + kill(cm, selection.anchor, selection.head, ring); + } + return true; + } + } + + function addPrefix(cm, digit) { + if (cm.state.emacsPrefix) { + if (digit != "-") cm.state.emacsPrefix += digit; + return; + } + // Not active yet + cm.state.emacsPrefix = digit; + cm.on("keyHandled", maybeClearPrefix); + cm.on("inputRead", maybeDuplicateInput); + } + + var prefixPreservingKeys = {"Alt-G": true, "Ctrl-X": true, "Ctrl-Q": true, "Ctrl-U": true}; + + function maybeClearPrefix(cm, arg) { + if (!cm.state.emacsPrefixMap && !prefixPreservingKeys.hasOwnProperty(arg)) + clearPrefix(cm); + } + + function clearPrefix(cm) { + cm.state.emacsPrefix = null; + cm.off("keyHandled", maybeClearPrefix); + cm.off("inputRead", maybeDuplicateInput); + } + + function maybeDuplicateInput(cm, event) { + var dup = getPrefix(cm); + if (dup > 1 && event.origin == "+input") { + var one = event.text.join("\n"), txt = ""; + for (var i = 1; i < dup; ++i) txt += one; + cm.replaceSelection(txt); + } + } + + function addPrefixMap(cm) { + cm.state.emacsPrefixMap = true; + cm.addKeyMap(prefixMap); + cm.on("keyHandled", maybeRemovePrefixMap); + cm.on("inputRead", maybeRemovePrefixMap); + } + + function maybeRemovePrefixMap(cm, arg) { + if (typeof arg == "string" && (/^\d$/.test(arg) || arg == "Ctrl-U")) return; + cm.removeKeyMap(prefixMap); + cm.state.emacsPrefixMap = false; + cm.off("keyHandled", maybeRemovePrefixMap); + cm.off("inputRead", maybeRemovePrefixMap); + } + + // Utilities + + function setMark(cm) { + cm.setCursor(cm.getCursor()); + cm.setExtending(!cm.getExtending()); + cm.on("change", function() { cm.setExtending(false); }); + } + + function clearMark(cm) { + cm.setExtending(false); + cm.setCursor(cm.getCursor()); + } + + function getInput(cm, msg, f) { + if (cm.openDialog) + cm.openDialog(msg + ": ", f, {bottom: true}); + else + f(prompt(msg, "")); + } + + function operateOnWord(cm, op) { + var start = cm.getCursor(), end = cm.findPosH(start, 1, "word"); + cm.replaceRange(op(cm.getRange(start, end)), start, end); + cm.setCursor(end); + } + + function toEnclosingExpr(cm) { + var pos = cm.getCursor(), line = pos.line, ch = pos.ch; + var stack = []; + while (line >= cm.firstLine()) { + var text = cm.getLine(line); + for (var i = ch == null ? text.length : ch; i > 0;) { + var ch = text.charAt(--i); + if (ch == ")") + stack.push("("); + else if (ch == "]") + stack.push("["); + else if (ch == "}") + stack.push("{"); + else if (/[\(\{\[]/.test(ch) && (!stack.length || stack.pop() != ch)) + return cm.extendSelection(Pos(line, i)); + } + --line; ch = null; + } + } + + function quit(cm) { + cm.execCommand("clearSearch"); + clearMark(cm); + } + + CodeMirror.emacs = {kill: kill, killRegion: killRegion, repeated: repeated}; + + // Actual keymap + + var keyMap = CodeMirror.keyMap.emacs = CodeMirror.normalizeKeyMap({ + "Ctrl-W": function(cm) {kill(cm, cm.getCursor("start"), cm.getCursor("end"), true);}, + "Ctrl-K": repeated(function(cm) { + var start = cm.getCursor(), end = cm.clipPos(Pos(start.line)); + var text = cm.getRange(start, end); + if (!/\S/.test(text)) { + text += "\n"; + end = Pos(start.line + 1, 0); + } + kill(cm, start, end, "grow", text); + }), + "Alt-W": function(cm) { + addToRing(cm.getSelection()); + clearMark(cm); + }, + "Ctrl-Y": function(cm) { + var start = cm.getCursor(); + cm.replaceRange(getFromRing(getPrefix(cm)), start, start, "paste"); + cm.setSelection(start, cm.getCursor()); + }, + "Alt-Y": function(cm) {cm.replaceSelection(popFromRing(), "around", "paste");}, + + "Ctrl-Space": setMark, "Ctrl-Shift-2": setMark, + + "Ctrl-F": move(byChar, 1), "Ctrl-B": move(byChar, -1), + "Right": move(byChar, 1), "Left": move(byChar, -1), + "Ctrl-D": function(cm) { killTo(cm, byChar, 1, false); }, + "Delete": function(cm) { killRegion(cm, false) || killTo(cm, byChar, 1, false); }, + "Ctrl-H": function(cm) { killTo(cm, byChar, -1, false); }, + "Backspace": function(cm) { killRegion(cm, false) || killTo(cm, byChar, -1, false); }, + + "Alt-F": move(byWord, 1), "Alt-B": move(byWord, -1), + "Alt-Right": move(byWord, 1), "Alt-Left": move(byWord, -1), + "Alt-D": function(cm) { killTo(cm, byWord, 1, "grow"); }, + "Alt-Backspace": function(cm) { killTo(cm, byWord, -1, "grow"); }, + + "Ctrl-N": move(byLine, 1), "Ctrl-P": move(byLine, -1), + "Down": move(byLine, 1), "Up": move(byLine, -1), + "Ctrl-A": "goLineStart", "Ctrl-E": "goLineEnd", + "End": "goLineEnd", "Home": "goLineStart", + + "Alt-V": move(byPage, -1), "Ctrl-V": move(byPage, 1), + "PageUp": move(byPage, -1), "PageDown": move(byPage, 1), + + "Ctrl-Up": move(byParagraph, -1), "Ctrl-Down": move(byParagraph, 1), + + "Alt-A": move(bySentence, -1), "Alt-E": move(bySentence, 1), + "Alt-K": function(cm) { killTo(cm, bySentence, 1, "grow"); }, + + "Ctrl-Alt-K": function(cm) { killTo(cm, byExpr, 1, "grow"); }, + "Ctrl-Alt-Backspace": function(cm) { killTo(cm, byExpr, -1, "grow"); }, + "Ctrl-Alt-F": move(byExpr, 1), "Ctrl-Alt-B": move(byExpr, -1, "grow"), + + "Shift-Ctrl-Alt-2": function(cm) { + var cursor = cm.getCursor(); + cm.setSelection(findEnd(cm, cursor, byExpr, 1), cursor); + }, + "Ctrl-Alt-T": function(cm) { + var leftStart = byExpr(cm, cm.getCursor(), -1), leftEnd = byExpr(cm, leftStart, 1); + var rightEnd = byExpr(cm, leftEnd, 1), rightStart = byExpr(cm, rightEnd, -1); + cm.replaceRange(cm.getRange(rightStart, rightEnd) + cm.getRange(leftEnd, rightStart) + + cm.getRange(leftStart, leftEnd), leftStart, rightEnd); + }, + "Ctrl-Alt-U": repeated(toEnclosingExpr), + + "Alt-Space": function(cm) { + var pos = cm.getCursor(), from = pos.ch, to = pos.ch, text = cm.getLine(pos.line); + while (from && /\s/.test(text.charAt(from - 1))) --from; + while (to < text.length && /\s/.test(text.charAt(to))) ++to; + cm.replaceRange(" ", Pos(pos.line, from), Pos(pos.line, to)); + }, + "Ctrl-O": repeated(function(cm) { cm.replaceSelection("\n", "start"); }), + "Ctrl-T": repeated(function(cm) { + cm.execCommand("transposeChars"); + }), + + "Alt-C": repeated(function(cm) { + operateOnWord(cm, function(w) { + var letter = w.search(/\w/); + if (letter == -1) return w; + return w.slice(0, letter) + w.charAt(letter).toUpperCase() + w.slice(letter + 1).toLowerCase(); + }); + }), + "Alt-U": repeated(function(cm) { + operateOnWord(cm, function(w) { return w.toUpperCase(); }); + }), + "Alt-L": repeated(function(cm) { + operateOnWord(cm, function(w) { return w.toLowerCase(); }); + }), + + "Alt-;": "toggleComment", + + "Ctrl-/": repeated("undo"), "Shift-Ctrl--": repeated("undo"), + "Ctrl-Z": repeated("undo"), "Cmd-Z": repeated("undo"), + "Shift-Alt-,": "goDocStart", "Shift-Alt-.": "goDocEnd", + "Ctrl-S": "findPersistentNext", "Ctrl-R": "findPersistentPrev", "Ctrl-G": quit, "Shift-Alt-5": "replace", + "Alt-/": "autocomplete", + "Enter": "newlineAndIndent", + "Ctrl-J": repeated(function(cm) { cm.replaceSelection("\n", "end"); }), + "Tab": "indentAuto", + + "Alt-G G": function(cm) { + var prefix = getPrefix(cm, true); + if (prefix != null && prefix > 0) return cm.setCursor(prefix - 1); + + getInput(cm, "Goto line", function(str) { + var num; + if (str && !isNaN(num = Number(str)) && num == (num|0) && num > 0) + cm.setCursor(num - 1); + }); + }, + + "Ctrl-X Tab": function(cm) { + cm.indentSelection(getPrefix(cm, true) || cm.getOption("indentUnit")); + }, + "Ctrl-X Ctrl-X": function(cm) { + cm.setSelection(cm.getCursor("head"), cm.getCursor("anchor")); + }, + "Ctrl-X Ctrl-S": "save", + "Ctrl-X Ctrl-W": "save", + "Ctrl-X S": "saveAll", + "Ctrl-X F": "open", + "Ctrl-X U": repeated("undo"), + "Ctrl-X K": "close", + "Ctrl-X Delete": function(cm) { kill(cm, cm.getCursor(), bySentence(cm, cm.getCursor(), 1), "grow"); }, + "Ctrl-X H": "selectAll", + + "Ctrl-Q Tab": repeated("insertTab"), + "Ctrl-U": addPrefixMap + }); + + var prefixMap = {"Ctrl-G": clearPrefix}; + function regPrefix(d) { + prefixMap[d] = function(cm) { addPrefix(cm, d); }; + keyMap["Ctrl-" + d] = function(cm) { addPrefix(cm, d); }; + prefixPreservingKeys["Ctrl-" + d] = true; + } + for (var i = 0; i < 10; ++i) regPrefix(String(i)); + regPrefix("-"); + }); + + +/***/ }), +/* 20 */ +/***/ (function(module, exports, __webpack_require__) { + + // CodeMirror, copyright (c) by Marijn Haverbeke and others + // Distributed under an MIT license: http://codemirror.net/LICENSE + + /** + * Supported keybindings: + * Too many to list. Refer to defaultKeyMap below. + * + * Supported Ex commands: + * Refer to defaultExCommandMap below. + * + * Registers: unnamed, -, a-z, A-Z, 0-9 + * (Does not respect the special case for number registers when delete + * operator is made with these commands: %, (, ), , /, ?, n, N, {, } ) + * TODO: Implement the remaining registers. + * + * Marks: a-z, A-Z, and 0-9 + * TODO: Implement the remaining special marks. They have more complex + * behavior. + * + * Events: + * 'vim-mode-change' - raised on the editor anytime the current mode changes, + * Event object: {mode: "visual", subMode: "linewise"} + * + * Code structure: + * 1. Default keymap + * 2. Variable declarations and short basic helpers + * 3. Instance (External API) implementation + * 4. Internal state tracking objects (input state, counter) implementation + * and instantiation + * 5. Key handler (the main command dispatcher) implementation + * 6. Motion, operator, and action implementations + * 7. Helper functions for the key handler, motions, operators, and actions + * 8. Set up Vim to work as a keymap for CodeMirror. + * 9. Ex command implementations. + */ + + (function(mod) { + if (true) // CommonJS + mod(__webpack_require__(2), __webpack_require__(3), __webpack_require__(1), __webpack_require__(5)); + else if (typeof define == "function" && define.amd) // AMD + define(["../lib/codemirror", "../addon/search/searchcursor", "../addon/dialog/dialog", "../addon/edit/matchbrackets"], mod); + else // Plain browser env + mod(CodeMirror); + })(function(CodeMirror) { + 'use strict'; + + var defaultKeymap = [ + // Key to key mapping. This goes first to make it possible to override + // existing mappings. + { keys: '', type: 'keyToKey', toKeys: 'h' }, + { keys: '', type: 'keyToKey', toKeys: 'l' }, + { keys: '', type: 'keyToKey', toKeys: 'k' }, + { keys: '', type: 'keyToKey', toKeys: 'j' }, + { keys: '', type: 'keyToKey', toKeys: 'l' }, + { keys: '', type: 'keyToKey', toKeys: 'h', context: 'normal'}, + { keys: '', type: 'keyToKey', toKeys: 'W' }, + { keys: '', type: 'keyToKey', toKeys: 'B', context: 'normal' }, + { keys: '', type: 'keyToKey', toKeys: 'w' }, + { keys: '', type: 'keyToKey', toKeys: 'b', context: 'normal' }, + { keys: '', type: 'keyToKey', toKeys: 'j' }, + { keys: '', type: 'keyToKey', toKeys: 'k' }, + { keys: '', type: 'keyToKey', toKeys: '' }, + { keys: '', type: 'keyToKey', toKeys: '' }, + { keys: '', type: 'keyToKey', toKeys: '', context: 'insert' }, + { keys: '', type: 'keyToKey', toKeys: '', context: 'insert' }, + { keys: 's', type: 'keyToKey', toKeys: 'cl', context: 'normal' }, + { keys: 's', type: 'keyToKey', toKeys: 'c', context: 'visual'}, + { keys: 'S', type: 'keyToKey', toKeys: 'cc', context: 'normal' }, + { keys: 'S', type: 'keyToKey', toKeys: 'VdO', context: 'visual' }, + { keys: '', type: 'keyToKey', toKeys: '0' }, + { keys: '', type: 'keyToKey', toKeys: '$' }, + { keys: '', type: 'keyToKey', toKeys: '' }, + { keys: '', type: 'keyToKey', toKeys: '' }, + { keys: '', type: 'keyToKey', toKeys: 'j^', context: 'normal' }, + { keys: '', type: 'action', action: 'toggleOverwrite', context: 'insert' }, + // Motions + { keys: 'H', type: 'motion', motion: 'moveToTopLine', motionArgs: { linewise: true, toJumplist: true }}, + { keys: 'M', type: 'motion', motion: 'moveToMiddleLine', motionArgs: { linewise: true, toJumplist: true }}, + { keys: 'L', type: 'motion', motion: 'moveToBottomLine', motionArgs: { linewise: true, toJumplist: true }}, + { keys: 'h', type: 'motion', motion: 'moveByCharacters', motionArgs: { forward: false }}, + { keys: 'l', type: 'motion', motion: 'moveByCharacters', motionArgs: { forward: true }}, + { keys: 'j', type: 'motion', motion: 'moveByLines', motionArgs: { forward: true, linewise: true }}, + { keys: 'k', type: 'motion', motion: 'moveByLines', motionArgs: { forward: false, linewise: true }}, + { keys: 'gj', type: 'motion', motion: 'moveByDisplayLines', motionArgs: { forward: true }}, + { keys: 'gk', type: 'motion', motion: 'moveByDisplayLines', motionArgs: { forward: false }}, + { keys: 'w', type: 'motion', motion: 'moveByWords', motionArgs: { forward: true, wordEnd: false }}, + { keys: 'W', type: 'motion', motion: 'moveByWords', motionArgs: { forward: true, wordEnd: false, bigWord: true }}, + { keys: 'e', type: 'motion', motion: 'moveByWords', motionArgs: { forward: true, wordEnd: true, inclusive: true }}, + { keys: 'E', type: 'motion', motion: 'moveByWords', motionArgs: { forward: true, wordEnd: true, bigWord: true, inclusive: true }}, + { keys: 'b', type: 'motion', motion: 'moveByWords', motionArgs: { forward: false, wordEnd: false }}, + { keys: 'B', type: 'motion', motion: 'moveByWords', motionArgs: { forward: false, wordEnd: false, bigWord: true }}, + { keys: 'ge', type: 'motion', motion: 'moveByWords', motionArgs: { forward: false, wordEnd: true, inclusive: true }}, + { keys: 'gE', type: 'motion', motion: 'moveByWords', motionArgs: { forward: false, wordEnd: true, bigWord: true, inclusive: true }}, + { keys: '{', type: 'motion', motion: 'moveByParagraph', motionArgs: { forward: false, toJumplist: true }}, + { keys: '}', type: 'motion', motion: 'moveByParagraph', motionArgs: { forward: true, toJumplist: true }}, + { keys: '(', type: 'motion', motion: 'moveBySentence', motionArgs: { forward: false }}, + { keys: ')', type: 'motion', motion: 'moveBySentence', motionArgs: { forward: true }}, + { keys: '', type: 'motion', motion: 'moveByPage', motionArgs: { forward: true }}, + { keys: '', type: 'motion', motion: 'moveByPage', motionArgs: { forward: false }}, + { keys: '', type: 'motion', motion: 'moveByScroll', motionArgs: { forward: true, explicitRepeat: true }}, + { keys: '', type: 'motion', motion: 'moveByScroll', motionArgs: { forward: false, explicitRepeat: true }}, + { keys: 'gg', type: 'motion', motion: 'moveToLineOrEdgeOfDocument', motionArgs: { forward: false, explicitRepeat: true, linewise: true, toJumplist: true }}, + { keys: 'G', type: 'motion', motion: 'moveToLineOrEdgeOfDocument', motionArgs: { forward: true, explicitRepeat: true, linewise: true, toJumplist: true }}, + { keys: '0', type: 'motion', motion: 'moveToStartOfLine' }, + { keys: '^', type: 'motion', motion: 'moveToFirstNonWhiteSpaceCharacter' }, + { keys: '+', type: 'motion', motion: 'moveByLines', motionArgs: { forward: true, toFirstChar:true }}, + { keys: '-', type: 'motion', motion: 'moveByLines', motionArgs: { forward: false, toFirstChar:true }}, + { keys: '_', type: 'motion', motion: 'moveByLines', motionArgs: { forward: true, toFirstChar:true, repeatOffset:-1 }}, + { keys: '$', type: 'motion', motion: 'moveToEol', motionArgs: { inclusive: true }}, + { keys: '%', type: 'motion', motion: 'moveToMatchedSymbol', motionArgs: { inclusive: true, toJumplist: true }}, + { keys: 'f', type: 'motion', motion: 'moveToCharacter', motionArgs: { forward: true , inclusive: true }}, + { keys: 'F', type: 'motion', motion: 'moveToCharacter', motionArgs: { forward: false }}, + { keys: 't', type: 'motion', motion: 'moveTillCharacter', motionArgs: { forward: true, inclusive: true }}, + { keys: 'T', type: 'motion', motion: 'moveTillCharacter', motionArgs: { forward: false }}, + { keys: ';', type: 'motion', motion: 'repeatLastCharacterSearch', motionArgs: { forward: true }}, + { keys: ',', type: 'motion', motion: 'repeatLastCharacterSearch', motionArgs: { forward: false }}, + { keys: '\'', type: 'motion', motion: 'goToMark', motionArgs: {toJumplist: true, linewise: true}}, + { keys: '`', type: 'motion', motion: 'goToMark', motionArgs: {toJumplist: true}}, + { keys: ']`', type: 'motion', motion: 'jumpToMark', motionArgs: { forward: true } }, + { keys: '[`', type: 'motion', motion: 'jumpToMark', motionArgs: { forward: false } }, + { keys: ']\'', type: 'motion', motion: 'jumpToMark', motionArgs: { forward: true, linewise: true } }, + { keys: '[\'', type: 'motion', motion: 'jumpToMark', motionArgs: { forward: false, linewise: true } }, + // the next two aren't motions but must come before more general motion declarations + { keys: ']p', type: 'action', action: 'paste', isEdit: true, actionArgs: { after: true, isEdit: true, matchIndent: true}}, + { keys: '[p', type: 'action', action: 'paste', isEdit: true, actionArgs: { after: false, isEdit: true, matchIndent: true}}, + { keys: ']', type: 'motion', motion: 'moveToSymbol', motionArgs: { forward: true, toJumplist: true}}, + { keys: '[', type: 'motion', motion: 'moveToSymbol', motionArgs: { forward: false, toJumplist: true}}, + { keys: '|', type: 'motion', motion: 'moveToColumn'}, + { keys: 'o', type: 'motion', motion: 'moveToOtherHighlightedEnd', context:'visual'}, + { keys: 'O', type: 'motion', motion: 'moveToOtherHighlightedEnd', motionArgs: {sameLine: true}, context:'visual'}, + // Operators + { keys: 'd', type: 'operator', operator: 'delete' }, + { keys: 'y', type: 'operator', operator: 'yank' }, + { keys: 'c', type: 'operator', operator: 'change' }, + { keys: '>', type: 'operator', operator: 'indent', operatorArgs: { indentRight: true }}, + { keys: '<', type: 'operator', operator: 'indent', operatorArgs: { indentRight: false }}, + { keys: 'g~', type: 'operator', operator: 'changeCase' }, + { keys: 'gu', type: 'operator', operator: 'changeCase', operatorArgs: {toLower: true}, isEdit: true }, + { keys: 'gU', type: 'operator', operator: 'changeCase', operatorArgs: {toLower: false}, isEdit: true }, + { keys: 'n', type: 'motion', motion: 'findNext', motionArgs: { forward: true, toJumplist: true }}, + { keys: 'N', type: 'motion', motion: 'findNext', motionArgs: { forward: false, toJumplist: true }}, + // Operator-Motion dual commands + { keys: 'x', type: 'operatorMotion', operator: 'delete', motion: 'moveByCharacters', motionArgs: { forward: true }, operatorMotionArgs: { visualLine: false }}, + { keys: 'X', type: 'operatorMotion', operator: 'delete', motion: 'moveByCharacters', motionArgs: { forward: false }, operatorMotionArgs: { visualLine: true }}, + { keys: 'D', type: 'operatorMotion', operator: 'delete', motion: 'moveToEol', motionArgs: { inclusive: true }, context: 'normal'}, + { keys: 'D', type: 'operator', operator: 'delete', operatorArgs: { linewise: true }, context: 'visual'}, + { keys: 'Y', type: 'operatorMotion', operator: 'yank', motion: 'expandToLine', motionArgs: { linewise: true }, context: 'normal'}, + { keys: 'Y', type: 'operator', operator: 'yank', operatorArgs: { linewise: true }, context: 'visual'}, + { keys: 'C', type: 'operatorMotion', operator: 'change', motion: 'moveToEol', motionArgs: { inclusive: true }, context: 'normal'}, + { keys: 'C', type: 'operator', operator: 'change', operatorArgs: { linewise: true }, context: 'visual'}, + { keys: '~', type: 'operatorMotion', operator: 'changeCase', motion: 'moveByCharacters', motionArgs: { forward: true }, operatorArgs: { shouldMoveCursor: true }, context: 'normal'}, + { keys: '~', type: 'operator', operator: 'changeCase', context: 'visual'}, + { keys: '', type: 'operatorMotion', operator: 'delete', motion: 'moveByWords', motionArgs: { forward: false, wordEnd: false }, context: 'insert' }, + // Actions + { keys: '', type: 'action', action: 'jumpListWalk', actionArgs: { forward: true }}, + { keys: '', type: 'action', action: 'jumpListWalk', actionArgs: { forward: false }}, + { keys: '', type: 'action', action: 'scroll', actionArgs: { forward: true, linewise: true }}, + { keys: '', type: 'action', action: 'scroll', actionArgs: { forward: false, linewise: true }}, + { keys: 'a', type: 'action', action: 'enterInsertMode', isEdit: true, actionArgs: { insertAt: 'charAfter' }, context: 'normal' }, + { keys: 'A', type: 'action', action: 'enterInsertMode', isEdit: true, actionArgs: { insertAt: 'eol' }, context: 'normal' }, + { keys: 'A', type: 'action', action: 'enterInsertMode', isEdit: true, actionArgs: { insertAt: 'endOfSelectedArea' }, context: 'visual' }, + { keys: 'i', type: 'action', action: 'enterInsertMode', isEdit: true, actionArgs: { insertAt: 'inplace' }, context: 'normal' }, + { keys: 'I', type: 'action', action: 'enterInsertMode', isEdit: true, actionArgs: { insertAt: 'firstNonBlank'}, context: 'normal' }, + { keys: 'I', type: 'action', action: 'enterInsertMode', isEdit: true, actionArgs: { insertAt: 'startOfSelectedArea' }, context: 'visual' }, + { keys: 'o', type: 'action', action: 'newLineAndEnterInsertMode', isEdit: true, interlaceInsertRepeat: true, actionArgs: { after: true }, context: 'normal' }, + { keys: 'O', type: 'action', action: 'newLineAndEnterInsertMode', isEdit: true, interlaceInsertRepeat: true, actionArgs: { after: false }, context: 'normal' }, + { keys: 'v', type: 'action', action: 'toggleVisualMode' }, + { keys: 'V', type: 'action', action: 'toggleVisualMode', actionArgs: { linewise: true }}, + { keys: '', type: 'action', action: 'toggleVisualMode', actionArgs: { blockwise: true }}, + { keys: '', type: 'action', action: 'toggleVisualMode', actionArgs: { blockwise: true }}, + { keys: 'gv', type: 'action', action: 'reselectLastSelection' }, + { keys: 'J', type: 'action', action: 'joinLines', isEdit: true }, + { keys: 'p', type: 'action', action: 'paste', isEdit: true, actionArgs: { after: true, isEdit: true }}, + { keys: 'P', type: 'action', action: 'paste', isEdit: true, actionArgs: { after: false, isEdit: true }}, + { keys: 'r', type: 'action', action: 'replace', isEdit: true }, + { keys: '@', type: 'action', action: 'replayMacro' }, + { keys: 'q', type: 'action', action: 'enterMacroRecordMode' }, + // Handle Replace-mode as a special case of insert mode. + { keys: 'R', type: 'action', action: 'enterInsertMode', isEdit: true, actionArgs: { replace: true }}, + { keys: 'u', type: 'action', action: 'undo', context: 'normal' }, + { keys: 'u', type: 'operator', operator: 'changeCase', operatorArgs: {toLower: true}, context: 'visual', isEdit: true }, + { keys: 'U', type: 'operator', operator: 'changeCase', operatorArgs: {toLower: false}, context: 'visual', isEdit: true }, + { keys: '', type: 'action', action: 'redo' }, + { keys: 'm', type: 'action', action: 'setMark' }, + { keys: '"', type: 'action', action: 'setRegister' }, + { keys: 'zz', type: 'action', action: 'scrollToCursor', actionArgs: { position: 'center' }}, + { keys: 'z.', type: 'action', action: 'scrollToCursor', actionArgs: { position: 'center' }, motion: 'moveToFirstNonWhiteSpaceCharacter' }, + { keys: 'zt', type: 'action', action: 'scrollToCursor', actionArgs: { position: 'top' }}, + { keys: 'z', type: 'action', action: 'scrollToCursor', actionArgs: { position: 'top' }, motion: 'moveToFirstNonWhiteSpaceCharacter' }, + { keys: 'z-', type: 'action', action: 'scrollToCursor', actionArgs: { position: 'bottom' }}, + { keys: 'zb', type: 'action', action: 'scrollToCursor', actionArgs: { position: 'bottom' }, motion: 'moveToFirstNonWhiteSpaceCharacter' }, + { keys: '.', type: 'action', action: 'repeatLastEdit' }, + { keys: '', type: 'action', action: 'incrementNumberToken', isEdit: true, actionArgs: {increase: true, backtrack: false}}, + { keys: '', type: 'action', action: 'incrementNumberToken', isEdit: true, actionArgs: {increase: false, backtrack: false}}, + { keys: '', type: 'action', action: 'indent', actionArgs: { indentRight: true }, context: 'insert' }, + { keys: '', type: 'action', action: 'indent', actionArgs: { indentRight: false }, context: 'insert' }, + // Text object motions + { keys: 'a', type: 'motion', motion: 'textObjectManipulation' }, + { keys: 'i', type: 'motion', motion: 'textObjectManipulation', motionArgs: { textObjectInner: true }}, + // Search + { keys: '/', type: 'search', searchArgs: { forward: true, querySrc: 'prompt', toJumplist: true }}, + { keys: '?', type: 'search', searchArgs: { forward: false, querySrc: 'prompt', toJumplist: true }}, + { keys: '*', type: 'search', searchArgs: { forward: true, querySrc: 'wordUnderCursor', wholeWordOnly: true, toJumplist: true }}, + { keys: '#', type: 'search', searchArgs: { forward: false, querySrc: 'wordUnderCursor', wholeWordOnly: true, toJumplist: true }}, + { keys: 'g*', type: 'search', searchArgs: { forward: true, querySrc: 'wordUnderCursor', toJumplist: true }}, + { keys: 'g#', type: 'search', searchArgs: { forward: false, querySrc: 'wordUnderCursor', toJumplist: true }}, + // Ex command + { keys: ':', type: 'ex' } + ]; + + /** + * Ex commands + * Care must be taken when adding to the default Ex command map. For any + * pair of commands that have a shared prefix, at least one of their + * shortNames must not match the prefix of the other command. + */ + var defaultExCommandMap = [ + { name: 'colorscheme', shortName: 'colo' }, + { name: 'map' }, + { name: 'imap', shortName: 'im' }, + { name: 'nmap', shortName: 'nm' }, + { name: 'vmap', shortName: 'vm' }, + { name: 'unmap' }, + { name: 'write', shortName: 'w' }, + { name: 'undo', shortName: 'u' }, + { name: 'redo', shortName: 'red' }, + { name: 'set', shortName: 'se' }, + { name: 'set', shortName: 'se' }, + { name: 'setlocal', shortName: 'setl' }, + { name: 'setglobal', shortName: 'setg' }, + { name: 'sort', shortName: 'sor' }, + { name: 'substitute', shortName: 's', possiblyAsync: true }, + { name: 'nohlsearch', shortName: 'noh' }, + { name: 'yank', shortName: 'y' }, + { name: 'delmarks', shortName: 'delm' }, + { name: 'registers', shortName: 'reg', excludeFromCommandHistory: true }, + { name: 'global', shortName: 'g' } + ]; + + var Pos = CodeMirror.Pos; + + var Vim = function() { + function enterVimMode(cm) { + cm.setOption('disableInput', true); + cm.setOption('showCursorWhenSelecting', false); + CodeMirror.signal(cm, "vim-mode-change", {mode: "normal"}); + cm.on('cursorActivity', onCursorActivity); + maybeInitVimState(cm); + CodeMirror.on(cm.getInputField(), 'paste', getOnPasteFn(cm)); + } + + function leaveVimMode(cm) { + cm.setOption('disableInput', false); + cm.off('cursorActivity', onCursorActivity); + CodeMirror.off(cm.getInputField(), 'paste', getOnPasteFn(cm)); + cm.state.vim = null; + } + + function detachVimMap(cm, next) { + if (this == CodeMirror.keyMap.vim) { + CodeMirror.rmClass(cm.getWrapperElement(), "cm-fat-cursor"); + if (cm.getOption("inputStyle") == "contenteditable" && document.body.style.caretColor != null) { + disableFatCursorMark(cm); + cm.getInputField().style.caretColor = ""; + } + } + + if (!next || next.attach != attachVimMap) + leaveVimMode(cm); + } + function attachVimMap(cm, prev) { + if (this == CodeMirror.keyMap.vim) { + CodeMirror.addClass(cm.getWrapperElement(), "cm-fat-cursor"); + if (cm.getOption("inputStyle") == "contenteditable" && document.body.style.caretColor != null) { + enableFatCursorMark(cm); + cm.getInputField().style.caretColor = "transparent"; + } + } + + if (!prev || prev.attach != attachVimMap) + enterVimMode(cm); + } + + function fatCursorMarks(cm) { + var ranges = cm.listSelections(), result = [] + for (var i = 0; i < ranges.length; i++) { + var range = ranges[i] + if (range.empty()) { + if (range.anchor.ch < cm.getLine(range.anchor.line).length) { + result.push(cm.markText(range.anchor, Pos(range.anchor.line, range.anchor.ch + 1), + {className: "cm-fat-cursor-mark"})) + } else { + var widget = document.createElement("span") + widget.textContent = "\u00a0" + widget.className = "cm-fat-cursor-mark" + result.push(cm.setBookmark(range.anchor, {widget: widget})) + } + } + } + return result + } + + function updateFatCursorMark(cm) { + var marks = cm.state.fatCursorMarks + if (marks) for (var i = 0; i < marks.length; i++) marks[i].clear() + cm.state.fatCursorMarks = fatCursorMarks(cm) + } + + function enableFatCursorMark(cm) { + cm.state.fatCursorMarks = fatCursorMarks(cm) + cm.on("cursorActivity", updateFatCursorMark) + } + + function disableFatCursorMark(cm) { + var marks = cm.state.fatCursorMarks + if (marks) for (var i = 0; i < marks.length; i++) marks[i].clear() + cm.state.fatCursorMarks = null + cm.off("cursorActivity", updateFatCursorMark) + } + + // Deprecated, simply setting the keymap works again. + CodeMirror.defineOption('vimMode', false, function(cm, val, prev) { + if (val && cm.getOption("keyMap") != "vim") + cm.setOption("keyMap", "vim"); + else if (!val && prev != CodeMirror.Init && /^vim/.test(cm.getOption("keyMap"))) + cm.setOption("keyMap", "default"); + }); + + function cmKey(key, cm) { + if (!cm) { return undefined; } + if (this[key]) { return this[key]; } + var vimKey = cmKeyToVimKey(key); + if (!vimKey) { + return false; + } + var cmd = CodeMirror.Vim.findKey(cm, vimKey); + if (typeof cmd == 'function') { + CodeMirror.signal(cm, 'vim-keypress', vimKey); + } + return cmd; + } + + var modifiers = {'Shift': 'S', 'Ctrl': 'C', 'Alt': 'A', 'Cmd': 'D', 'Mod': 'A'}; + var specialKeys = {Enter:'CR',Backspace:'BS',Delete:'Del',Insert:'Ins'}; + function cmKeyToVimKey(key) { + if (key.charAt(0) == '\'') { + // Keypress character binding of format "'a'" + return key.charAt(1); + } + var pieces = key.split(/-(?!$)/); + var lastPiece = pieces[pieces.length - 1]; + if (pieces.length == 1 && pieces[0].length == 1) { + // No-modifier bindings use literal character bindings above. Skip. + return false; + } else if (pieces.length == 2 && pieces[0] == 'Shift' && lastPiece.length == 1) { + // Ignore Shift+char bindings as they should be handled by literal character. + return false; + } + var hasCharacter = false; + for (var i = 0; i < pieces.length; i++) { + var piece = pieces[i]; + if (piece in modifiers) { pieces[i] = modifiers[piece]; } + else { hasCharacter = true; } + if (piece in specialKeys) { pieces[i] = specialKeys[piece]; } + } + if (!hasCharacter) { + // Vim does not support modifier only keys. + return false; + } + // TODO: Current bindings expect the character to be lower case, but + // it looks like vim key notation uses upper case. + if (isUpperCase(lastPiece)) { + pieces[pieces.length - 1] = lastPiece.toLowerCase(); + } + return '<' + pieces.join('-') + '>'; + } + + function getOnPasteFn(cm) { + var vim = cm.state.vim; + if (!vim.onPasteFn) { + vim.onPasteFn = function() { + if (!vim.insertMode) { + cm.setCursor(offsetCursor(cm.getCursor(), 0, 1)); + actions.enterInsertMode(cm, {}, vim); + } + }; + } + return vim.onPasteFn; + } + + var numberRegex = /[\d]/; + var wordCharTest = [CodeMirror.isWordChar, function(ch) { + return ch && !CodeMirror.isWordChar(ch) && !/\s/.test(ch); + }], bigWordCharTest = [function(ch) { + return /\S/.test(ch); + }]; + function makeKeyRange(start, size) { + var keys = []; + for (var i = start; i < start + size; i++) { + keys.push(String.fromCharCode(i)); + } + return keys; + } + var upperCaseAlphabet = makeKeyRange(65, 26); + var lowerCaseAlphabet = makeKeyRange(97, 26); + var numbers = makeKeyRange(48, 10); + var validMarks = [].concat(upperCaseAlphabet, lowerCaseAlphabet, numbers, ['<', '>']); + var validRegisters = [].concat(upperCaseAlphabet, lowerCaseAlphabet, numbers, ['-', '"', '.', ':', '/']); + + function isLine(cm, line) { + return line >= cm.firstLine() && line <= cm.lastLine(); + } + function isLowerCase(k) { + return (/^[a-z]$/).test(k); + } + function isMatchableSymbol(k) { + return '()[]{}'.indexOf(k) != -1; + } + function isNumber(k) { + return numberRegex.test(k); + } + function isUpperCase(k) { + return (/^[A-Z]$/).test(k); + } + function isWhiteSpaceString(k) { + return (/^\s*$/).test(k); + } + function isEndOfSentenceSymbol(k) { + return '.?!'.indexOf(k) != -1; + } + function inArray(val, arr) { + for (var i = 0; i < arr.length; i++) { + if (arr[i] == val) { + return true; + } + } + return false; + } + + var options = {}; + function defineOption(name, defaultValue, type, aliases, callback) { + if (defaultValue === undefined && !callback) { + throw Error('defaultValue is required unless callback is provided'); + } + if (!type) { type = 'string'; } + options[name] = { + type: type, + defaultValue: defaultValue, + callback: callback + }; + if (aliases) { + for (var i = 0; i < aliases.length; i++) { + options[aliases[i]] = options[name]; + } + } + if (defaultValue) { + setOption(name, defaultValue); + } + } + + function setOption(name, value, cm, cfg) { + var option = options[name]; + cfg = cfg || {}; + var scope = cfg.scope; + if (!option) { + return new Error('Unknown option: ' + name); + } + if (option.type == 'boolean') { + if (value && value !== true) { + return new Error('Invalid argument: ' + name + '=' + value); + } else if (value !== false) { + // Boolean options are set to true if value is not defined. + value = true; + } + } + if (option.callback) { + if (scope !== 'local') { + option.callback(value, undefined); + } + if (scope !== 'global' && cm) { + option.callback(value, cm); + } + } else { + if (scope !== 'local') { + option.value = option.type == 'boolean' ? !!value : value; + } + if (scope !== 'global' && cm) { + cm.state.vim.options[name] = {value: value}; + } + } + } + + function getOption(name, cm, cfg) { + var option = options[name]; + cfg = cfg || {}; + var scope = cfg.scope; + if (!option) { + return new Error('Unknown option: ' + name); + } + if (option.callback) { + var local = cm && option.callback(undefined, cm); + if (scope !== 'global' && local !== undefined) { + return local; + } + if (scope !== 'local') { + return option.callback(); + } + return; + } else { + var local = (scope !== 'global') && (cm && cm.state.vim.options[name]); + return (local || (scope !== 'local') && option || {}).value; + } + } + + defineOption('filetype', undefined, 'string', ['ft'], function(name, cm) { + // Option is local. Do nothing for global. + if (cm === undefined) { + return; + } + // The 'filetype' option proxies to the CodeMirror 'mode' option. + if (name === undefined) { + var mode = cm.getOption('mode'); + return mode == 'null' ? '' : mode; + } else { + var mode = name == '' ? 'null' : name; + cm.setOption('mode', mode); + } + }); + + var createCircularJumpList = function() { + var size = 100; + var pointer = -1; + var head = 0; + var tail = 0; + var buffer = new Array(size); + function add(cm, oldCur, newCur) { + var current = pointer % size; + var curMark = buffer[current]; + function useNextSlot(cursor) { + var next = ++pointer % size; + var trashMark = buffer[next]; + if (trashMark) { + trashMark.clear(); + } + buffer[next] = cm.setBookmark(cursor); + } + if (curMark) { + var markPos = curMark.find(); + // avoid recording redundant cursor position + if (markPos && !cursorEqual(markPos, oldCur)) { + useNextSlot(oldCur); + } + } else { + useNextSlot(oldCur); + } + useNextSlot(newCur); + head = pointer; + tail = pointer - size + 1; + if (tail < 0) { + tail = 0; + } + } + function move(cm, offset) { + pointer += offset; + if (pointer > head) { + pointer = head; + } else if (pointer < tail) { + pointer = tail; + } + var mark = buffer[(size + pointer) % size]; + // skip marks that are temporarily removed from text buffer + if (mark && !mark.find()) { + var inc = offset > 0 ? 1 : -1; + var newCur; + var oldCur = cm.getCursor(); + do { + pointer += inc; + mark = buffer[(size + pointer) % size]; + // skip marks that are the same as current position + if (mark && + (newCur = mark.find()) && + !cursorEqual(oldCur, newCur)) { + break; + } + } while (pointer < head && pointer > tail); + } + return mark; + } + return { + cachedCursor: undefined, //used for # and * jumps + add: add, + move: move + }; + }; + + // Returns an object to track the changes associated insert mode. It + // clones the object that is passed in, or creates an empty object one if + // none is provided. + var createInsertModeChanges = function(c) { + if (c) { + // Copy construction + return { + changes: c.changes, + expectCursorActivityForChange: c.expectCursorActivityForChange + }; + } + return { + // Change list + changes: [], + // Set to true on change, false on cursorActivity. + expectCursorActivityForChange: false + }; + }; + + function MacroModeState() { + this.latestRegister = undefined; + this.isPlaying = false; + this.isRecording = false; + this.replaySearchQueries = []; + this.onRecordingDone = undefined; + this.lastInsertModeChanges = createInsertModeChanges(); + } + MacroModeState.prototype = { + exitMacroRecordMode: function() { + var macroModeState = vimGlobalState.macroModeState; + if (macroModeState.onRecordingDone) { + macroModeState.onRecordingDone(); // close dialog + } + macroModeState.onRecordingDone = undefined; + macroModeState.isRecording = false; + }, + enterMacroRecordMode: function(cm, registerName) { + var register = + vimGlobalState.registerController.getRegister(registerName); + if (register) { + register.clear(); + this.latestRegister = registerName; + if (cm.openDialog) { + this.onRecordingDone = cm.openDialog( + '(recording)['+registerName+']', null, {bottom:true}); + } + this.isRecording = true; + } + } + }; + + function maybeInitVimState(cm) { + if (!cm.state.vim) { + // Store instance state in the CodeMirror object. + cm.state.vim = { + inputState: new InputState(), + // Vim's input state that triggered the last edit, used to repeat + // motions and operators with '.'. + lastEditInputState: undefined, + // Vim's action command before the last edit, used to repeat actions + // with '.' and insert mode repeat. + lastEditActionCommand: undefined, + // When using jk for navigation, if you move from a longer line to a + // shorter line, the cursor may clip to the end of the shorter line. + // If j is pressed again and cursor goes to the next line, the + // cursor should go back to its horizontal position on the longer + // line if it can. This is to keep track of the horizontal position. + lastHPos: -1, + // Doing the same with screen-position for gj/gk + lastHSPos: -1, + // The last motion command run. Cleared if a non-motion command gets + // executed in between. + lastMotion: null, + marks: {}, + // Mark for rendering fake cursor for visual mode. + fakeCursor: null, + insertMode: false, + // Repeat count for changes made in insert mode, triggered by key + // sequences like 3,i. Only exists when insertMode is true. + insertModeRepeat: undefined, + visualMode: false, + // If we are in visual line mode. No effect if visualMode is false. + visualLine: false, + visualBlock: false, + lastSelection: null, + lastPastedText: null, + sel: {}, + // Buffer-local/window-local values of vim options. + options: {} + }; + } + return cm.state.vim; + } + var vimGlobalState; + function resetVimGlobalState() { + vimGlobalState = { + // The current search query. + searchQuery: null, + // Whether we are searching backwards. + searchIsReversed: false, + // Replace part of the last substituted pattern + lastSubstituteReplacePart: undefined, + jumpList: createCircularJumpList(), + macroModeState: new MacroModeState, + // Recording latest f, t, F or T motion command. + lastCharacterSearch: {increment:0, forward:true, selectedCharacter:''}, + registerController: new RegisterController({}), + // search history buffer + searchHistoryController: new HistoryController(), + // ex Command history buffer + exCommandHistoryController : new HistoryController() + }; + for (var optionName in options) { + var option = options[optionName]; + option.value = option.defaultValue; + } + } + + var lastInsertModeKeyTimer; + var vimApi= { + buildKeyMap: function() { + // TODO: Convert keymap into dictionary format for fast lookup. + }, + // Testing hook, though it might be useful to expose the register + // controller anyways. + getRegisterController: function() { + return vimGlobalState.registerController; + }, + // Testing hook. + resetVimGlobalState_: resetVimGlobalState, + + // Testing hook. + getVimGlobalState_: function() { + return vimGlobalState; + }, + + // Testing hook. + maybeInitVimState_: maybeInitVimState, + + suppressErrorLogging: false, + + InsertModeKey: InsertModeKey, + map: function(lhs, rhs, ctx) { + // Add user defined key bindings. + exCommandDispatcher.map(lhs, rhs, ctx); + }, + unmap: function(lhs, ctx) { + exCommandDispatcher.unmap(lhs, ctx); + }, + // TODO: Expose setOption and getOption as instance methods. Need to decide how to namespace + // them, or somehow make them work with the existing CodeMirror setOption/getOption API. + setOption: setOption, + getOption: getOption, + defineOption: defineOption, + defineEx: function(name, prefix, func){ + if (!prefix) { + prefix = name; + } else if (name.indexOf(prefix) !== 0) { + throw new Error('(Vim.defineEx) "'+prefix+'" is not a prefix of "'+name+'", command not registered'); + } + exCommands[name]=func; + exCommandDispatcher.commandMap_[prefix]={name:name, shortName:prefix, type:'api'}; + }, + handleKey: function (cm, key, origin) { + var command = this.findKey(cm, key, origin); + if (typeof command === 'function') { + return command(); + } + }, + /** + * This is the outermost function called by CodeMirror, after keys have + * been mapped to their Vim equivalents. + * + * Finds a command based on the key (and cached keys if there is a + * multi-key sequence). Returns `undefined` if no key is matched, a noop + * function if a partial match is found (multi-key), and a function to + * execute the bound command if a a key is matched. The function always + * returns true. + */ + findKey: function(cm, key, origin) { + var vim = maybeInitVimState(cm); + function handleMacroRecording() { + var macroModeState = vimGlobalState.macroModeState; + if (macroModeState.isRecording) { + if (key == 'q') { + macroModeState.exitMacroRecordMode(); + clearInputState(cm); + return true; + } + if (origin != 'mapping') { + logKey(macroModeState, key); + } + } + } + function handleEsc() { + if (key == '') { + // Clear input state and get back to normal mode. + clearInputState(cm); + if (vim.visualMode) { + exitVisualMode(cm); + } else if (vim.insertMode) { + exitInsertMode(cm); + } + return true; + } + } + function doKeyToKey(keys) { + // TODO: prevent infinite recursion. + var match; + while (keys) { + // Pull off one command key, which is either a single character + // or a special sequence wrapped in '<' and '>', e.g. ''. + match = (/<\w+-.+?>|<\w+>|./).exec(keys); + key = match[0]; + keys = keys.substring(match.index + key.length); + CodeMirror.Vim.handleKey(cm, key, 'mapping'); + } + } + + function handleKeyInsertMode() { + if (handleEsc()) { return true; } + var keys = vim.inputState.keyBuffer = vim.inputState.keyBuffer + key; + var keysAreChars = key.length == 1; + var match = commandDispatcher.matchCommand(keys, defaultKeymap, vim.inputState, 'insert'); + // Need to check all key substrings in insert mode. + while (keys.length > 1 && match.type != 'full') { + var keys = vim.inputState.keyBuffer = keys.slice(1); + var thisMatch = commandDispatcher.matchCommand(keys, defaultKeymap, vim.inputState, 'insert'); + if (thisMatch.type != 'none') { match = thisMatch; } + } + if (match.type == 'none') { clearInputState(cm); return false; } + else if (match.type == 'partial') { + if (lastInsertModeKeyTimer) { window.clearTimeout(lastInsertModeKeyTimer); } + lastInsertModeKeyTimer = window.setTimeout( + function() { if (vim.insertMode && vim.inputState.keyBuffer) { clearInputState(cm); } }, + getOption('insertModeEscKeysTimeout')); + return !keysAreChars; + } + + if (lastInsertModeKeyTimer) { window.clearTimeout(lastInsertModeKeyTimer); } + if (keysAreChars) { + var selections = cm.listSelections(); + for (var i = 0; i < selections.length; i++) { + var here = selections[i].head; + cm.replaceRange('', offsetCursor(here, 0, -(keys.length - 1)), here, '+input'); + } + vimGlobalState.macroModeState.lastInsertModeChanges.changes.pop(); + } + clearInputState(cm); + return match.command; + } + + function handleKeyNonInsertMode() { + if (handleMacroRecording() || handleEsc()) { return true; } + + var keys = vim.inputState.keyBuffer = vim.inputState.keyBuffer + key; + if (/^[1-9]\d*$/.test(keys)) { return true; } + + var keysMatcher = /^(\d*)(.*)$/.exec(keys); + if (!keysMatcher) { clearInputState(cm); return false; } + var context = vim.visualMode ? 'visual' : + 'normal'; + var match = commandDispatcher.matchCommand(keysMatcher[2] || keysMatcher[1], defaultKeymap, vim.inputState, context); + if (match.type == 'none') { clearInputState(cm); return false; } + else if (match.type == 'partial') { return true; } + + vim.inputState.keyBuffer = ''; + var keysMatcher = /^(\d*)(.*)$/.exec(keys); + if (keysMatcher[1] && keysMatcher[1] != '0') { + vim.inputState.pushRepeatDigit(keysMatcher[1]); + } + return match.command; + } + + var command; + if (vim.insertMode) { command = handleKeyInsertMode(); } + else { command = handleKeyNonInsertMode(); } + if (command === false) { + return !vim.insertMode && key.length === 1 ? function() { return true; } : undefined; + } else if (command === true) { + // TODO: Look into using CodeMirror's multi-key handling. + // Return no-op since we are caching the key. Counts as handled, but + // don't want act on it just yet. + return function() { return true; }; + } else { + return function() { + return cm.operation(function() { + cm.curOp.isVimOp = true; + try { + if (command.type == 'keyToKey') { + doKeyToKey(command.toKeys); + } else { + commandDispatcher.processCommand(cm, vim, command); + } + } catch (e) { + // clear VIM state in case it's in a bad state. + cm.state.vim = undefined; + maybeInitVimState(cm); + if (!CodeMirror.Vim.suppressErrorLogging) { + console['log'](e); + } + throw e; + } + return true; + }); + }; + } + }, + handleEx: function(cm, input) { + exCommandDispatcher.processCommand(cm, input); + }, + + defineMotion: defineMotion, + defineAction: defineAction, + defineOperator: defineOperator, + mapCommand: mapCommand, + _mapCommand: _mapCommand, + + defineRegister: defineRegister, + + exitVisualMode: exitVisualMode, + exitInsertMode: exitInsertMode + }; + + // Represents the current input state. + function InputState() { + this.prefixRepeat = []; + this.motionRepeat = []; + + this.operator = null; + this.operatorArgs = null; + this.motion = null; + this.motionArgs = null; + this.keyBuffer = []; // For matching multi-key commands. + this.registerName = null; // Defaults to the unnamed register. + } + InputState.prototype.pushRepeatDigit = function(n) { + if (!this.operator) { + this.prefixRepeat = this.prefixRepeat.concat(n); + } else { + this.motionRepeat = this.motionRepeat.concat(n); + } + }; + InputState.prototype.getRepeat = function() { + var repeat = 0; + if (this.prefixRepeat.length > 0 || this.motionRepeat.length > 0) { + repeat = 1; + if (this.prefixRepeat.length > 0) { + repeat *= parseInt(this.prefixRepeat.join(''), 10); + } + if (this.motionRepeat.length > 0) { + repeat *= parseInt(this.motionRepeat.join(''), 10); + } + } + return repeat; + }; + + function clearInputState(cm, reason) { + cm.state.vim.inputState = new InputState(); + CodeMirror.signal(cm, 'vim-command-done', reason); + } + + /* + * Register stores information about copy and paste registers. Besides + * text, a register must store whether it is linewise (i.e., when it is + * pasted, should it insert itself into a new line, or should the text be + * inserted at the cursor position.) + */ + function Register(text, linewise, blockwise) { + this.clear(); + this.keyBuffer = [text || '']; + this.insertModeChanges = []; + this.searchQueries = []; + this.linewise = !!linewise; + this.blockwise = !!blockwise; + } + Register.prototype = { + setText: function(text, linewise, blockwise) { + this.keyBuffer = [text || '']; + this.linewise = !!linewise; + this.blockwise = !!blockwise; + }, + pushText: function(text, linewise) { + // if this register has ever been set to linewise, use linewise. + if (linewise) { + if (!this.linewise) { + this.keyBuffer.push('\n'); + } + this.linewise = true; + } + this.keyBuffer.push(text); + }, + pushInsertModeChanges: function(changes) { + this.insertModeChanges.push(createInsertModeChanges(changes)); + }, + pushSearchQuery: function(query) { + this.searchQueries.push(query); + }, + clear: function() { + this.keyBuffer = []; + this.insertModeChanges = []; + this.searchQueries = []; + this.linewise = false; + }, + toString: function() { + return this.keyBuffer.join(''); + } + }; + + /** + * Defines an external register. + * + * The name should be a single character that will be used to reference the register. + * The register should support setText, pushText, clear, and toString(). See Register + * for a reference implementation. + */ + function defineRegister(name, register) { + var registers = vimGlobalState.registerController.registers; + if (!name || name.length != 1) { + throw Error('Register name must be 1 character'); + } + if (registers[name]) { + throw Error('Register already defined ' + name); + } + registers[name] = register; + validRegisters.push(name); + } + + /* + * vim registers allow you to keep many independent copy and paste buffers. + * See http://usevim.com/2012/04/13/registers/ for an introduction. + * + * RegisterController keeps the state of all the registers. An initial + * state may be passed in. The unnamed register '"' will always be + * overridden. + */ + function RegisterController(registers) { + this.registers = registers; + this.unnamedRegister = registers['"'] = new Register(); + registers['.'] = new Register(); + registers[':'] = new Register(); + registers['/'] = new Register(); + } + RegisterController.prototype = { + pushText: function(registerName, operator, text, linewise, blockwise) { + if (linewise && text.charAt(text.length - 1) !== '\n'){ + text += '\n'; + } + // Lowercase and uppercase registers refer to the same register. + // Uppercase just means append. + var register = this.isValidRegister(registerName) ? + this.getRegister(registerName) : null; + // if no register/an invalid register was specified, things go to the + // default registers + if (!register) { + switch (operator) { + case 'yank': + // The 0 register contains the text from the most recent yank. + this.registers['0'] = new Register(text, linewise, blockwise); + break; + case 'delete': + case 'change': + if (text.indexOf('\n') == -1) { + // Delete less than 1 line. Update the small delete register. + this.registers['-'] = new Register(text, linewise); + } else { + // Shift down the contents of the numbered registers and put the + // deleted text into register 1. + this.shiftNumericRegisters_(); + this.registers['1'] = new Register(text, linewise); + } + break; + } + // Make sure the unnamed register is set to what just happened + this.unnamedRegister.setText(text, linewise, blockwise); + return; + } + + // If we've gotten to this point, we've actually specified a register + var append = isUpperCase(registerName); + if (append) { + register.pushText(text, linewise); + } else { + register.setText(text, linewise, blockwise); + } + // The unnamed register always has the same value as the last used + // register. + this.unnamedRegister.setText(register.toString(), linewise); + }, + // Gets the register named @name. If one of @name doesn't already exist, + // create it. If @name is invalid, return the unnamedRegister. + getRegister: function(name) { + if (!this.isValidRegister(name)) { + return this.unnamedRegister; + } + name = name.toLowerCase(); + if (!this.registers[name]) { + this.registers[name] = new Register(); + } + return this.registers[name]; + }, + isValidRegister: function(name) { + return name && inArray(name, validRegisters); + }, + shiftNumericRegisters_: function() { + for (var i = 9; i >= 2; i--) { + this.registers[i] = this.getRegister('' + (i - 1)); + } + } + }; + function HistoryController() { + this.historyBuffer = []; + this.iterator = 0; + this.initialPrefix = null; + } + HistoryController.prototype = { + // the input argument here acts a user entered prefix for a small time + // until we start autocompletion in which case it is the autocompleted. + nextMatch: function (input, up) { + var historyBuffer = this.historyBuffer; + var dir = up ? -1 : 1; + if (this.initialPrefix === null) this.initialPrefix = input; + for (var i = this.iterator + dir; up ? i >= 0 : i < historyBuffer.length; i+= dir) { + var element = historyBuffer[i]; + for (var j = 0; j <= element.length; j++) { + if (this.initialPrefix == element.substring(0, j)) { + this.iterator = i; + return element; + } + } + } + // should return the user input in case we reach the end of buffer. + if (i >= historyBuffer.length) { + this.iterator = historyBuffer.length; + return this.initialPrefix; + } + // return the last autocompleted query or exCommand as it is. + if (i < 0 ) return input; + }, + pushInput: function(input) { + var index = this.historyBuffer.indexOf(input); + if (index > -1) this.historyBuffer.splice(index, 1); + if (input.length) this.historyBuffer.push(input); + }, + reset: function() { + this.initialPrefix = null; + this.iterator = this.historyBuffer.length; + } + }; + var commandDispatcher = { + matchCommand: function(keys, keyMap, inputState, context) { + var matches = commandMatches(keys, keyMap, context, inputState); + if (!matches.full && !matches.partial) { + return {type: 'none'}; + } else if (!matches.full && matches.partial) { + return {type: 'partial'}; + } + + var bestMatch; + for (var i = 0; i < matches.full.length; i++) { + var match = matches.full[i]; + if (!bestMatch) { + bestMatch = match; + } + } + if (bestMatch.keys.slice(-11) == '') { + var character = lastChar(keys); + if (!character) return {type: 'none'}; + inputState.selectedCharacter = character; + } + return {type: 'full', command: bestMatch}; + }, + processCommand: function(cm, vim, command) { + vim.inputState.repeatOverride = command.repeatOverride; + switch (command.type) { + case 'motion': + this.processMotion(cm, vim, command); + break; + case 'operator': + this.processOperator(cm, vim, command); + break; + case 'operatorMotion': + this.processOperatorMotion(cm, vim, command); + break; + case 'action': + this.processAction(cm, vim, command); + break; + case 'search': + this.processSearch(cm, vim, command); + break; + case 'ex': + case 'keyToEx': + this.processEx(cm, vim, command); + break; + default: + break; + } + }, + processMotion: function(cm, vim, command) { + vim.inputState.motion = command.motion; + vim.inputState.motionArgs = copyArgs(command.motionArgs); + this.evalInput(cm, vim); + }, + processOperator: function(cm, vim, command) { + var inputState = vim.inputState; + if (inputState.operator) { + if (inputState.operator == command.operator) { + // Typing an operator twice like 'dd' makes the operator operate + // linewise + inputState.motion = 'expandToLine'; + inputState.motionArgs = { linewise: true }; + this.evalInput(cm, vim); + return; + } else { + // 2 different operators in a row doesn't make sense. + clearInputState(cm); + } + } + inputState.operator = command.operator; + inputState.operatorArgs = copyArgs(command.operatorArgs); + if (vim.visualMode) { + // Operating on a selection in visual mode. We don't need a motion. + this.evalInput(cm, vim); + } + }, + processOperatorMotion: function(cm, vim, command) { + var visualMode = vim.visualMode; + var operatorMotionArgs = copyArgs(command.operatorMotionArgs); + if (operatorMotionArgs) { + // Operator motions may have special behavior in visual mode. + if (visualMode && operatorMotionArgs.visualLine) { + vim.visualLine = true; + } + } + this.processOperator(cm, vim, command); + if (!visualMode) { + this.processMotion(cm, vim, command); + } + }, + processAction: function(cm, vim, command) { + var inputState = vim.inputState; + var repeat = inputState.getRepeat(); + var repeatIsExplicit = !!repeat; + var actionArgs = copyArgs(command.actionArgs) || {}; + if (inputState.selectedCharacter) { + actionArgs.selectedCharacter = inputState.selectedCharacter; + } + // Actions may or may not have motions and operators. Do these first. + if (command.operator) { + this.processOperator(cm, vim, command); + } + if (command.motion) { + this.processMotion(cm, vim, command); + } + if (command.motion || command.operator) { + this.evalInput(cm, vim); + } + actionArgs.repeat = repeat || 1; + actionArgs.repeatIsExplicit = repeatIsExplicit; + actionArgs.registerName = inputState.registerName; + clearInputState(cm); + vim.lastMotion = null; + if (command.isEdit) { + this.recordLastEdit(vim, inputState, command); + } + actions[command.action](cm, actionArgs, vim); + }, + processSearch: function(cm, vim, command) { + if (!cm.getSearchCursor) { + // Search depends on SearchCursor. + return; + } + var forward = command.searchArgs.forward; + var wholeWordOnly = command.searchArgs.wholeWordOnly; + getSearchState(cm).setReversed(!forward); + var promptPrefix = (forward) ? '/' : '?'; + var originalQuery = getSearchState(cm).getQuery(); + var originalScrollPos = cm.getScrollInfo(); + function handleQuery(query, ignoreCase, smartCase) { + vimGlobalState.searchHistoryController.pushInput(query); + vimGlobalState.searchHistoryController.reset(); + try { + updateSearchQuery(cm, query, ignoreCase, smartCase); + } catch (e) { + showConfirm(cm, 'Invalid regex: ' + query); + clearInputState(cm); + return; + } + commandDispatcher.processMotion(cm, vim, { + type: 'motion', + motion: 'findNext', + motionArgs: { forward: true, toJumplist: command.searchArgs.toJumplist } + }); + } + function onPromptClose(query) { + cm.scrollTo(originalScrollPos.left, originalScrollPos.top); + handleQuery(query, true /** ignoreCase */, true /** smartCase */); + var macroModeState = vimGlobalState.macroModeState; + if (macroModeState.isRecording) { + logSearchQuery(macroModeState, query); + } + } + function onPromptKeyUp(e, query, close) { + var keyName = CodeMirror.keyName(e), up, offset; + if (keyName == 'Up' || keyName == 'Down') { + up = keyName == 'Up' ? true : false; + offset = e.target ? e.target.selectionEnd : 0; + query = vimGlobalState.searchHistoryController.nextMatch(query, up) || ''; + close(query); + if (offset && e.target) e.target.selectionEnd = e.target.selectionStart = Math.min(offset, e.target.value.length); + } else { + if ( keyName != 'Left' && keyName != 'Right' && keyName != 'Ctrl' && keyName != 'Alt' && keyName != 'Shift') + vimGlobalState.searchHistoryController.reset(); + } + var parsedQuery; + try { + parsedQuery = updateSearchQuery(cm, query, + true /** ignoreCase */, true /** smartCase */); + } catch (e) { + // Swallow bad regexes for incremental search. + } + if (parsedQuery) { + cm.scrollIntoView(findNext(cm, !forward, parsedQuery), 30); + } else { + clearSearchHighlight(cm); + cm.scrollTo(originalScrollPos.left, originalScrollPos.top); + } + } + function onPromptKeyDown(e, query, close) { + var keyName = CodeMirror.keyName(e); + if (keyName == 'Esc' || keyName == 'Ctrl-C' || keyName == 'Ctrl-[' || + (keyName == 'Backspace' && query == '')) { + vimGlobalState.searchHistoryController.pushInput(query); + vimGlobalState.searchHistoryController.reset(); + updateSearchQuery(cm, originalQuery); + clearSearchHighlight(cm); + cm.scrollTo(originalScrollPos.left, originalScrollPos.top); + CodeMirror.e_stop(e); + clearInputState(cm); + close(); + cm.focus(); + } else if (keyName == 'Up' || keyName == 'Down') { + CodeMirror.e_stop(e); + } else if (keyName == 'Ctrl-U') { + // Ctrl-U clears input. + CodeMirror.e_stop(e); + close(''); + } + } + switch (command.searchArgs.querySrc) { + case 'prompt': + var macroModeState = vimGlobalState.macroModeState; + if (macroModeState.isPlaying) { + var query = macroModeState.replaySearchQueries.shift(); + handleQuery(query, true /** ignoreCase */, false /** smartCase */); + } else { + showPrompt(cm, { + onClose: onPromptClose, + prefix: promptPrefix, + desc: searchPromptDesc, + onKeyUp: onPromptKeyUp, + onKeyDown: onPromptKeyDown + }); + } + break; + case 'wordUnderCursor': + var word = expandWordUnderCursor(cm, false /** inclusive */, + true /** forward */, false /** bigWord */, + true /** noSymbol */); + var isKeyword = true; + if (!word) { + word = expandWordUnderCursor(cm, false /** inclusive */, + true /** forward */, false /** bigWord */, + false /** noSymbol */); + isKeyword = false; + } + if (!word) { + return; + } + var query = cm.getLine(word.start.line).substring(word.start.ch, + word.end.ch); + if (isKeyword && wholeWordOnly) { + query = '\\b' + query + '\\b'; + } else { + query = escapeRegex(query); + } + + // cachedCursor is used to save the old position of the cursor + // when * or # causes vim to seek for the nearest word and shift + // the cursor before entering the motion. + vimGlobalState.jumpList.cachedCursor = cm.getCursor(); + cm.setCursor(word.start); + + handleQuery(query, true /** ignoreCase */, false /** smartCase */); + break; + } + }, + processEx: function(cm, vim, command) { + function onPromptClose(input) { + // Give the prompt some time to close so that if processCommand shows + // an error, the elements don't overlap. + vimGlobalState.exCommandHistoryController.pushInput(input); + vimGlobalState.exCommandHistoryController.reset(); + exCommandDispatcher.processCommand(cm, input); + } + function onPromptKeyDown(e, input, close) { + var keyName = CodeMirror.keyName(e), up, offset; + if (keyName == 'Esc' || keyName == 'Ctrl-C' || keyName == 'Ctrl-[' || + (keyName == 'Backspace' && input == '')) { + vimGlobalState.exCommandHistoryController.pushInput(input); + vimGlobalState.exCommandHistoryController.reset(); + CodeMirror.e_stop(e); + clearInputState(cm); + close(); + cm.focus(); + } + if (keyName == 'Up' || keyName == 'Down') { + CodeMirror.e_stop(e); + up = keyName == 'Up' ? true : false; + offset = e.target ? e.target.selectionEnd : 0; + input = vimGlobalState.exCommandHistoryController.nextMatch(input, up) || ''; + close(input); + if (offset && e.target) e.target.selectionEnd = e.target.selectionStart = Math.min(offset, e.target.value.length); + } else if (keyName == 'Ctrl-U') { + // Ctrl-U clears input. + CodeMirror.e_stop(e); + close(''); + } else { + if ( keyName != 'Left' && keyName != 'Right' && keyName != 'Ctrl' && keyName != 'Alt' && keyName != 'Shift') + vimGlobalState.exCommandHistoryController.reset(); + } + } + if (command.type == 'keyToEx') { + // Handle user defined Ex to Ex mappings + exCommandDispatcher.processCommand(cm, command.exArgs.input); + } else { + if (vim.visualMode) { + showPrompt(cm, { onClose: onPromptClose, prefix: ':', value: '\'<,\'>', + onKeyDown: onPromptKeyDown, selectValueOnOpen: false}); + } else { + showPrompt(cm, { onClose: onPromptClose, prefix: ':', + onKeyDown: onPromptKeyDown}); + } + } + }, + evalInput: function(cm, vim) { + // If the motion command is set, execute both the operator and motion. + // Otherwise return. + var inputState = vim.inputState; + var motion = inputState.motion; + var motionArgs = inputState.motionArgs || {}; + var operator = inputState.operator; + var operatorArgs = inputState.operatorArgs || {}; + var registerName = inputState.registerName; + var sel = vim.sel; + // TODO: Make sure cm and vim selections are identical outside visual mode. + var origHead = copyCursor(vim.visualMode ? clipCursorToContent(cm, sel.head): cm.getCursor('head')); + var origAnchor = copyCursor(vim.visualMode ? clipCursorToContent(cm, sel.anchor) : cm.getCursor('anchor')); + var oldHead = copyCursor(origHead); + var oldAnchor = copyCursor(origAnchor); + var newHead, newAnchor; + var repeat; + if (operator) { + this.recordLastEdit(vim, inputState); + } + if (inputState.repeatOverride !== undefined) { + // If repeatOverride is specified, that takes precedence over the + // input state's repeat. Used by Ex mode and can be user defined. + repeat = inputState.repeatOverride; + } else { + repeat = inputState.getRepeat(); + } + if (repeat > 0 && motionArgs.explicitRepeat) { + motionArgs.repeatIsExplicit = true; + } else if (motionArgs.noRepeat || + (!motionArgs.explicitRepeat && repeat === 0)) { + repeat = 1; + motionArgs.repeatIsExplicit = false; + } + if (inputState.selectedCharacter) { + // If there is a character input, stick it in all of the arg arrays. + motionArgs.selectedCharacter = operatorArgs.selectedCharacter = + inputState.selectedCharacter; + } + motionArgs.repeat = repeat; + clearInputState(cm); + if (motion) { + var motionResult = motions[motion](cm, origHead, motionArgs, vim); + vim.lastMotion = motions[motion]; + if (!motionResult) { + return; + } + if (motionArgs.toJumplist) { + var jumpList = vimGlobalState.jumpList; + // if the current motion is # or *, use cachedCursor + var cachedCursor = jumpList.cachedCursor; + if (cachedCursor) { + recordJumpPosition(cm, cachedCursor, motionResult); + delete jumpList.cachedCursor; + } else { + recordJumpPosition(cm, origHead, motionResult); + } + } + if (motionResult instanceof Array) { + newAnchor = motionResult[0]; + newHead = motionResult[1]; + } else { + newHead = motionResult; + } + // TODO: Handle null returns from motion commands better. + if (!newHead) { + newHead = copyCursor(origHead); + } + if (vim.visualMode) { + if (!(vim.visualBlock && newHead.ch === Infinity)) { + newHead = clipCursorToContent(cm, newHead, vim.visualBlock); + } + if (newAnchor) { + newAnchor = clipCursorToContent(cm, newAnchor, true); + } + newAnchor = newAnchor || oldAnchor; + sel.anchor = newAnchor; + sel.head = newHead; + updateCmSelection(cm); + updateMark(cm, vim, '<', + cursorIsBefore(newAnchor, newHead) ? newAnchor + : newHead); + updateMark(cm, vim, '>', + cursorIsBefore(newAnchor, newHead) ? newHead + : newAnchor); + } else if (!operator) { + newHead = clipCursorToContent(cm, newHead); + cm.setCursor(newHead.line, newHead.ch); + } + } + if (operator) { + if (operatorArgs.lastSel) { + // Replaying a visual mode operation + newAnchor = oldAnchor; + var lastSel = operatorArgs.lastSel; + var lineOffset = Math.abs(lastSel.head.line - lastSel.anchor.line); + var chOffset = Math.abs(lastSel.head.ch - lastSel.anchor.ch); + if (lastSel.visualLine) { + // Linewise Visual mode: The same number of lines. + newHead = Pos(oldAnchor.line + lineOffset, oldAnchor.ch); + } else if (lastSel.visualBlock) { + // Blockwise Visual mode: The same number of lines and columns. + newHead = Pos(oldAnchor.line + lineOffset, oldAnchor.ch + chOffset); + } else if (lastSel.head.line == lastSel.anchor.line) { + // Normal Visual mode within one line: The same number of characters. + newHead = Pos(oldAnchor.line, oldAnchor.ch + chOffset); + } else { + // Normal Visual mode with several lines: The same number of lines, in the + // last line the same number of characters as in the last line the last time. + newHead = Pos(oldAnchor.line + lineOffset, oldAnchor.ch); + } + vim.visualMode = true; + vim.visualLine = lastSel.visualLine; + vim.visualBlock = lastSel.visualBlock; + sel = vim.sel = { + anchor: newAnchor, + head: newHead + }; + updateCmSelection(cm); + } else if (vim.visualMode) { + operatorArgs.lastSel = { + anchor: copyCursor(sel.anchor), + head: copyCursor(sel.head), + visualBlock: vim.visualBlock, + visualLine: vim.visualLine + }; + } + var curStart, curEnd, linewise, mode; + var cmSel; + if (vim.visualMode) { + // Init visual op + curStart = cursorMin(sel.head, sel.anchor); + curEnd = cursorMax(sel.head, sel.anchor); + linewise = vim.visualLine || operatorArgs.linewise; + mode = vim.visualBlock ? 'block' : + linewise ? 'line' : + 'char'; + cmSel = makeCmSelection(cm, { + anchor: curStart, + head: curEnd + }, mode); + if (linewise) { + var ranges = cmSel.ranges; + if (mode == 'block') { + // Linewise operators in visual block mode extend to end of line + for (var i = 0; i < ranges.length; i++) { + ranges[i].head.ch = lineLength(cm, ranges[i].head.line); + } + } else if (mode == 'line') { + ranges[0].head = Pos(ranges[0].head.line + 1, 0); + } + } + } else { + // Init motion op + curStart = copyCursor(newAnchor || oldAnchor); + curEnd = copyCursor(newHead || oldHead); + if (cursorIsBefore(curEnd, curStart)) { + var tmp = curStart; + curStart = curEnd; + curEnd = tmp; + } + linewise = motionArgs.linewise || operatorArgs.linewise; + if (linewise) { + // Expand selection to entire line. + expandSelectionToLine(cm, curStart, curEnd); + } else if (motionArgs.forward) { + // Clip to trailing newlines only if the motion goes forward. + clipToLine(cm, curStart, curEnd); + } + mode = 'char'; + var exclusive = !motionArgs.inclusive || linewise; + cmSel = makeCmSelection(cm, { + anchor: curStart, + head: curEnd + }, mode, exclusive); + } + cm.setSelections(cmSel.ranges, cmSel.primary); + vim.lastMotion = null; + operatorArgs.repeat = repeat; // For indent in visual mode. + operatorArgs.registerName = registerName; + // Keep track of linewise as it affects how paste and change behave. + operatorArgs.linewise = linewise; + var operatorMoveTo = operators[operator]( + cm, operatorArgs, cmSel.ranges, oldAnchor, newHead); + if (vim.visualMode) { + exitVisualMode(cm, operatorMoveTo != null); + } + if (operatorMoveTo) { + cm.setCursor(operatorMoveTo); + } + } + }, + recordLastEdit: function(vim, inputState, actionCommand) { + var macroModeState = vimGlobalState.macroModeState; + if (macroModeState.isPlaying) { return; } + vim.lastEditInputState = inputState; + vim.lastEditActionCommand = actionCommand; + macroModeState.lastInsertModeChanges.changes = []; + macroModeState.lastInsertModeChanges.expectCursorActivityForChange = false; + } + }; + + /** + * typedef {Object{line:number,ch:number}} Cursor An object containing the + * position of the cursor. + */ + // All of the functions below return Cursor objects. + var motions = { + moveToTopLine: function(cm, _head, motionArgs) { + var line = getUserVisibleLines(cm).top + motionArgs.repeat -1; + return Pos(line, findFirstNonWhiteSpaceCharacter(cm.getLine(line))); + }, + moveToMiddleLine: function(cm) { + var range = getUserVisibleLines(cm); + var line = Math.floor((range.top + range.bottom) * 0.5); + return Pos(line, findFirstNonWhiteSpaceCharacter(cm.getLine(line))); + }, + moveToBottomLine: function(cm, _head, motionArgs) { + var line = getUserVisibleLines(cm).bottom - motionArgs.repeat +1; + return Pos(line, findFirstNonWhiteSpaceCharacter(cm.getLine(line))); + }, + expandToLine: function(_cm, head, motionArgs) { + // Expands forward to end of line, and then to next line if repeat is + // >1. Does not handle backward motion! + var cur = head; + return Pos(cur.line + motionArgs.repeat - 1, Infinity); + }, + findNext: function(cm, _head, motionArgs) { + var state = getSearchState(cm); + var query = state.getQuery(); + if (!query) { + return; + } + var prev = !motionArgs.forward; + // If search is initiated with ? instead of /, negate direction. + prev = (state.isReversed()) ? !prev : prev; + highlightSearchMatches(cm, query); + return findNext(cm, prev/** prev */, query, motionArgs.repeat); + }, + goToMark: function(cm, _head, motionArgs, vim) { + var pos = getMarkPos(cm, vim, motionArgs.selectedCharacter); + if (pos) { + return motionArgs.linewise ? { line: pos.line, ch: findFirstNonWhiteSpaceCharacter(cm.getLine(pos.line)) } : pos; + } + return null; + }, + moveToOtherHighlightedEnd: function(cm, _head, motionArgs, vim) { + if (vim.visualBlock && motionArgs.sameLine) { + var sel = vim.sel; + return [ + clipCursorToContent(cm, Pos(sel.anchor.line, sel.head.ch)), + clipCursorToContent(cm, Pos(sel.head.line, sel.anchor.ch)) + ]; + } else { + return ([vim.sel.head, vim.sel.anchor]); + } + }, + jumpToMark: function(cm, head, motionArgs, vim) { + var best = head; + for (var i = 0; i < motionArgs.repeat; i++) { + var cursor = best; + for (var key in vim.marks) { + if (!isLowerCase(key)) { + continue; + } + var mark = vim.marks[key].find(); + var isWrongDirection = (motionArgs.forward) ? + cursorIsBefore(mark, cursor) : cursorIsBefore(cursor, mark); + + if (isWrongDirection) { + continue; + } + if (motionArgs.linewise && (mark.line == cursor.line)) { + continue; + } + + var equal = cursorEqual(cursor, best); + var between = (motionArgs.forward) ? + cursorIsBetween(cursor, mark, best) : + cursorIsBetween(best, mark, cursor); + + if (equal || between) { + best = mark; + } + } + } + + if (motionArgs.linewise) { + // Vim places the cursor on the first non-whitespace character of + // the line if there is one, else it places the cursor at the end + // of the line, regardless of whether a mark was found. + best = Pos(best.line, findFirstNonWhiteSpaceCharacter(cm.getLine(best.line))); + } + return best; + }, + moveByCharacters: function(_cm, head, motionArgs) { + var cur = head; + var repeat = motionArgs.repeat; + var ch = motionArgs.forward ? cur.ch + repeat : cur.ch - repeat; + return Pos(cur.line, ch); + }, + moveByLines: function(cm, head, motionArgs, vim) { + var cur = head; + var endCh = cur.ch; + // Depending what our last motion was, we may want to do different + // things. If our last motion was moving vertically, we want to + // preserve the HPos from our last horizontal move. If our last motion + // was going to the end of a line, moving vertically we should go to + // the end of the line, etc. + switch (vim.lastMotion) { + case this.moveByLines: + case this.moveByDisplayLines: + case this.moveByScroll: + case this.moveToColumn: + case this.moveToEol: + endCh = vim.lastHPos; + break; + default: + vim.lastHPos = endCh; + } + var repeat = motionArgs.repeat+(motionArgs.repeatOffset||0); + var line = motionArgs.forward ? cur.line + repeat : cur.line - repeat; + var first = cm.firstLine(); + var last = cm.lastLine(); + // Vim go to line begin or line end when cursor at first/last line and + // move to previous/next line is triggered. + if (line < first && cur.line == first){ + return this.moveToStartOfLine(cm, head, motionArgs, vim); + }else if (line > last && cur.line == last){ + return this.moveToEol(cm, head, motionArgs, vim); + } + if (motionArgs.toFirstChar){ + endCh=findFirstNonWhiteSpaceCharacter(cm.getLine(line)); + vim.lastHPos = endCh; + } + vim.lastHSPos = cm.charCoords(Pos(line, endCh),'div').left; + return Pos(line, endCh); + }, + moveByDisplayLines: function(cm, head, motionArgs, vim) { + var cur = head; + switch (vim.lastMotion) { + case this.moveByDisplayLines: + case this.moveByScroll: + case this.moveByLines: + case this.moveToColumn: + case this.moveToEol: + break; + default: + vim.lastHSPos = cm.charCoords(cur,'div').left; + } + var repeat = motionArgs.repeat; + var res=cm.findPosV(cur,(motionArgs.forward ? repeat : -repeat),'line',vim.lastHSPos); + if (res.hitSide) { + if (motionArgs.forward) { + var lastCharCoords = cm.charCoords(res, 'div'); + var goalCoords = { top: lastCharCoords.top + 8, left: vim.lastHSPos }; + var res = cm.coordsChar(goalCoords, 'div'); + } else { + var resCoords = cm.charCoords(Pos(cm.firstLine(), 0), 'div'); + resCoords.left = vim.lastHSPos; + res = cm.coordsChar(resCoords, 'div'); + } + } + vim.lastHPos = res.ch; + return res; + }, + moveByPage: function(cm, head, motionArgs) { + // CodeMirror only exposes functions that move the cursor page down, so + // doing this bad hack to move the cursor and move it back. evalInput + // will move the cursor to where it should be in the end. + var curStart = head; + var repeat = motionArgs.repeat; + return cm.findPosV(curStart, (motionArgs.forward ? repeat : -repeat), 'page'); + }, + moveByParagraph: function(cm, head, motionArgs) { + var dir = motionArgs.forward ? 1 : -1; + return findParagraph(cm, head, motionArgs.repeat, dir); + }, + moveBySentence: function(cm, head, motionArgs) { + var dir = motionArgs.forward ? 1 : -1; + return findSentence(cm, head, motionArgs.repeat, dir); + }, + moveByScroll: function(cm, head, motionArgs, vim) { + var scrollbox = cm.getScrollInfo(); + var curEnd = null; + var repeat = motionArgs.repeat; + if (!repeat) { + repeat = scrollbox.clientHeight / (2 * cm.defaultTextHeight()); + } + var orig = cm.charCoords(head, 'local'); + motionArgs.repeat = repeat; + var curEnd = motions.moveByDisplayLines(cm, head, motionArgs, vim); + if (!curEnd) { + return null; + } + var dest = cm.charCoords(curEnd, 'local'); + cm.scrollTo(null, scrollbox.top + dest.top - orig.top); + return curEnd; + }, + moveByWords: function(cm, head, motionArgs) { + return moveToWord(cm, head, motionArgs.repeat, !!motionArgs.forward, + !!motionArgs.wordEnd, !!motionArgs.bigWord); + }, + moveTillCharacter: function(cm, _head, motionArgs) { + var repeat = motionArgs.repeat; + var curEnd = moveToCharacter(cm, repeat, motionArgs.forward, + motionArgs.selectedCharacter); + var increment = motionArgs.forward ? -1 : 1; + recordLastCharacterSearch(increment, motionArgs); + if (!curEnd) return null; + curEnd.ch += increment; + return curEnd; + }, + moveToCharacter: function(cm, head, motionArgs) { + var repeat = motionArgs.repeat; + recordLastCharacterSearch(0, motionArgs); + return moveToCharacter(cm, repeat, motionArgs.forward, + motionArgs.selectedCharacter) || head; + }, + moveToSymbol: function(cm, head, motionArgs) { + var repeat = motionArgs.repeat; + return findSymbol(cm, repeat, motionArgs.forward, + motionArgs.selectedCharacter) || head; + }, + moveToColumn: function(cm, head, motionArgs, vim) { + var repeat = motionArgs.repeat; + // repeat is equivalent to which column we want to move to! + vim.lastHPos = repeat - 1; + vim.lastHSPos = cm.charCoords(head,'div').left; + return moveToColumn(cm, repeat); + }, + moveToEol: function(cm, head, motionArgs, vim) { + var cur = head; + vim.lastHPos = Infinity; + var retval= Pos(cur.line + motionArgs.repeat - 1, Infinity); + var end=cm.clipPos(retval); + end.ch--; + vim.lastHSPos = cm.charCoords(end,'div').left; + return retval; + }, + moveToFirstNonWhiteSpaceCharacter: function(cm, head) { + // Go to the start of the line where the text begins, or the end for + // whitespace-only lines + var cursor = head; + return Pos(cursor.line, + findFirstNonWhiteSpaceCharacter(cm.getLine(cursor.line))); + }, + moveToMatchedSymbol: function(cm, head) { + var cursor = head; + var line = cursor.line; + var ch = cursor.ch; + var lineText = cm.getLine(line); + var symbol; + for (; ch < lineText.length; ch++) { + symbol = lineText.charAt(ch); + if (symbol && isMatchableSymbol(symbol)) { + var style = cm.getTokenTypeAt(Pos(line, ch + 1)); + if (style !== "string" && style !== "comment") { + break; + } + } + } + if (ch < lineText.length) { + var matched = cm.findMatchingBracket(Pos(line, ch)); + return matched.to; + } else { + return cursor; + } + }, + moveToStartOfLine: function(_cm, head) { + return Pos(head.line, 0); + }, + moveToLineOrEdgeOfDocument: function(cm, _head, motionArgs) { + var lineNum = motionArgs.forward ? cm.lastLine() : cm.firstLine(); + if (motionArgs.repeatIsExplicit) { + lineNum = motionArgs.repeat - cm.getOption('firstLineNumber'); + } + return Pos(lineNum, + findFirstNonWhiteSpaceCharacter(cm.getLine(lineNum))); + }, + textObjectManipulation: function(cm, head, motionArgs, vim) { + // TODO: lots of possible exceptions that can be thrown here. Try da( + // outside of a () block. + + // TODO: adding <> >< to this map doesn't work, presumably because + // they're operators + var mirroredPairs = {'(': ')', ')': '(', + '{': '}', '}': '{', + '[': ']', ']': '['}; + var selfPaired = {'\'': true, '"': true}; + + var character = motionArgs.selectedCharacter; + // 'b' refers to '()' block. + // 'B' refers to '{}' block. + if (character == 'b') { + character = '('; + } else if (character == 'B') { + character = '{'; + } + + // Inclusive is the difference between a and i + // TODO: Instead of using the additional text object map to perform text + // object operations, merge the map into the defaultKeyMap and use + // motionArgs to define behavior. Define separate entries for 'aw', + // 'iw', 'a[', 'i[', etc. + var inclusive = !motionArgs.textObjectInner; + + var tmp; + if (mirroredPairs[character]) { + tmp = selectCompanionObject(cm, head, character, inclusive); + } else if (selfPaired[character]) { + tmp = findBeginningAndEnd(cm, head, character, inclusive); + } else if (character === 'W') { + tmp = expandWordUnderCursor(cm, inclusive, true /** forward */, + true /** bigWord */); + } else if (character === 'w') { + tmp = expandWordUnderCursor(cm, inclusive, true /** forward */, + false /** bigWord */); + } else if (character === 'p') { + tmp = findParagraph(cm, head, motionArgs.repeat, 0, inclusive); + motionArgs.linewise = true; + if (vim.visualMode) { + if (!vim.visualLine) { vim.visualLine = true; } + } else { + var operatorArgs = vim.inputState.operatorArgs; + if (operatorArgs) { operatorArgs.linewise = true; } + tmp.end.line--; + } + } else { + // No text object defined for this, don't move. + return null; + } + + if (!cm.state.vim.visualMode) { + return [tmp.start, tmp.end]; + } else { + return expandSelection(cm, tmp.start, tmp.end); + } + }, + + repeatLastCharacterSearch: function(cm, head, motionArgs) { + var lastSearch = vimGlobalState.lastCharacterSearch; + var repeat = motionArgs.repeat; + var forward = motionArgs.forward === lastSearch.forward; + var increment = (lastSearch.increment ? 1 : 0) * (forward ? -1 : 1); + cm.moveH(-increment, 'char'); + motionArgs.inclusive = forward ? true : false; + var curEnd = moveToCharacter(cm, repeat, forward, lastSearch.selectedCharacter); + if (!curEnd) { + cm.moveH(increment, 'char'); + return head; + } + curEnd.ch += increment; + return curEnd; + } + }; + + function defineMotion(name, fn) { + motions[name] = fn; + } + + function fillArray(val, times) { + var arr = []; + for (var i = 0; i < times; i++) { + arr.push(val); + } + return arr; + } + /** + * An operator acts on a text selection. It receives the list of selections + * as input. The corresponding CodeMirror selection is guaranteed to + * match the input selection. + */ + var operators = { + change: function(cm, args, ranges) { + var finalHead, text; + var vim = cm.state.vim; + vimGlobalState.macroModeState.lastInsertModeChanges.inVisualBlock = vim.visualBlock; + if (!vim.visualMode) { + var anchor = ranges[0].anchor, + head = ranges[0].head; + text = cm.getRange(anchor, head); + var lastState = vim.lastEditInputState || {}; + if (lastState.motion == "moveByWords" && !isWhiteSpaceString(text)) { + // Exclude trailing whitespace if the range is not all whitespace. + var match = (/\s+$/).exec(text); + if (match && lastState.motionArgs && lastState.motionArgs.forward) { + head = offsetCursor(head, 0, - match[0].length); + text = text.slice(0, - match[0].length); + } + } + var prevLineEnd = new Pos(anchor.line - 1, Number.MAX_VALUE); + var wasLastLine = cm.firstLine() == cm.lastLine(); + if (head.line > cm.lastLine() && args.linewise && !wasLastLine) { + cm.replaceRange('', prevLineEnd, head); + } else { + cm.replaceRange('', anchor, head); + } + if (args.linewise) { + // Push the next line back down, if there is a next line. + if (!wasLastLine) { + cm.setCursor(prevLineEnd); + CodeMirror.commands.newlineAndIndent(cm); + } + // make sure cursor ends up at the end of the line. + anchor.ch = Number.MAX_VALUE; + } + finalHead = anchor; + } else { + text = cm.getSelection(); + var replacement = fillArray('', ranges.length); + cm.replaceSelections(replacement); + finalHead = cursorMin(ranges[0].head, ranges[0].anchor); + } + vimGlobalState.registerController.pushText( + args.registerName, 'change', text, + args.linewise, ranges.length > 1); + actions.enterInsertMode(cm, {head: finalHead}, cm.state.vim); + }, + // delete is a javascript keyword. + 'delete': function(cm, args, ranges) { + var finalHead, text; + var vim = cm.state.vim; + if (!vim.visualBlock) { + var anchor = ranges[0].anchor, + head = ranges[0].head; + if (args.linewise && + head.line != cm.firstLine() && + anchor.line == cm.lastLine() && + anchor.line == head.line - 1) { + // Special case for dd on last line (and first line). + if (anchor.line == cm.firstLine()) { + anchor.ch = 0; + } else { + anchor = Pos(anchor.line - 1, lineLength(cm, anchor.line - 1)); + } + } + text = cm.getRange(anchor, head); + cm.replaceRange('', anchor, head); + finalHead = anchor; + if (args.linewise) { + finalHead = motions.moveToFirstNonWhiteSpaceCharacter(cm, anchor); + } + } else { + text = cm.getSelection(); + var replacement = fillArray('', ranges.length); + cm.replaceSelections(replacement); + finalHead = ranges[0].anchor; + } + vimGlobalState.registerController.pushText( + args.registerName, 'delete', text, + args.linewise, vim.visualBlock); + var includeLineBreak = vim.insertMode + return clipCursorToContent(cm, finalHead, includeLineBreak); + }, + indent: function(cm, args, ranges) { + var vim = cm.state.vim; + var startLine = ranges[0].anchor.line; + var endLine = vim.visualBlock ? + ranges[ranges.length - 1].anchor.line : + ranges[0].head.line; + // In visual mode, n> shifts the selection right n times, instead of + // shifting n lines right once. + var repeat = (vim.visualMode) ? args.repeat : 1; + if (args.linewise) { + // The only way to delete a newline is to delete until the start of + // the next line, so in linewise mode evalInput will include the next + // line. We don't want this in indent, so we go back a line. + endLine--; + } + for (var i = startLine; i <= endLine; i++) { + for (var j = 0; j < repeat; j++) { + cm.indentLine(i, args.indentRight); + } + } + return motions.moveToFirstNonWhiteSpaceCharacter(cm, ranges[0].anchor); + }, + changeCase: function(cm, args, ranges, oldAnchor, newHead) { + var selections = cm.getSelections(); + var swapped = []; + var toLower = args.toLower; + for (var j = 0; j < selections.length; j++) { + var toSwap = selections[j]; + var text = ''; + if (toLower === true) { + text = toSwap.toLowerCase(); + } else if (toLower === false) { + text = toSwap.toUpperCase(); + } else { + for (var i = 0; i < toSwap.length; i++) { + var character = toSwap.charAt(i); + text += isUpperCase(character) ? character.toLowerCase() : + character.toUpperCase(); + } + } + swapped.push(text); + } + cm.replaceSelections(swapped); + if (args.shouldMoveCursor){ + return newHead; + } else if (!cm.state.vim.visualMode && args.linewise && ranges[0].anchor.line + 1 == ranges[0].head.line) { + return motions.moveToFirstNonWhiteSpaceCharacter(cm, oldAnchor); + } else if (args.linewise){ + return oldAnchor; + } else { + return cursorMin(ranges[0].anchor, ranges[0].head); + } + }, + yank: function(cm, args, ranges, oldAnchor) { + var vim = cm.state.vim; + var text = cm.getSelection(); + var endPos = vim.visualMode + ? cursorMin(vim.sel.anchor, vim.sel.head, ranges[0].head, ranges[0].anchor) + : oldAnchor; + vimGlobalState.registerController.pushText( + args.registerName, 'yank', + text, args.linewise, vim.visualBlock); + return endPos; + } + }; + + function defineOperator(name, fn) { + operators[name] = fn; + } + + var actions = { + jumpListWalk: function(cm, actionArgs, vim) { + if (vim.visualMode) { + return; + } + var repeat = actionArgs.repeat; + var forward = actionArgs.forward; + var jumpList = vimGlobalState.jumpList; + + var mark = jumpList.move(cm, forward ? repeat : -repeat); + var markPos = mark ? mark.find() : undefined; + markPos = markPos ? markPos : cm.getCursor(); + cm.setCursor(markPos); + }, + scroll: function(cm, actionArgs, vim) { + if (vim.visualMode) { + return; + } + var repeat = actionArgs.repeat || 1; + var lineHeight = cm.defaultTextHeight(); + var top = cm.getScrollInfo().top; + var delta = lineHeight * repeat; + var newPos = actionArgs.forward ? top + delta : top - delta; + var cursor = copyCursor(cm.getCursor()); + var cursorCoords = cm.charCoords(cursor, 'local'); + if (actionArgs.forward) { + if (newPos > cursorCoords.top) { + cursor.line += (newPos - cursorCoords.top) / lineHeight; + cursor.line = Math.ceil(cursor.line); + cm.setCursor(cursor); + cursorCoords = cm.charCoords(cursor, 'local'); + cm.scrollTo(null, cursorCoords.top); + } else { + // Cursor stays within bounds. Just reposition the scroll window. + cm.scrollTo(null, newPos); + } + } else { + var newBottom = newPos + cm.getScrollInfo().clientHeight; + if (newBottom < cursorCoords.bottom) { + cursor.line -= (cursorCoords.bottom - newBottom) / lineHeight; + cursor.line = Math.floor(cursor.line); + cm.setCursor(cursor); + cursorCoords = cm.charCoords(cursor, 'local'); + cm.scrollTo( + null, cursorCoords.bottom - cm.getScrollInfo().clientHeight); + } else { + // Cursor stays within bounds. Just reposition the scroll window. + cm.scrollTo(null, newPos); + } + } + }, + scrollToCursor: function(cm, actionArgs) { + var lineNum = cm.getCursor().line; + var charCoords = cm.charCoords(Pos(lineNum, 0), 'local'); + var height = cm.getScrollInfo().clientHeight; + var y = charCoords.top; + var lineHeight = charCoords.bottom - y; + switch (actionArgs.position) { + case 'center': y = y - (height / 2) + lineHeight; + break; + case 'bottom': y = y - height + lineHeight; + break; + } + cm.scrollTo(null, y); + }, + replayMacro: function(cm, actionArgs, vim) { + var registerName = actionArgs.selectedCharacter; + var repeat = actionArgs.repeat; + var macroModeState = vimGlobalState.macroModeState; + if (registerName == '@') { + registerName = macroModeState.latestRegister; + } + while(repeat--){ + executeMacroRegister(cm, vim, macroModeState, registerName); + } + }, + enterMacroRecordMode: function(cm, actionArgs) { + var macroModeState = vimGlobalState.macroModeState; + var registerName = actionArgs.selectedCharacter; + if (vimGlobalState.registerController.isValidRegister(registerName)) { + macroModeState.enterMacroRecordMode(cm, registerName); + } + }, + toggleOverwrite: function(cm) { + if (!cm.state.overwrite) { + cm.toggleOverwrite(true); + cm.setOption('keyMap', 'vim-replace'); + CodeMirror.signal(cm, "vim-mode-change", {mode: "replace"}); + } else { + cm.toggleOverwrite(false); + cm.setOption('keyMap', 'vim-insert'); + CodeMirror.signal(cm, "vim-mode-change", {mode: "insert"}); + } + }, + enterInsertMode: function(cm, actionArgs, vim) { + if (cm.getOption('readOnly')) { return; } + vim.insertMode = true; + vim.insertModeRepeat = actionArgs && actionArgs.repeat || 1; + var insertAt = (actionArgs) ? actionArgs.insertAt : null; + var sel = vim.sel; + var head = actionArgs.head || cm.getCursor('head'); + var height = cm.listSelections().length; + if (insertAt == 'eol') { + head = Pos(head.line, lineLength(cm, head.line)); + } else if (insertAt == 'charAfter') { + head = offsetCursor(head, 0, 1); + } else if (insertAt == 'firstNonBlank') { + head = motions.moveToFirstNonWhiteSpaceCharacter(cm, head); + } else if (insertAt == 'startOfSelectedArea') { + if (!vim.visualBlock) { + if (sel.head.line < sel.anchor.line) { + head = sel.head; + } else { + head = Pos(sel.anchor.line, 0); + } + } else { + head = Pos( + Math.min(sel.head.line, sel.anchor.line), + Math.min(sel.head.ch, sel.anchor.ch)); + height = Math.abs(sel.head.line - sel.anchor.line) + 1; + } + } else if (insertAt == 'endOfSelectedArea') { + if (!vim.visualBlock) { + if (sel.head.line >= sel.anchor.line) { + head = offsetCursor(sel.head, 0, 1); + } else { + head = Pos(sel.anchor.line, 0); + } + } else { + head = Pos( + Math.min(sel.head.line, sel.anchor.line), + Math.max(sel.head.ch + 1, sel.anchor.ch)); + height = Math.abs(sel.head.line - sel.anchor.line) + 1; + } + } else if (insertAt == 'inplace') { + if (vim.visualMode){ + return; + } + } + cm.setOption('disableInput', false); + if (actionArgs && actionArgs.replace) { + // Handle Replace-mode as a special case of insert mode. + cm.toggleOverwrite(true); + cm.setOption('keyMap', 'vim-replace'); + CodeMirror.signal(cm, "vim-mode-change", {mode: "replace"}); + } else { + cm.toggleOverwrite(false); + cm.setOption('keyMap', 'vim-insert'); + CodeMirror.signal(cm, "vim-mode-change", {mode: "insert"}); + } + if (!vimGlobalState.macroModeState.isPlaying) { + // Only record if not replaying. + cm.on('change', onChange); + CodeMirror.on(cm.getInputField(), 'keydown', onKeyEventTargetKeyDown); + } + if (vim.visualMode) { + exitVisualMode(cm); + } + selectForInsert(cm, head, height); + }, + toggleVisualMode: function(cm, actionArgs, vim) { + var repeat = actionArgs.repeat; + var anchor = cm.getCursor(); + var head; + // TODO: The repeat should actually select number of characters/lines + // equal to the repeat times the size of the previous visual + // operation. + if (!vim.visualMode) { + // Entering visual mode + vim.visualMode = true; + vim.visualLine = !!actionArgs.linewise; + vim.visualBlock = !!actionArgs.blockwise; + head = clipCursorToContent( + cm, Pos(anchor.line, anchor.ch + repeat - 1), + true /** includeLineBreak */); + vim.sel = { + anchor: anchor, + head: head + }; + CodeMirror.signal(cm, "vim-mode-change", {mode: "visual", subMode: vim.visualLine ? "linewise" : vim.visualBlock ? "blockwise" : ""}); + updateCmSelection(cm); + updateMark(cm, vim, '<', cursorMin(anchor, head)); + updateMark(cm, vim, '>', cursorMax(anchor, head)); + } else if (vim.visualLine ^ actionArgs.linewise || + vim.visualBlock ^ actionArgs.blockwise) { + // Toggling between modes + vim.visualLine = !!actionArgs.linewise; + vim.visualBlock = !!actionArgs.blockwise; + CodeMirror.signal(cm, "vim-mode-change", {mode: "visual", subMode: vim.visualLine ? "linewise" : vim.visualBlock ? "blockwise" : ""}); + updateCmSelection(cm); + } else { + exitVisualMode(cm); + } + }, + reselectLastSelection: function(cm, _actionArgs, vim) { + var lastSelection = vim.lastSelection; + if (vim.visualMode) { + updateLastSelection(cm, vim); + } + if (lastSelection) { + var anchor = lastSelection.anchorMark.find(); + var head = lastSelection.headMark.find(); + if (!anchor || !head) { + // If the marks have been destroyed due to edits, do nothing. + return; + } + vim.sel = { + anchor: anchor, + head: head + }; + vim.visualMode = true; + vim.visualLine = lastSelection.visualLine; + vim.visualBlock = lastSelection.visualBlock; + updateCmSelection(cm); + updateMark(cm, vim, '<', cursorMin(anchor, head)); + updateMark(cm, vim, '>', cursorMax(anchor, head)); + CodeMirror.signal(cm, 'vim-mode-change', { + mode: 'visual', + subMode: vim.visualLine ? 'linewise' : + vim.visualBlock ? 'blockwise' : ''}); + } + }, + joinLines: function(cm, actionArgs, vim) { + var curStart, curEnd; + if (vim.visualMode) { + curStart = cm.getCursor('anchor'); + curEnd = cm.getCursor('head'); + if (cursorIsBefore(curEnd, curStart)) { + var tmp = curEnd; + curEnd = curStart; + curStart = tmp; + } + curEnd.ch = lineLength(cm, curEnd.line) - 1; + } else { + // Repeat is the number of lines to join. Minimum 2 lines. + var repeat = Math.max(actionArgs.repeat, 2); + curStart = cm.getCursor(); + curEnd = clipCursorToContent(cm, Pos(curStart.line + repeat - 1, + Infinity)); + } + var finalCh = 0; + for (var i = curStart.line; i < curEnd.line; i++) { + finalCh = lineLength(cm, curStart.line); + var tmp = Pos(curStart.line + 1, + lineLength(cm, curStart.line + 1)); + var text = cm.getRange(curStart, tmp); + text = text.replace(/\n\s*/g, ' '); + cm.replaceRange(text, curStart, tmp); + } + var curFinalPos = Pos(curStart.line, finalCh); + if (vim.visualMode) { + exitVisualMode(cm, false); + } + cm.setCursor(curFinalPos); + }, + newLineAndEnterInsertMode: function(cm, actionArgs, vim) { + vim.insertMode = true; + var insertAt = copyCursor(cm.getCursor()); + if (insertAt.line === cm.firstLine() && !actionArgs.after) { + // Special case for inserting newline before start of document. + cm.replaceRange('\n', Pos(cm.firstLine(), 0)); + cm.setCursor(cm.firstLine(), 0); + } else { + insertAt.line = (actionArgs.after) ? insertAt.line : + insertAt.line - 1; + insertAt.ch = lineLength(cm, insertAt.line); + cm.setCursor(insertAt); + var newlineFn = CodeMirror.commands.newlineAndIndentContinueComment || + CodeMirror.commands.newlineAndIndent; + newlineFn(cm); + } + this.enterInsertMode(cm, { repeat: actionArgs.repeat }, vim); + }, + paste: function(cm, actionArgs, vim) { + var cur = copyCursor(cm.getCursor()); + var register = vimGlobalState.registerController.getRegister( + actionArgs.registerName); + var text = register.toString(); + if (!text) { + return; + } + if (actionArgs.matchIndent) { + var tabSize = cm.getOption("tabSize"); + // length that considers tabs and tabSize + var whitespaceLength = function(str) { + var tabs = (str.split("\t").length - 1); + var spaces = (str.split(" ").length - 1); + return tabs * tabSize + spaces * 1; + }; + var currentLine = cm.getLine(cm.getCursor().line); + var indent = whitespaceLength(currentLine.match(/^\s*/)[0]); + // chomp last newline b/c don't want it to match /^\s*/gm + var chompedText = text.replace(/\n$/, ''); + var wasChomped = text !== chompedText; + var firstIndent = whitespaceLength(text.match(/^\s*/)[0]); + var text = chompedText.replace(/^\s*/gm, function(wspace) { + var newIndent = indent + (whitespaceLength(wspace) - firstIndent); + if (newIndent < 0) { + return ""; + } + else if (cm.getOption("indentWithTabs")) { + var quotient = Math.floor(newIndent / tabSize); + return Array(quotient + 1).join('\t'); + } + else { + return Array(newIndent + 1).join(' '); + } + }); + text += wasChomped ? "\n" : ""; + } + if (actionArgs.repeat > 1) { + var text = Array(actionArgs.repeat + 1).join(text); + } + var linewise = register.linewise; + var blockwise = register.blockwise; + if (linewise) { + if(vim.visualMode) { + text = vim.visualLine ? text.slice(0, -1) : '\n' + text.slice(0, text.length - 1) + '\n'; + } else if (actionArgs.after) { + // Move the newline at the end to the start instead, and paste just + // before the newline character of the line we are on right now. + text = '\n' + text.slice(0, text.length - 1); + cur.ch = lineLength(cm, cur.line); + } else { + cur.ch = 0; + } + } else { + if (blockwise) { + text = text.split('\n'); + for (var i = 0; i < text.length; i++) { + text[i] = (text[i] == '') ? ' ' : text[i]; + } + } + cur.ch += actionArgs.after ? 1 : 0; + } + var curPosFinal; + var idx; + if (vim.visualMode) { + // save the pasted text for reselection if the need arises + vim.lastPastedText = text; + var lastSelectionCurEnd; + var selectedArea = getSelectedAreaRange(cm, vim); + var selectionStart = selectedArea[0]; + var selectionEnd = selectedArea[1]; + var selectedText = cm.getSelection(); + var selections = cm.listSelections(); + var emptyStrings = new Array(selections.length).join('1').split('1'); + // save the curEnd marker before it get cleared due to cm.replaceRange. + if (vim.lastSelection) { + lastSelectionCurEnd = vim.lastSelection.headMark.find(); + } + // push the previously selected text to unnamed register + vimGlobalState.registerController.unnamedRegister.setText(selectedText); + if (blockwise) { + // first delete the selected text + cm.replaceSelections(emptyStrings); + // Set new selections as per the block length of the yanked text + selectionEnd = Pos(selectionStart.line + text.length-1, selectionStart.ch); + cm.setCursor(selectionStart); + selectBlock(cm, selectionEnd); + cm.replaceSelections(text); + curPosFinal = selectionStart; + } else if (vim.visualBlock) { + cm.replaceSelections(emptyStrings); + cm.setCursor(selectionStart); + cm.replaceRange(text, selectionStart, selectionStart); + curPosFinal = selectionStart; + } else { + cm.replaceRange(text, selectionStart, selectionEnd); + curPosFinal = cm.posFromIndex(cm.indexFromPos(selectionStart) + text.length - 1); + } + // restore the the curEnd marker + if(lastSelectionCurEnd) { + vim.lastSelection.headMark = cm.setBookmark(lastSelectionCurEnd); + } + if (linewise) { + curPosFinal.ch=0; + } + } else { + if (blockwise) { + cm.setCursor(cur); + for (var i = 0; i < text.length; i++) { + var line = cur.line+i; + if (line > cm.lastLine()) { + cm.replaceRange('\n', Pos(line, 0)); + } + var lastCh = lineLength(cm, line); + if (lastCh < cur.ch) { + extendLineToColumn(cm, line, cur.ch); + } + } + cm.setCursor(cur); + selectBlock(cm, Pos(cur.line + text.length-1, cur.ch)); + cm.replaceSelections(text); + curPosFinal = cur; + } else { + cm.replaceRange(text, cur); + // Now fine tune the cursor to where we want it. + if (linewise && actionArgs.after) { + curPosFinal = Pos( + cur.line + 1, + findFirstNonWhiteSpaceCharacter(cm.getLine(cur.line + 1))); + } else if (linewise && !actionArgs.after) { + curPosFinal = Pos( + cur.line, + findFirstNonWhiteSpaceCharacter(cm.getLine(cur.line))); + } else if (!linewise && actionArgs.after) { + idx = cm.indexFromPos(cur); + curPosFinal = cm.posFromIndex(idx + text.length - 1); + } else { + idx = cm.indexFromPos(cur); + curPosFinal = cm.posFromIndex(idx + text.length); + } + } + } + if (vim.visualMode) { + exitVisualMode(cm, false); + } + cm.setCursor(curPosFinal); + }, + undo: function(cm, actionArgs) { + cm.operation(function() { + repeatFn(cm, CodeMirror.commands.undo, actionArgs.repeat)(); + cm.setCursor(cm.getCursor('anchor')); + }); + }, + redo: function(cm, actionArgs) { + repeatFn(cm, CodeMirror.commands.redo, actionArgs.repeat)(); + }, + setRegister: function(_cm, actionArgs, vim) { + vim.inputState.registerName = actionArgs.selectedCharacter; + }, + setMark: function(cm, actionArgs, vim) { + var markName = actionArgs.selectedCharacter; + updateMark(cm, vim, markName, cm.getCursor()); + }, + replace: function(cm, actionArgs, vim) { + var replaceWith = actionArgs.selectedCharacter; + var curStart = cm.getCursor(); + var replaceTo; + var curEnd; + var selections = cm.listSelections(); + if (vim.visualMode) { + curStart = cm.getCursor('start'); + curEnd = cm.getCursor('end'); + } else { + var line = cm.getLine(curStart.line); + replaceTo = curStart.ch + actionArgs.repeat; + if (replaceTo > line.length) { + replaceTo=line.length; + } + curEnd = Pos(curStart.line, replaceTo); + } + if (replaceWith=='\n') { + if (!vim.visualMode) cm.replaceRange('', curStart, curEnd); + // special case, where vim help says to replace by just one line-break + (CodeMirror.commands.newlineAndIndentContinueComment || CodeMirror.commands.newlineAndIndent)(cm); + } else { + var replaceWithStr = cm.getRange(curStart, curEnd); + //replace all characters in range by selected, but keep linebreaks + replaceWithStr = replaceWithStr.replace(/[^\n]/g, replaceWith); + if (vim.visualBlock) { + // Tabs are split in visua block before replacing + var spaces = new Array(cm.getOption("tabSize")+1).join(' '); + replaceWithStr = cm.getSelection(); + replaceWithStr = replaceWithStr.replace(/\t/g, spaces).replace(/[^\n]/g, replaceWith).split('\n'); + cm.replaceSelections(replaceWithStr); + } else { + cm.replaceRange(replaceWithStr, curStart, curEnd); + } + if (vim.visualMode) { + curStart = cursorIsBefore(selections[0].anchor, selections[0].head) ? + selections[0].anchor : selections[0].head; + cm.setCursor(curStart); + exitVisualMode(cm, false); + } else { + cm.setCursor(offsetCursor(curEnd, 0, -1)); + } + } + }, + incrementNumberToken: function(cm, actionArgs) { + var cur = cm.getCursor(); + var lineStr = cm.getLine(cur.line); + var re = /(-?)(?:(0x)([\da-f]+)|(0b|0|)(\d+))/gi; + var match; + var start; + var end; + var numberStr; + while ((match = re.exec(lineStr)) !== null) { + start = match.index; + end = start + match[0].length; + if (cur.ch < end)break; + } + if (!actionArgs.backtrack && (end <= cur.ch))return; + if (match) { + var baseStr = match[2] || match[4] + var digits = match[3] || match[5] + var increment = actionArgs.increase ? 1 : -1; + var base = {'0b': 2, '0': 8, '': 10, '0x': 16}[baseStr.toLowerCase()]; + var number = parseInt(match[1] + digits, base) + (increment * actionArgs.repeat); + numberStr = number.toString(base); + var zeroPadding = baseStr ? new Array(digits.length - numberStr.length + 1 + match[1].length).join('0') : '' + if (numberStr.charAt(0) === '-') { + numberStr = '-' + baseStr + zeroPadding + numberStr.substr(1); + } else { + numberStr = baseStr + zeroPadding + numberStr; + } + var from = Pos(cur.line, start); + var to = Pos(cur.line, end); + cm.replaceRange(numberStr, from, to); + } else { + return; + } + cm.setCursor(Pos(cur.line, start + numberStr.length - 1)); + }, + repeatLastEdit: function(cm, actionArgs, vim) { + var lastEditInputState = vim.lastEditInputState; + if (!lastEditInputState) { return; } + var repeat = actionArgs.repeat; + if (repeat && actionArgs.repeatIsExplicit) { + vim.lastEditInputState.repeatOverride = repeat; + } else { + repeat = vim.lastEditInputState.repeatOverride || repeat; + } + repeatLastEdit(cm, vim, repeat, false /** repeatForInsert */); + }, + indent: function(cm, actionArgs) { + cm.indentLine(cm.getCursor().line, actionArgs.indentRight); + }, + exitInsertMode: exitInsertMode + }; + + function defineAction(name, fn) { + actions[name] = fn; + } + + /* + * Below are miscellaneous utility functions used by vim.js + */ + + /** + * Clips cursor to ensure that line is within the buffer's range + * If includeLineBreak is true, then allow cur.ch == lineLength. + */ + function clipCursorToContent(cm, cur, includeLineBreak) { + var line = Math.min(Math.max(cm.firstLine(), cur.line), cm.lastLine() ); + var maxCh = lineLength(cm, line) - 1; + maxCh = (includeLineBreak) ? maxCh + 1 : maxCh; + var ch = Math.min(Math.max(0, cur.ch), maxCh); + return Pos(line, ch); + } + function copyArgs(args) { + var ret = {}; + for (var prop in args) { + if (args.hasOwnProperty(prop)) { + ret[prop] = args[prop]; + } + } + return ret; + } + function offsetCursor(cur, offsetLine, offsetCh) { + if (typeof offsetLine === 'object') { + offsetCh = offsetLine.ch; + offsetLine = offsetLine.line; + } + return Pos(cur.line + offsetLine, cur.ch + offsetCh); + } + function getOffset(anchor, head) { + return { + line: head.line - anchor.line, + ch: head.line - anchor.line + }; + } + function commandMatches(keys, keyMap, context, inputState) { + // Partial matches are not applied. They inform the key handler + // that the current key sequence is a subsequence of a valid key + // sequence, so that the key buffer is not cleared. + var match, partial = [], full = []; + for (var i = 0; i < keyMap.length; i++) { + var command = keyMap[i]; + if (context == 'insert' && command.context != 'insert' || + command.context && command.context != context || + inputState.operator && command.type == 'action' || + !(match = commandMatch(keys, command.keys))) { continue; } + if (match == 'partial') { partial.push(command); } + if (match == 'full') { full.push(command); } + } + return { + partial: partial.length && partial, + full: full.length && full + }; + } + function commandMatch(pressed, mapped) { + if (mapped.slice(-11) == '') { + // Last character matches anything. + var prefixLen = mapped.length - 11; + var pressedPrefix = pressed.slice(0, prefixLen); + var mappedPrefix = mapped.slice(0, prefixLen); + return pressedPrefix == mappedPrefix && pressed.length > prefixLen ? 'full' : + mappedPrefix.indexOf(pressedPrefix) == 0 ? 'partial' : false; + } else { + return pressed == mapped ? 'full' : + mapped.indexOf(pressed) == 0 ? 'partial' : false; + } + } + function lastChar(keys) { + var match = /^.*(<[^>]+>)$/.exec(keys); + var selectedCharacter = match ? match[1] : keys.slice(-1); + if (selectedCharacter.length > 1){ + switch(selectedCharacter){ + case '': + selectedCharacter='\n'; + break; + case '': + selectedCharacter=' '; + break; + default: + selectedCharacter=''; + break; + } + } + return selectedCharacter; + } + function repeatFn(cm, fn, repeat) { + return function() { + for (var i = 0; i < repeat; i++) { + fn(cm); + } + }; + } + function copyCursor(cur) { + return Pos(cur.line, cur.ch); + } + function cursorEqual(cur1, cur2) { + return cur1.ch == cur2.ch && cur1.line == cur2.line; + } + function cursorIsBefore(cur1, cur2) { + if (cur1.line < cur2.line) { + return true; + } + if (cur1.line == cur2.line && cur1.ch < cur2.ch) { + return true; + } + return false; + } + function cursorMin(cur1, cur2) { + if (arguments.length > 2) { + cur2 = cursorMin.apply(undefined, Array.prototype.slice.call(arguments, 1)); + } + return cursorIsBefore(cur1, cur2) ? cur1 : cur2; + } + function cursorMax(cur1, cur2) { + if (arguments.length > 2) { + cur2 = cursorMax.apply(undefined, Array.prototype.slice.call(arguments, 1)); + } + return cursorIsBefore(cur1, cur2) ? cur2 : cur1; + } + function cursorIsBetween(cur1, cur2, cur3) { + // returns true if cur2 is between cur1 and cur3. + var cur1before2 = cursorIsBefore(cur1, cur2); + var cur2before3 = cursorIsBefore(cur2, cur3); + return cur1before2 && cur2before3; + } + function lineLength(cm, lineNum) { + return cm.getLine(lineNum).length; + } + function trim(s) { + if (s.trim) { + return s.trim(); + } + return s.replace(/^\s+|\s+$/g, ''); + } + function escapeRegex(s) { + return s.replace(/([.?*+$\[\]\/\\(){}|\-])/g, '\\$1'); + } + function extendLineToColumn(cm, lineNum, column) { + var endCh = lineLength(cm, lineNum); + var spaces = new Array(column-endCh+1).join(' '); + cm.setCursor(Pos(lineNum, endCh)); + cm.replaceRange(spaces, cm.getCursor()); + } + // This functions selects a rectangular block + // of text with selectionEnd as any of its corner + // Height of block: + // Difference in selectionEnd.line and first/last selection.line + // Width of the block: + // Distance between selectionEnd.ch and any(first considered here) selection.ch + function selectBlock(cm, selectionEnd) { + var selections = [], ranges = cm.listSelections(); + var head = copyCursor(cm.clipPos(selectionEnd)); + var isClipped = !cursorEqual(selectionEnd, head); + var curHead = cm.getCursor('head'); + var primIndex = getIndex(ranges, curHead); + var wasClipped = cursorEqual(ranges[primIndex].head, ranges[primIndex].anchor); + var max = ranges.length - 1; + var index = max - primIndex > primIndex ? max : 0; + var base = ranges[index].anchor; + + var firstLine = Math.min(base.line, head.line); + var lastLine = Math.max(base.line, head.line); + var baseCh = base.ch, headCh = head.ch; + + var dir = ranges[index].head.ch - baseCh; + var newDir = headCh - baseCh; + if (dir > 0 && newDir <= 0) { + baseCh++; + if (!isClipped) { headCh--; } + } else if (dir < 0 && newDir >= 0) { + baseCh--; + if (!wasClipped) { headCh++; } + } else if (dir < 0 && newDir == -1) { + baseCh--; + headCh++; + } + for (var line = firstLine; line <= lastLine; line++) { + var range = {anchor: new Pos(line, baseCh), head: new Pos(line, headCh)}; + selections.push(range); + } + cm.setSelections(selections); + selectionEnd.ch = headCh; + base.ch = baseCh; + return base; + } + function selectForInsert(cm, head, height) { + var sel = []; + for (var i = 0; i < height; i++) { + var lineHead = offsetCursor(head, i, 0); + sel.push({anchor: lineHead, head: lineHead}); + } + cm.setSelections(sel, 0); + } + // getIndex returns the index of the cursor in the selections. + function getIndex(ranges, cursor, end) { + for (var i = 0; i < ranges.length; i++) { + var atAnchor = end != 'head' && cursorEqual(ranges[i].anchor, cursor); + var atHead = end != 'anchor' && cursorEqual(ranges[i].head, cursor); + if (atAnchor || atHead) { + return i; + } + } + return -1; + } + function getSelectedAreaRange(cm, vim) { + var lastSelection = vim.lastSelection; + var getCurrentSelectedAreaRange = function() { + var selections = cm.listSelections(); + var start = selections[0]; + var end = selections[selections.length-1]; + var selectionStart = cursorIsBefore(start.anchor, start.head) ? start.anchor : start.head; + var selectionEnd = cursorIsBefore(end.anchor, end.head) ? end.head : end.anchor; + return [selectionStart, selectionEnd]; + }; + var getLastSelectedAreaRange = function() { + var selectionStart = cm.getCursor(); + var selectionEnd = cm.getCursor(); + var block = lastSelection.visualBlock; + if (block) { + var width = block.width; + var height = block.height; + selectionEnd = Pos(selectionStart.line + height, selectionStart.ch + width); + var selections = []; + // selectBlock creates a 'proper' rectangular block. + // We do not want that in all cases, so we manually set selections. + for (var i = selectionStart.line; i < selectionEnd.line; i++) { + var anchor = Pos(i, selectionStart.ch); + var head = Pos(i, selectionEnd.ch); + var range = {anchor: anchor, head: head}; + selections.push(range); + } + cm.setSelections(selections); + } else { + var start = lastSelection.anchorMark.find(); + var end = lastSelection.headMark.find(); + var line = end.line - start.line; + var ch = end.ch - start.ch; + selectionEnd = {line: selectionEnd.line + line, ch: line ? selectionEnd.ch : ch + selectionEnd.ch}; + if (lastSelection.visualLine) { + selectionStart = Pos(selectionStart.line, 0); + selectionEnd = Pos(selectionEnd.line, lineLength(cm, selectionEnd.line)); + } + cm.setSelection(selectionStart, selectionEnd); + } + return [selectionStart, selectionEnd]; + }; + if (!vim.visualMode) { + // In case of replaying the action. + return getLastSelectedAreaRange(); + } else { + return getCurrentSelectedAreaRange(); + } + } + // Updates the previous selection with the current selection's values. This + // should only be called in visual mode. + function updateLastSelection(cm, vim) { + var anchor = vim.sel.anchor; + var head = vim.sel.head; + // To accommodate the effect of lastPastedText in the last selection + if (vim.lastPastedText) { + head = cm.posFromIndex(cm.indexFromPos(anchor) + vim.lastPastedText.length); + vim.lastPastedText = null; + } + vim.lastSelection = {'anchorMark': cm.setBookmark(anchor), + 'headMark': cm.setBookmark(head), + 'anchor': copyCursor(anchor), + 'head': copyCursor(head), + 'visualMode': vim.visualMode, + 'visualLine': vim.visualLine, + 'visualBlock': vim.visualBlock}; + } + function expandSelection(cm, start, end) { + var sel = cm.state.vim.sel; + var head = sel.head; + var anchor = sel.anchor; + var tmp; + if (cursorIsBefore(end, start)) { + tmp = end; + end = start; + start = tmp; + } + if (cursorIsBefore(head, anchor)) { + head = cursorMin(start, head); + anchor = cursorMax(anchor, end); + } else { + anchor = cursorMin(start, anchor); + head = cursorMax(head, end); + head = offsetCursor(head, 0, -1); + if (head.ch == -1 && head.line != cm.firstLine()) { + head = Pos(head.line - 1, lineLength(cm, head.line - 1)); + } + } + return [anchor, head]; + } + /** + * Updates the CodeMirror selection to match the provided vim selection. + * If no arguments are given, it uses the current vim selection state. + */ + function updateCmSelection(cm, sel, mode) { + var vim = cm.state.vim; + sel = sel || vim.sel; + var mode = mode || + vim.visualLine ? 'line' : vim.visualBlock ? 'block' : 'char'; + var cmSel = makeCmSelection(cm, sel, mode); + cm.setSelections(cmSel.ranges, cmSel.primary); + updateFakeCursor(cm); + } + function makeCmSelection(cm, sel, mode, exclusive) { + var head = copyCursor(sel.head); + var anchor = copyCursor(sel.anchor); + if (mode == 'char') { + var headOffset = !exclusive && !cursorIsBefore(sel.head, sel.anchor) ? 1 : 0; + var anchorOffset = cursorIsBefore(sel.head, sel.anchor) ? 1 : 0; + head = offsetCursor(sel.head, 0, headOffset); + anchor = offsetCursor(sel.anchor, 0, anchorOffset); + return { + ranges: [{anchor: anchor, head: head}], + primary: 0 + }; + } else if (mode == 'line') { + if (!cursorIsBefore(sel.head, sel.anchor)) { + anchor.ch = 0; + + var lastLine = cm.lastLine(); + if (head.line > lastLine) { + head.line = lastLine; + } + head.ch = lineLength(cm, head.line); + } else { + head.ch = 0; + anchor.ch = lineLength(cm, anchor.line); + } + return { + ranges: [{anchor: anchor, head: head}], + primary: 0 + }; + } else if (mode == 'block') { + var top = Math.min(anchor.line, head.line), + left = Math.min(anchor.ch, head.ch), + bottom = Math.max(anchor.line, head.line), + right = Math.max(anchor.ch, head.ch) + 1; + var height = bottom - top + 1; + var primary = head.line == top ? 0 : height - 1; + var ranges = []; + for (var i = 0; i < height; i++) { + ranges.push({ + anchor: Pos(top + i, left), + head: Pos(top + i, right) + }); + } + return { + ranges: ranges, + primary: primary + }; + } + } + function getHead(cm) { + var cur = cm.getCursor('head'); + if (cm.getSelection().length == 1) { + // Small corner case when only 1 character is selected. The "real" + // head is the left of head and anchor. + cur = cursorMin(cur, cm.getCursor('anchor')); + } + return cur; + } + + /** + * If moveHead is set to false, the CodeMirror selection will not be + * touched. The caller assumes the responsibility of putting the cursor + * in the right place. + */ + function exitVisualMode(cm, moveHead) { + var vim = cm.state.vim; + if (moveHead !== false) { + cm.setCursor(clipCursorToContent(cm, vim.sel.head)); + } + updateLastSelection(cm, vim); + vim.visualMode = false; + vim.visualLine = false; + vim.visualBlock = false; + CodeMirror.signal(cm, "vim-mode-change", {mode: "normal"}); + if (vim.fakeCursor) { + vim.fakeCursor.clear(); + } + } + + // Remove any trailing newlines from the selection. For + // example, with the caret at the start of the last word on the line, + // 'dw' should word, but not the newline, while 'w' should advance the + // caret to the first character of the next line. + function clipToLine(cm, curStart, curEnd) { + var selection = cm.getRange(curStart, curEnd); + // Only clip if the selection ends with trailing newline + whitespace + if (/\n\s*$/.test(selection)) { + var lines = selection.split('\n'); + // We know this is all whitespace. + lines.pop(); + + // Cases: + // 1. Last word is an empty line - do not clip the trailing '\n' + // 2. Last word is not an empty line - clip the trailing '\n' + var line; + // Find the line containing the last word, and clip all whitespace up + // to it. + for (var line = lines.pop(); lines.length > 0 && line && isWhiteSpaceString(line); line = lines.pop()) { + curEnd.line--; + curEnd.ch = 0; + } + // If the last word is not an empty line, clip an additional newline + if (line) { + curEnd.line--; + curEnd.ch = lineLength(cm, curEnd.line); + } else { + curEnd.ch = 0; + } + } + } + + // Expand the selection to line ends. + function expandSelectionToLine(_cm, curStart, curEnd) { + curStart.ch = 0; + curEnd.ch = 0; + curEnd.line++; + } + + function findFirstNonWhiteSpaceCharacter(text) { + if (!text) { + return 0; + } + var firstNonWS = text.search(/\S/); + return firstNonWS == -1 ? text.length : firstNonWS; + } + + function expandWordUnderCursor(cm, inclusive, _forward, bigWord, noSymbol) { + var cur = getHead(cm); + var line = cm.getLine(cur.line); + var idx = cur.ch; + + // Seek to first word or non-whitespace character, depending on if + // noSymbol is true. + var test = noSymbol ? wordCharTest[0] : bigWordCharTest [0]; + while (!test(line.charAt(idx))) { + idx++; + if (idx >= line.length) { return null; } + } + + if (bigWord) { + test = bigWordCharTest[0]; + } else { + test = wordCharTest[0]; + if (!test(line.charAt(idx))) { + test = wordCharTest[1]; + } + } + + var end = idx, start = idx; + while (test(line.charAt(end)) && end < line.length) { end++; } + while (test(line.charAt(start)) && start >= 0) { start--; } + start++; + + if (inclusive) { + // If present, include all whitespace after word. + // Otherwise, include all whitespace before word, except indentation. + var wordEnd = end; + while (/\s/.test(line.charAt(end)) && end < line.length) { end++; } + if (wordEnd == end) { + var wordStart = start; + while (/\s/.test(line.charAt(start - 1)) && start > 0) { start--; } + if (!start) { start = wordStart; } + } + } + return { start: Pos(cur.line, start), end: Pos(cur.line, end) }; + } + + function recordJumpPosition(cm, oldCur, newCur) { + if (!cursorEqual(oldCur, newCur)) { + vimGlobalState.jumpList.add(cm, oldCur, newCur); + } + } + + function recordLastCharacterSearch(increment, args) { + vimGlobalState.lastCharacterSearch.increment = increment; + vimGlobalState.lastCharacterSearch.forward = args.forward; + vimGlobalState.lastCharacterSearch.selectedCharacter = args.selectedCharacter; + } + + var symbolToMode = { + '(': 'bracket', ')': 'bracket', '{': 'bracket', '}': 'bracket', + '[': 'section', ']': 'section', + '*': 'comment', '/': 'comment', + 'm': 'method', 'M': 'method', + '#': 'preprocess' + }; + var findSymbolModes = { + bracket: { + isComplete: function(state) { + if (state.nextCh === state.symb) { + state.depth++; + if (state.depth >= 1)return true; + } else if (state.nextCh === state.reverseSymb) { + state.depth--; + } + return false; + } + }, + section: { + init: function(state) { + state.curMoveThrough = true; + state.symb = (state.forward ? ']' : '[') === state.symb ? '{' : '}'; + }, + isComplete: function(state) { + return state.index === 0 && state.nextCh === state.symb; + } + }, + comment: { + isComplete: function(state) { + var found = state.lastCh === '*' && state.nextCh === '/'; + state.lastCh = state.nextCh; + return found; + } + }, + // TODO: The original Vim implementation only operates on level 1 and 2. + // The current implementation doesn't check for code block level and + // therefore it operates on any levels. + method: { + init: function(state) { + state.symb = (state.symb === 'm' ? '{' : '}'); + state.reverseSymb = state.symb === '{' ? '}' : '{'; + }, + isComplete: function(state) { + if (state.nextCh === state.symb)return true; + return false; + } + }, + preprocess: { + init: function(state) { + state.index = 0; + }, + isComplete: function(state) { + if (state.nextCh === '#') { + var token = state.lineText.match(/#(\w+)/)[1]; + if (token === 'endif') { + if (state.forward && state.depth === 0) { + return true; + } + state.depth++; + } else if (token === 'if') { + if (!state.forward && state.depth === 0) { + return true; + } + state.depth--; + } + if (token === 'else' && state.depth === 0)return true; + } + return false; + } + } + }; + function findSymbol(cm, repeat, forward, symb) { + var cur = copyCursor(cm.getCursor()); + var increment = forward ? 1 : -1; + var endLine = forward ? cm.lineCount() : -1; + var curCh = cur.ch; + var line = cur.line; + var lineText = cm.getLine(line); + var state = { + lineText: lineText, + nextCh: lineText.charAt(curCh), + lastCh: null, + index: curCh, + symb: symb, + reverseSymb: (forward ? { ')': '(', '}': '{' } : { '(': ')', '{': '}' })[symb], + forward: forward, + depth: 0, + curMoveThrough: false + }; + var mode = symbolToMode[symb]; + if (!mode)return cur; + var init = findSymbolModes[mode].init; + var isComplete = findSymbolModes[mode].isComplete; + if (init) { init(state); } + while (line !== endLine && repeat) { + state.index += increment; + state.nextCh = state.lineText.charAt(state.index); + if (!state.nextCh) { + line += increment; + state.lineText = cm.getLine(line) || ''; + if (increment > 0) { + state.index = 0; + } else { + var lineLen = state.lineText.length; + state.index = (lineLen > 0) ? (lineLen-1) : 0; + } + state.nextCh = state.lineText.charAt(state.index); + } + if (isComplete(state)) { + cur.line = line; + cur.ch = state.index; + repeat--; + } + } + if (state.nextCh || state.curMoveThrough) { + return Pos(line, state.index); + } + return cur; + } + + /* + * Returns the boundaries of the next word. If the cursor in the middle of + * the word, then returns the boundaries of the current word, starting at + * the cursor. If the cursor is at the start/end of a word, and we are going + * forward/backward, respectively, find the boundaries of the next word. + * + * @param {CodeMirror} cm CodeMirror object. + * @param {Cursor} cur The cursor position. + * @param {boolean} forward True to search forward. False to search + * backward. + * @param {boolean} bigWord True if punctuation count as part of the word. + * False if only [a-zA-Z0-9] characters count as part of the word. + * @param {boolean} emptyLineIsWord True if empty lines should be treated + * as words. + * @return {Object{from:number, to:number, line: number}} The boundaries of + * the word, or null if there are no more words. + */ + function findWord(cm, cur, forward, bigWord, emptyLineIsWord) { + var lineNum = cur.line; + var pos = cur.ch; + var line = cm.getLine(lineNum); + var dir = forward ? 1 : -1; + var charTests = bigWord ? bigWordCharTest: wordCharTest; + + if (emptyLineIsWord && line == '') { + lineNum += dir; + line = cm.getLine(lineNum); + if (!isLine(cm, lineNum)) { + return null; + } + pos = (forward) ? 0 : line.length; + } + + while (true) { + if (emptyLineIsWord && line == '') { + return { from: 0, to: 0, line: lineNum }; + } + var stop = (dir > 0) ? line.length : -1; + var wordStart = stop, wordEnd = stop; + // Find bounds of next word. + while (pos != stop) { + var foundWord = false; + for (var i = 0; i < charTests.length && !foundWord; ++i) { + if (charTests[i](line.charAt(pos))) { + wordStart = pos; + // Advance to end of word. + while (pos != stop && charTests[i](line.charAt(pos))) { + pos += dir; + } + wordEnd = pos; + foundWord = wordStart != wordEnd; + if (wordStart == cur.ch && lineNum == cur.line && + wordEnd == wordStart + dir) { + // We started at the end of a word. Find the next one. + continue; + } else { + return { + from: Math.min(wordStart, wordEnd + 1), + to: Math.max(wordStart, wordEnd), + line: lineNum }; + } + } + } + if (!foundWord) { + pos += dir; + } + } + // Advance to next/prev line. + lineNum += dir; + if (!isLine(cm, lineNum)) { + return null; + } + line = cm.getLine(lineNum); + pos = (dir > 0) ? 0 : line.length; + } + } + + /** + * @param {CodeMirror} cm CodeMirror object. + * @param {Pos} cur The position to start from. + * @param {int} repeat Number of words to move past. + * @param {boolean} forward True to search forward. False to search + * backward. + * @param {boolean} wordEnd True to move to end of word. False to move to + * beginning of word. + * @param {boolean} bigWord True if punctuation count as part of the word. + * False if only alphabet characters count as part of the word. + * @return {Cursor} The position the cursor should move to. + */ + function moveToWord(cm, cur, repeat, forward, wordEnd, bigWord) { + var curStart = copyCursor(cur); + var words = []; + if (forward && !wordEnd || !forward && wordEnd) { + repeat++; + } + // For 'e', empty lines are not considered words, go figure. + var emptyLineIsWord = !(forward && wordEnd); + for (var i = 0; i < repeat; i++) { + var word = findWord(cm, cur, forward, bigWord, emptyLineIsWord); + if (!word) { + var eodCh = lineLength(cm, cm.lastLine()); + words.push(forward + ? {line: cm.lastLine(), from: eodCh, to: eodCh} + : {line: 0, from: 0, to: 0}); + break; + } + words.push(word); + cur = Pos(word.line, forward ? (word.to - 1) : word.from); + } + var shortCircuit = words.length != repeat; + var firstWord = words[0]; + var lastWord = words.pop(); + if (forward && !wordEnd) { + // w + if (!shortCircuit && (firstWord.from != curStart.ch || firstWord.line != curStart.line)) { + // We did not start in the middle of a word. Discard the extra word at the end. + lastWord = words.pop(); + } + return Pos(lastWord.line, lastWord.from); + } else if (forward && wordEnd) { + return Pos(lastWord.line, lastWord.to - 1); + } else if (!forward && wordEnd) { + // ge + if (!shortCircuit && (firstWord.to != curStart.ch || firstWord.line != curStart.line)) { + // We did not start in the middle of a word. Discard the extra word at the end. + lastWord = words.pop(); + } + return Pos(lastWord.line, lastWord.to); + } else { + // b + return Pos(lastWord.line, lastWord.from); + } + } + + function moveToCharacter(cm, repeat, forward, character) { + var cur = cm.getCursor(); + var start = cur.ch; + var idx; + for (var i = 0; i < repeat; i ++) { + var line = cm.getLine(cur.line); + idx = charIdxInLine(start, line, character, forward, true); + if (idx == -1) { + return null; + } + start = idx; + } + return Pos(cm.getCursor().line, idx); + } + + function moveToColumn(cm, repeat) { + // repeat is always >= 1, so repeat - 1 always corresponds + // to the column we want to go to. + var line = cm.getCursor().line; + return clipCursorToContent(cm, Pos(line, repeat - 1)); + } + + function updateMark(cm, vim, markName, pos) { + if (!inArray(markName, validMarks)) { + return; + } + if (vim.marks[markName]) { + vim.marks[markName].clear(); + } + vim.marks[markName] = cm.setBookmark(pos); + } + + function charIdxInLine(start, line, character, forward, includeChar) { + // Search for char in line. + // motion_options: {forward, includeChar} + // If includeChar = true, include it too. + // If forward = true, search forward, else search backwards. + // If char is not found on this line, do nothing + var idx; + if (forward) { + idx = line.indexOf(character, start + 1); + if (idx != -1 && !includeChar) { + idx -= 1; + } + } else { + idx = line.lastIndexOf(character, start - 1); + if (idx != -1 && !includeChar) { + idx += 1; + } + } + return idx; + } + + function findParagraph(cm, head, repeat, dir, inclusive) { + var line = head.line; + var min = cm.firstLine(); + var max = cm.lastLine(); + var start, end, i = line; + function isEmpty(i) { return !cm.getLine(i); } + function isBoundary(i, dir, any) { + if (any) { return isEmpty(i) != isEmpty(i + dir); } + return !isEmpty(i) && isEmpty(i + dir); + } + if (dir) { + while (min <= i && i <= max && repeat > 0) { + if (isBoundary(i, dir)) { repeat--; } + i += dir; + } + return new Pos(i, 0); + } + + var vim = cm.state.vim; + if (vim.visualLine && isBoundary(line, 1, true)) { + var anchor = vim.sel.anchor; + if (isBoundary(anchor.line, -1, true)) { + if (!inclusive || anchor.line != line) { + line += 1; + } + } + } + var startState = isEmpty(line); + for (i = line; i <= max && repeat; i++) { + if (isBoundary(i, 1, true)) { + if (!inclusive || isEmpty(i) != startState) { + repeat--; + } + } + } + end = new Pos(i, 0); + // select boundary before paragraph for the last one + if (i > max && !startState) { startState = true; } + else { inclusive = false; } + for (i = line; i > min; i--) { + if (!inclusive || isEmpty(i) == startState || i == line) { + if (isBoundary(i, -1, true)) { break; } + } + } + start = new Pos(i, 0); + return { start: start, end: end }; + } + + function findSentence(cm, cur, repeat, dir) { + + /* + Takes an index object + { + line: the line string, + ln: line number, + pos: index in line, + dir: direction of traversal (-1 or 1) + } + and modifies the line, ln, and pos members to represent the + next valid position or sets them to null if there are + no more valid positions. + */ + function nextChar(cm, idx) { + if (idx.pos + idx.dir < 0 || idx.pos + idx.dir >= idx.line.length) { + idx.ln += idx.dir; + if (!isLine(cm, idx.ln)) { + idx.line = null; + idx.ln = null; + idx.pos = null; + return; + } + idx.line = cm.getLine(idx.ln); + idx.pos = (idx.dir > 0) ? 0 : idx.line.length - 1; + } + else { + idx.pos += idx.dir; + } + } + + /* + Performs one iteration of traversal in forward direction + Returns an index object of the new location + */ + function forward(cm, ln, pos, dir) { + var line = cm.getLine(ln); + var stop = (line === ""); + + var curr = { + line: line, + ln: ln, + pos: pos, + dir: dir, + } + + var last_valid = { + ln: curr.ln, + pos: curr.pos, + } + + var skip_empty_lines = (curr.line === ""); + + // Move one step to skip character we start on + nextChar(cm, curr); + + while (curr.line !== null) { + last_valid.ln = curr.ln; + last_valid.pos = curr.pos; + + if (curr.line === "" && !skip_empty_lines) { + return { ln: curr.ln, pos: curr.pos, }; + } + else if (stop && curr.line !== "" && !isWhiteSpaceString(curr.line[curr.pos])) { + return { ln: curr.ln, pos: curr.pos, }; + } + else if (isEndOfSentenceSymbol(curr.line[curr.pos]) + && !stop + && (curr.pos === curr.line.length - 1 + || isWhiteSpaceString(curr.line[curr.pos + 1]))) { + stop = true; + } + + nextChar(cm, curr); + } + + /* + Set the position to the last non whitespace character on the last + valid line in the case that we reach the end of the document. + */ + var line = cm.getLine(last_valid.ln); + last_valid.pos = 0; + for(var i = line.length - 1; i >= 0; --i) { + if (!isWhiteSpaceString(line[i])) { + last_valid.pos = i; + break; + } + } + + return last_valid; + + } + + /* + Performs one iteration of traversal in reverse direction + Returns an index object of the new location + */ + function reverse(cm, ln, pos, dir) { + var line = cm.getLine(ln); + + var curr = { + line: line, + ln: ln, + pos: pos, + dir: dir, + } + + var last_valid = { + ln: curr.ln, + pos: null, + }; + + var skip_empty_lines = (curr.line === ""); + + // Move one step to skip character we start on + nextChar(cm, curr); + + while (curr.line !== null) { + + if (curr.line === "" && !skip_empty_lines) { + if (last_valid.pos !== null) { + return last_valid; + } + else { + return { ln: curr.ln, pos: curr.pos }; + } + } + else if (isEndOfSentenceSymbol(curr.line[curr.pos]) + && last_valid.pos !== null + && !(curr.ln === last_valid.ln && curr.pos + 1 === last_valid.pos)) { + return last_valid; + } + else if (curr.line !== "" && !isWhiteSpaceString(curr.line[curr.pos])) { + skip_empty_lines = false; + last_valid = { ln: curr.ln, pos: curr.pos } + } + + nextChar(cm, curr); + } + + /* + Set the position to the first non whitespace character on the last + valid line in the case that we reach the beginning of the document. + */ + var line = cm.getLine(last_valid.ln); + last_valid.pos = 0; + for(var i = 0; i < line.length; ++i) { + if (!isWhiteSpaceString(line[i])) { + last_valid.pos = i; + break; + } + } + return last_valid; + } + + var curr_index = { + ln: cur.line, + pos: cur.ch, + }; + + while (repeat > 0) { + if (dir < 0) { + curr_index = reverse(cm, curr_index.ln, curr_index.pos, dir); + } + else { + curr_index = forward(cm, curr_index.ln, curr_index.pos, dir); + } + repeat--; + } + + return Pos(curr_index.ln, curr_index.pos); + } + + // TODO: perhaps this finagling of start and end positions belonds + // in codemirror/replaceRange? + function selectCompanionObject(cm, head, symb, inclusive) { + var cur = head, start, end; + + var bracketRegexp = ({ + '(': /[()]/, ')': /[()]/, + '[': /[[\]]/, ']': /[[\]]/, + '{': /[{}]/, '}': /[{}]/})[symb]; + var openSym = ({ + '(': '(', ')': '(', + '[': '[', ']': '[', + '{': '{', '}': '{'})[symb]; + var curChar = cm.getLine(cur.line).charAt(cur.ch); + // Due to the behavior of scanForBracket, we need to add an offset if the + // cursor is on a matching open bracket. + var offset = curChar === openSym ? 1 : 0; + + start = cm.scanForBracket(Pos(cur.line, cur.ch + offset), -1, undefined, {'bracketRegex': bracketRegexp}); + end = cm.scanForBracket(Pos(cur.line, cur.ch + offset), 1, undefined, {'bracketRegex': bracketRegexp}); + + if (!start || !end) { + return { start: cur, end: cur }; + } + + start = start.pos; + end = end.pos; + + if ((start.line == end.line && start.ch > end.ch) + || (start.line > end.line)) { + var tmp = start; + start = end; + end = tmp; + } + + if (inclusive) { + end.ch += 1; + } else { + start.ch += 1; + } + + return { start: start, end: end }; + } + + // Takes in a symbol and a cursor and tries to simulate text objects that + // have identical opening and closing symbols + // TODO support across multiple lines + function findBeginningAndEnd(cm, head, symb, inclusive) { + var cur = copyCursor(head); + var line = cm.getLine(cur.line); + var chars = line.split(''); + var start, end, i, len; + var firstIndex = chars.indexOf(symb); + + // the decision tree is to always look backwards for the beginning first, + // but if the cursor is in front of the first instance of the symb, + // then move the cursor forward + if (cur.ch < firstIndex) { + cur.ch = firstIndex; + // Why is this line even here??? + // cm.setCursor(cur.line, firstIndex+1); + } + // otherwise if the cursor is currently on the closing symbol + else if (firstIndex < cur.ch && chars[cur.ch] == symb) { + end = cur.ch; // assign end to the current cursor + --cur.ch; // make sure to look backwards + } + + // if we're currently on the symbol, we've got a start + if (chars[cur.ch] == symb && !end) { + start = cur.ch + 1; // assign start to ahead of the cursor + } else { + // go backwards to find the start + for (i = cur.ch; i > -1 && !start; i--) { + if (chars[i] == symb) { + start = i + 1; + } + } + } + + // look forwards for the end symbol + if (start && !end) { + for (i = start, len = chars.length; i < len && !end; i++) { + if (chars[i] == symb) { + end = i; + } + } + } + + // nothing found + if (!start || !end) { + return { start: cur, end: cur }; + } + + // include the symbols + if (inclusive) { + --start; ++end; + } + + return { + start: Pos(cur.line, start), + end: Pos(cur.line, end) + }; + } + + // Search functions + defineOption('pcre', true, 'boolean'); + function SearchState() {} + SearchState.prototype = { + getQuery: function() { + return vimGlobalState.query; + }, + setQuery: function(query) { + vimGlobalState.query = query; + }, + getOverlay: function() { + return this.searchOverlay; + }, + setOverlay: function(overlay) { + this.searchOverlay = overlay; + }, + isReversed: function() { + return vimGlobalState.isReversed; + }, + setReversed: function(reversed) { + vimGlobalState.isReversed = reversed; + }, + getScrollbarAnnotate: function() { + return this.annotate; + }, + setScrollbarAnnotate: function(annotate) { + this.annotate = annotate; + } + }; + function getSearchState(cm) { + var vim = cm.state.vim; + return vim.searchState_ || (vim.searchState_ = new SearchState()); + } + function dialog(cm, template, shortText, onClose, options) { + if (cm.openDialog) { + cm.openDialog(template, onClose, { bottom: true, value: options.value, + onKeyDown: options.onKeyDown, onKeyUp: options.onKeyUp, + selectValueOnOpen: false}); + } + else { + onClose(prompt(shortText, '')); + } + } + function splitBySlash(argString) { + return splitBySeparator(argString, '/'); + } + + function findUnescapedSlashes(argString) { + return findUnescapedSeparators(argString, '/'); + } + + function splitBySeparator(argString, separator) { + var slashes = findUnescapedSeparators(argString, separator) || []; + if (!slashes.length) return []; + var tokens = []; + // in case of strings like foo/bar + if (slashes[0] !== 0) return; + for (var i = 0; i < slashes.length; i++) { + if (typeof slashes[i] == 'number') + tokens.push(argString.substring(slashes[i] + 1, slashes[i+1])); + } + return tokens; + } + + function findUnescapedSeparators(str, separator) { + if (!separator) + separator = '/'; + + var escapeNextChar = false; + var slashes = []; + for (var i = 0; i < str.length; i++) { + var c = str.charAt(i); + if (!escapeNextChar && c == separator) { + slashes.push(i); + } + escapeNextChar = !escapeNextChar && (c == '\\'); + } + return slashes; + } + + // Translates a search string from ex (vim) syntax into javascript form. + function translateRegex(str) { + // When these match, add a '\' if unescaped or remove one if escaped. + var specials = '|(){'; + // Remove, but never add, a '\' for these. + var unescape = '}'; + var escapeNextChar = false; + var out = []; + for (var i = -1; i < str.length; i++) { + var c = str.charAt(i) || ''; + var n = str.charAt(i+1) || ''; + var specialComesNext = (n && specials.indexOf(n) != -1); + if (escapeNextChar) { + if (c !== '\\' || !specialComesNext) { + out.push(c); + } + escapeNextChar = false; + } else { + if (c === '\\') { + escapeNextChar = true; + // Treat the unescape list as special for removing, but not adding '\'. + if (n && unescape.indexOf(n) != -1) { + specialComesNext = true; + } + // Not passing this test means removing a '\'. + if (!specialComesNext || n === '\\') { + out.push(c); + } + } else { + out.push(c); + if (specialComesNext && n !== '\\') { + out.push('\\'); + } + } + } + } + return out.join(''); + } + + // Translates the replace part of a search and replace from ex (vim) syntax into + // javascript form. Similar to translateRegex, but additionally fixes back references + // (translates '\[0..9]' to '$[0..9]') and follows different rules for escaping '$'. + var charUnescapes = {'\\n': '\n', '\\r': '\r', '\\t': '\t'}; + function translateRegexReplace(str) { + var escapeNextChar = false; + var out = []; + for (var i = -1; i < str.length; i++) { + var c = str.charAt(i) || ''; + var n = str.charAt(i+1) || ''; + if (charUnescapes[c + n]) { + out.push(charUnescapes[c+n]); + i++; + } else if (escapeNextChar) { + // At any point in the loop, escapeNextChar is true if the previous + // character was a '\' and was not escaped. + out.push(c); + escapeNextChar = false; + } else { + if (c === '\\') { + escapeNextChar = true; + if ((isNumber(n) || n === '$')) { + out.push('$'); + } else if (n !== '/' && n !== '\\') { + out.push('\\'); + } + } else { + if (c === '$') { + out.push('$'); + } + out.push(c); + if (n === '/') { + out.push('\\'); + } + } + } + } + return out.join(''); + } + + // Unescape \ and / in the replace part, for PCRE mode. + var unescapes = {'\\/': '/', '\\\\': '\\', '\\n': '\n', '\\r': '\r', '\\t': '\t'}; + function unescapeRegexReplace(str) { + var stream = new CodeMirror.StringStream(str); + var output = []; + while (!stream.eol()) { + // Search for \. + while (stream.peek() && stream.peek() != '\\') { + output.push(stream.next()); + } + var matched = false; + for (var matcher in unescapes) { + if (stream.match(matcher, true)) { + matched = true; + output.push(unescapes[matcher]); + break; + } + } + if (!matched) { + // Don't change anything + output.push(stream.next()); + } + } + return output.join(''); + } + + /** + * Extract the regular expression from the query and return a Regexp object. + * Returns null if the query is blank. + * If ignoreCase is passed in, the Regexp object will have the 'i' flag set. + * If smartCase is passed in, and the query contains upper case letters, + * then ignoreCase is overridden, and the 'i' flag will not be set. + * If the query contains the /i in the flag part of the regular expression, + * then both ignoreCase and smartCase are ignored, and 'i' will be passed + * through to the Regex object. + */ + function parseQuery(query, ignoreCase, smartCase) { + // First update the last search register + var lastSearchRegister = vimGlobalState.registerController.getRegister('/'); + lastSearchRegister.setText(query); + // Check if the query is already a regex. + if (query instanceof RegExp) { return query; } + // First try to extract regex + flags from the input. If no flags found, + // extract just the regex. IE does not accept flags directly defined in + // the regex string in the form /regex/flags + var slashes = findUnescapedSlashes(query); + var regexPart; + var forceIgnoreCase; + if (!slashes.length) { + // Query looks like 'regexp' + regexPart = query; + } else { + // Query looks like 'regexp/...' + regexPart = query.substring(0, slashes[0]); + var flagsPart = query.substring(slashes[0]); + forceIgnoreCase = (flagsPart.indexOf('i') != -1); + } + if (!regexPart) { + return null; + } + if (!getOption('pcre')) { + regexPart = translateRegex(regexPart); + } + if (smartCase) { + ignoreCase = (/^[^A-Z]*$/).test(regexPart); + } + var regexp = new RegExp(regexPart, + (ignoreCase || forceIgnoreCase) ? 'i' : undefined); + return regexp; + } + function showConfirm(cm, text) { + if (cm.openNotification) { + cm.openNotification('' + text + '', + {bottom: true, duration: 5000}); + } else { + alert(text); + } + } + function makePrompt(prefix, desc) { + var raw = '' + + (prefix || "") + ''; + if (desc) + raw += ' ' + desc + ''; + return raw; + } + var searchPromptDesc = '(Javascript regexp)'; + function showPrompt(cm, options) { + var shortText = (options.prefix || '') + ' ' + (options.desc || ''); + var prompt = makePrompt(options.prefix, options.desc); + dialog(cm, prompt, shortText, options.onClose, options); + } + function regexEqual(r1, r2) { + if (r1 instanceof RegExp && r2 instanceof RegExp) { + var props = ['global', 'multiline', 'ignoreCase', 'source']; + for (var i = 0; i < props.length; i++) { + var prop = props[i]; + if (r1[prop] !== r2[prop]) { + return false; + } + } + return true; + } + return false; + } + // Returns true if the query is valid. + function updateSearchQuery(cm, rawQuery, ignoreCase, smartCase) { + if (!rawQuery) { + return; + } + var state = getSearchState(cm); + var query = parseQuery(rawQuery, !!ignoreCase, !!smartCase); + if (!query) { + return; + } + highlightSearchMatches(cm, query); + if (regexEqual(query, state.getQuery())) { + return query; + } + state.setQuery(query); + return query; + } + function searchOverlay(query) { + if (query.source.charAt(0) == '^') { + var matchSol = true; + } + return { + token: function(stream) { + if (matchSol && !stream.sol()) { + stream.skipToEnd(); + return; + } + var match = stream.match(query, false); + if (match) { + if (match[0].length == 0) { + // Matched empty string, skip to next. + stream.next(); + return 'searching'; + } + if (!stream.sol()) { + // Backtrack 1 to match \b + stream.backUp(1); + if (!query.exec(stream.next() + match[0])) { + stream.next(); + return null; + } + } + stream.match(query); + return 'searching'; + } + while (!stream.eol()) { + stream.next(); + if (stream.match(query, false)) break; + } + }, + query: query + }; + } + function highlightSearchMatches(cm, query) { + var searchState = getSearchState(cm); + var overlay = searchState.getOverlay(); + if (!overlay || query != overlay.query) { + if (overlay) { + cm.removeOverlay(overlay); + } + overlay = searchOverlay(query); + cm.addOverlay(overlay); + if (cm.showMatchesOnScrollbar) { + if (searchState.getScrollbarAnnotate()) { + searchState.getScrollbarAnnotate().clear(); + } + searchState.setScrollbarAnnotate(cm.showMatchesOnScrollbar(query)); + } + searchState.setOverlay(overlay); + } + } + function findNext(cm, prev, query, repeat) { + if (repeat === undefined) { repeat = 1; } + return cm.operation(function() { + var pos = cm.getCursor(); + var cursor = cm.getSearchCursor(query, pos); + for (var i = 0; i < repeat; i++) { + var found = cursor.find(prev); + if (i == 0 && found && cursorEqual(cursor.from(), pos)) { found = cursor.find(prev); } + if (!found) { + // SearchCursor may have returned null because it hit EOF, wrap + // around and try again. + cursor = cm.getSearchCursor(query, + (prev) ? Pos(cm.lastLine()) : Pos(cm.firstLine(), 0) ); + if (!cursor.find(prev)) { + return; + } + } + } + return cursor.from(); + }); + } + function clearSearchHighlight(cm) { + var state = getSearchState(cm); + cm.removeOverlay(getSearchState(cm).getOverlay()); + state.setOverlay(null); + if (state.getScrollbarAnnotate()) { + state.getScrollbarAnnotate().clear(); + state.setScrollbarAnnotate(null); + } + } + /** + * Check if pos is in the specified range, INCLUSIVE. + * Range can be specified with 1 or 2 arguments. + * If the first range argument is an array, treat it as an array of line + * numbers. Match pos against any of the lines. + * If the first range argument is a number, + * if there is only 1 range argument, check if pos has the same line + * number + * if there are 2 range arguments, then check if pos is in between the two + * range arguments. + */ + function isInRange(pos, start, end) { + if (typeof pos != 'number') { + // Assume it is a cursor position. Get the line number. + pos = pos.line; + } + if (start instanceof Array) { + return inArray(pos, start); + } else { + if (end) { + return (pos >= start && pos <= end); + } else { + return pos == start; + } + } + } + function getUserVisibleLines(cm) { + var scrollInfo = cm.getScrollInfo(); + var occludeToleranceTop = 6; + var occludeToleranceBottom = 10; + var from = cm.coordsChar({left:0, top: occludeToleranceTop + scrollInfo.top}, 'local'); + var bottomY = scrollInfo.clientHeight - occludeToleranceBottom + scrollInfo.top; + var to = cm.coordsChar({left:0, top: bottomY}, 'local'); + return {top: from.line, bottom: to.line}; + } + + function getMarkPos(cm, vim, markName) { + if (markName == '\'') { + var history = cm.doc.history.done; + var event = history[history.length - 2]; + return event && event.ranges && event.ranges[0].head; + } else if (markName == '.') { + if (cm.doc.history.lastModTime == 0) { + return // If no changes, bail out; don't bother to copy or reverse history array. + } else { + var changeHistory = cm.doc.history.done.filter(function(el){ if (el.changes !== undefined) { return el } }); + changeHistory.reverse(); + var lastEditPos = changeHistory[0].changes[0].to; + } + return lastEditPos; + } + + var mark = vim.marks[markName]; + return mark && mark.find(); + } + + var ExCommandDispatcher = function() { + this.buildCommandMap_(); + }; + ExCommandDispatcher.prototype = { + processCommand: function(cm, input, opt_params) { + var that = this; + cm.operation(function () { + cm.curOp.isVimOp = true; + that._processCommand(cm, input, opt_params); + }); + }, + _processCommand: function(cm, input, opt_params) { + var vim = cm.state.vim; + var commandHistoryRegister = vimGlobalState.registerController.getRegister(':'); + var previousCommand = commandHistoryRegister.toString(); + if (vim.visualMode) { + exitVisualMode(cm); + } + var inputStream = new CodeMirror.StringStream(input); + // update ": with the latest command whether valid or invalid + commandHistoryRegister.setText(input); + var params = opt_params || {}; + params.input = input; + try { + this.parseInput_(cm, inputStream, params); + } catch(e) { + showConfirm(cm, e); + throw e; + } + var command; + var commandName; + if (!params.commandName) { + // If only a line range is defined, move to the line. + if (params.line !== undefined) { + commandName = 'move'; + } + } else { + command = this.matchCommand_(params.commandName); + if (command) { + commandName = command.name; + if (command.excludeFromCommandHistory) { + commandHistoryRegister.setText(previousCommand); + } + this.parseCommandArgs_(inputStream, params, command); + if (command.type == 'exToKey') { + // Handle Ex to Key mapping. + for (var i = 0; i < command.toKeys.length; i++) { + CodeMirror.Vim.handleKey(cm, command.toKeys[i], 'mapping'); + } + return; + } else if (command.type == 'exToEx') { + // Handle Ex to Ex mapping. + this.processCommand(cm, command.toInput); + return; + } + } + } + if (!commandName) { + showConfirm(cm, 'Not an editor command ":' + input + '"'); + return; + } + try { + exCommands[commandName](cm, params); + // Possibly asynchronous commands (e.g. substitute, which might have a + // user confirmation), are responsible for calling the callback when + // done. All others have it taken care of for them here. + if ((!command || !command.possiblyAsync) && params.callback) { + params.callback(); + } + } catch(e) { + showConfirm(cm, e); + throw e; + } + }, + parseInput_: function(cm, inputStream, result) { + inputStream.eatWhile(':'); + // Parse range. + if (inputStream.eat('%')) { + result.line = cm.firstLine(); + result.lineEnd = cm.lastLine(); + } else { + result.line = this.parseLineSpec_(cm, inputStream); + if (result.line !== undefined && inputStream.eat(',')) { + result.lineEnd = this.parseLineSpec_(cm, inputStream); + } + } + + // Parse command name. + var commandMatch = inputStream.match(/^(\w+)/); + if (commandMatch) { + result.commandName = commandMatch[1]; + } else { + result.commandName = inputStream.match(/.*/)[0]; + } + + return result; + }, + parseLineSpec_: function(cm, inputStream) { + var numberMatch = inputStream.match(/^(\d+)/); + if (numberMatch) { + // Absolute line number plus offset (N+M or N-M) is probably a typo, + // not something the user actually wanted. (NB: vim does allow this.) + return parseInt(numberMatch[1], 10) - 1; + } + switch (inputStream.next()) { + case '.': + return this.parseLineSpecOffset_(inputStream, cm.getCursor().line); + case '$': + return this.parseLineSpecOffset_(inputStream, cm.lastLine()); + case '\'': + var markName = inputStream.next(); + var markPos = getMarkPos(cm, cm.state.vim, markName); + if (!markPos) throw new Error('Mark not set'); + return this.parseLineSpecOffset_(inputStream, markPos.line); + case '-': + case '+': + inputStream.backUp(1); + // Offset is relative to current line if not otherwise specified. + return this.parseLineSpecOffset_(inputStream, cm.getCursor().line); + default: + inputStream.backUp(1); + return undefined; + } + }, + parseLineSpecOffset_: function(inputStream, line) { + var offsetMatch = inputStream.match(/^([+-])?(\d+)/); + if (offsetMatch) { + var offset = parseInt(offsetMatch[2], 10); + if (offsetMatch[1] == "-") { + line -= offset; + } else { + line += offset; + } + } + return line; + }, + parseCommandArgs_: function(inputStream, params, command) { + if (inputStream.eol()) { + return; + } + params.argString = inputStream.match(/.*/)[0]; + // Parse command-line arguments + var delim = command.argDelimiter || /\s+/; + var args = trim(params.argString).split(delim); + if (args.length && args[0]) { + params.args = args; + } + }, + matchCommand_: function(commandName) { + // Return the command in the command map that matches the shortest + // prefix of the passed in command name. The match is guaranteed to be + // unambiguous if the defaultExCommandMap's shortNames are set up + // correctly. (see @code{defaultExCommandMap}). + for (var i = commandName.length; i > 0; i--) { + var prefix = commandName.substring(0, i); + if (this.commandMap_[prefix]) { + var command = this.commandMap_[prefix]; + if (command.name.indexOf(commandName) === 0) { + return command; + } + } + } + return null; + }, + buildCommandMap_: function() { + this.commandMap_ = {}; + for (var i = 0; i < defaultExCommandMap.length; i++) { + var command = defaultExCommandMap[i]; + var key = command.shortName || command.name; + this.commandMap_[key] = command; + } + }, + map: function(lhs, rhs, ctx) { + if (lhs != ':' && lhs.charAt(0) == ':') { + if (ctx) { throw Error('Mode not supported for ex mappings'); } + var commandName = lhs.substring(1); + if (rhs != ':' && rhs.charAt(0) == ':') { + // Ex to Ex mapping + this.commandMap_[commandName] = { + name: commandName, + type: 'exToEx', + toInput: rhs.substring(1), + user: true + }; + } else { + // Ex to key mapping + this.commandMap_[commandName] = { + name: commandName, + type: 'exToKey', + toKeys: rhs, + user: true + }; + } + } else { + if (rhs != ':' && rhs.charAt(0) == ':') { + // Key to Ex mapping. + var mapping = { + keys: lhs, + type: 'keyToEx', + exArgs: { input: rhs.substring(1) } + }; + if (ctx) { mapping.context = ctx; } + defaultKeymap.unshift(mapping); + } else { + // Key to key mapping + var mapping = { + keys: lhs, + type: 'keyToKey', + toKeys: rhs + }; + if (ctx) { mapping.context = ctx; } + defaultKeymap.unshift(mapping); + } + } + }, + unmap: function(lhs, ctx) { + if (lhs != ':' && lhs.charAt(0) == ':') { + // Ex to Ex or Ex to key mapping + if (ctx) { throw Error('Mode not supported for ex mappings'); } + var commandName = lhs.substring(1); + if (this.commandMap_[commandName] && this.commandMap_[commandName].user) { + delete this.commandMap_[commandName]; + return; + } + } else { + // Key to Ex or key to key mapping + var keys = lhs; + for (var i = 0; i < defaultKeymap.length; i++) { + if (keys == defaultKeymap[i].keys + && defaultKeymap[i].context === ctx) { + defaultKeymap.splice(i, 1); + return; + } + } + } + throw Error('No such mapping.'); + } + }; + + var exCommands = { + colorscheme: function(cm, params) { + if (!params.args || params.args.length < 1) { + showConfirm(cm, cm.getOption('theme')); + return; + } + cm.setOption('theme', params.args[0]); + }, + map: function(cm, params, ctx) { + var mapArgs = params.args; + if (!mapArgs || mapArgs.length < 2) { + if (cm) { + showConfirm(cm, 'Invalid mapping: ' + params.input); + } + return; + } + exCommandDispatcher.map(mapArgs[0], mapArgs[1], ctx); + }, + imap: function(cm, params) { this.map(cm, params, 'insert'); }, + nmap: function(cm, params) { this.map(cm, params, 'normal'); }, + vmap: function(cm, params) { this.map(cm, params, 'visual'); }, + unmap: function(cm, params, ctx) { + var mapArgs = params.args; + if (!mapArgs || mapArgs.length < 1) { + if (cm) { + showConfirm(cm, 'No such mapping: ' + params.input); + } + return; + } + exCommandDispatcher.unmap(mapArgs[0], ctx); + }, + move: function(cm, params) { + commandDispatcher.processCommand(cm, cm.state.vim, { + type: 'motion', + motion: 'moveToLineOrEdgeOfDocument', + motionArgs: { forward: false, explicitRepeat: true, + linewise: true }, + repeatOverride: params.line+1}); + }, + set: function(cm, params) { + var setArgs = params.args; + // Options passed through to the setOption/getOption calls. May be passed in by the + // local/global versions of the set command + var setCfg = params.setCfg || {}; + if (!setArgs || setArgs.length < 1) { + if (cm) { + showConfirm(cm, 'Invalid mapping: ' + params.input); + } + return; + } + var expr = setArgs[0].split('='); + var optionName = expr[0]; + var value = expr[1]; + var forceGet = false; + + if (optionName.charAt(optionName.length - 1) == '?') { + // If post-fixed with ?, then the set is actually a get. + if (value) { throw Error('Trailing characters: ' + params.argString); } + optionName = optionName.substring(0, optionName.length - 1); + forceGet = true; + } + if (value === undefined && optionName.substring(0, 2) == 'no') { + // To set boolean options to false, the option name is prefixed with + // 'no'. + optionName = optionName.substring(2); + value = false; + } + + var optionIsBoolean = options[optionName] && options[optionName].type == 'boolean'; + if (optionIsBoolean && value == undefined) { + // Calling set with a boolean option sets it to true. + value = true; + } + // If no value is provided, then we assume this is a get. + if (!optionIsBoolean && value === undefined || forceGet) { + var oldValue = getOption(optionName, cm, setCfg); + if (oldValue instanceof Error) { + showConfirm(cm, oldValue.message); + } else if (oldValue === true || oldValue === false) { + showConfirm(cm, ' ' + (oldValue ? '' : 'no') + optionName); + } else { + showConfirm(cm, ' ' + optionName + '=' + oldValue); + } + } else { + var setOptionReturn = setOption(optionName, value, cm, setCfg); + if (setOptionReturn instanceof Error) { + showConfirm(cm, setOptionReturn.message); + } + } + }, + setlocal: function (cm, params) { + // setCfg is passed through to setOption + params.setCfg = {scope: 'local'}; + this.set(cm, params); + }, + setglobal: function (cm, params) { + // setCfg is passed through to setOption + params.setCfg = {scope: 'global'}; + this.set(cm, params); + }, + registers: function(cm, params) { + var regArgs = params.args; + var registers = vimGlobalState.registerController.registers; + var regInfo = '----------Registers----------

'; + if (!regArgs) { + for (var registerName in registers) { + var text = registers[registerName].toString(); + if (text.length) { + regInfo += '"' + registerName + ' ' + text + '
'; + } + } + } else { + var registerName; + regArgs = regArgs.join(''); + for (var i = 0; i < regArgs.length; i++) { + registerName = regArgs.charAt(i); + if (!vimGlobalState.registerController.isValidRegister(registerName)) { + continue; + } + var register = registers[registerName] || new Register(); + regInfo += '"' + registerName + ' ' + register.toString() + '
'; + } + } + showConfirm(cm, regInfo); + }, + sort: function(cm, params) { + var reverse, ignoreCase, unique, number, pattern; + function parseArgs() { + if (params.argString) { + var args = new CodeMirror.StringStream(params.argString); + if (args.eat('!')) { reverse = true; } + if (args.eol()) { return; } + if (!args.eatSpace()) { return 'Invalid arguments'; } + var opts = args.match(/([dinuox]+)?\s*(\/.+\/)?\s*/); + if (!opts && !args.eol()) { return 'Invalid arguments'; } + if (opts[1]) { + ignoreCase = opts[1].indexOf('i') != -1; + unique = opts[1].indexOf('u') != -1; + var decimal = opts[1].indexOf('d') != -1 || opts[1].indexOf('n') != -1 && 1; + var hex = opts[1].indexOf('x') != -1 && 1; + var octal = opts[1].indexOf('o') != -1 && 1; + if (decimal + hex + octal > 1) { return 'Invalid arguments'; } + number = decimal && 'decimal' || hex && 'hex' || octal && 'octal'; + } + if (opts[2]) { + pattern = new RegExp(opts[2].substr(1, opts[2].length - 2), ignoreCase ? 'i' : ''); + } + } + } + var err = parseArgs(); + if (err) { + showConfirm(cm, err + ': ' + params.argString); + return; + } + var lineStart = params.line || cm.firstLine(); + var lineEnd = params.lineEnd || params.line || cm.lastLine(); + if (lineStart == lineEnd) { return; } + var curStart = Pos(lineStart, 0); + var curEnd = Pos(lineEnd, lineLength(cm, lineEnd)); + var text = cm.getRange(curStart, curEnd).split('\n'); + var numberRegex = pattern ? pattern : + (number == 'decimal') ? /(-?)([\d]+)/ : + (number == 'hex') ? /(-?)(?:0x)?([0-9a-f]+)/i : + (number == 'octal') ? /([0-7]+)/ : null; + var radix = (number == 'decimal') ? 10 : (number == 'hex') ? 16 : (number == 'octal') ? 8 : null; + var numPart = [], textPart = []; + if (number || pattern) { + for (var i = 0; i < text.length; i++) { + var matchPart = pattern ? text[i].match(pattern) : null; + if (matchPart && matchPart[0] != '') { + numPart.push(matchPart); + } else if (!pattern && numberRegex.exec(text[i])) { + numPart.push(text[i]); + } else { + textPart.push(text[i]); + } + } + } else { + textPart = text; + } + function compareFn(a, b) { + if (reverse) { var tmp; tmp = a; a = b; b = tmp; } + if (ignoreCase) { a = a.toLowerCase(); b = b.toLowerCase(); } + var anum = number && numberRegex.exec(a); + var bnum = number && numberRegex.exec(b); + if (!anum) { return a < b ? -1 : 1; } + anum = parseInt((anum[1] + anum[2]).toLowerCase(), radix); + bnum = parseInt((bnum[1] + bnum[2]).toLowerCase(), radix); + return anum - bnum; + } + function comparePatternFn(a, b) { + if (reverse) { var tmp; tmp = a; a = b; b = tmp; } + if (ignoreCase) { a[0] = a[0].toLowerCase(); b[0] = b[0].toLowerCase(); } + return (a[0] < b[0]) ? -1 : 1; + } + numPart.sort(pattern ? comparePatternFn : compareFn); + if (pattern) { + for (var i = 0; i < numPart.length; i++) { + numPart[i] = numPart[i].input; + } + } else if (!number) { textPart.sort(compareFn); } + text = (!reverse) ? textPart.concat(numPart) : numPart.concat(textPart); + if (unique) { // Remove duplicate lines + var textOld = text; + var lastLine; + text = []; + for (var i = 0; i < textOld.length; i++) { + if (textOld[i] != lastLine) { + text.push(textOld[i]); + } + lastLine = textOld[i]; + } + } + cm.replaceRange(text.join('\n'), curStart, curEnd); + }, + global: function(cm, params) { + // a global command is of the form + // :[range]g/pattern/[cmd] + // argString holds the string /pattern/[cmd] + var argString = params.argString; + if (!argString) { + showConfirm(cm, 'Regular Expression missing from global'); + return; + } + // range is specified here + var lineStart = (params.line !== undefined) ? params.line : cm.firstLine(); + var lineEnd = params.lineEnd || params.line || cm.lastLine(); + // get the tokens from argString + var tokens = splitBySlash(argString); + var regexPart = argString, cmd; + if (tokens.length) { + regexPart = tokens[0]; + cmd = tokens.slice(1, tokens.length).join('/'); + } + if (regexPart) { + // If regex part is empty, then use the previous query. Otherwise + // use the regex part as the new query. + try { + updateSearchQuery(cm, regexPart, true /** ignoreCase */, + true /** smartCase */); + } catch (e) { + showConfirm(cm, 'Invalid regex: ' + regexPart); + return; + } + } + // now that we have the regexPart, search for regex matches in the + // specified range of lines + var query = getSearchState(cm).getQuery(); + var matchedLines = [], content = ''; + for (var i = lineStart; i <= lineEnd; i++) { + var matched = query.test(cm.getLine(i)); + if (matched) { + matchedLines.push(i+1); + content+= cm.getLine(i) + '
'; + } + } + // if there is no [cmd], just display the list of matched lines + if (!cmd) { + showConfirm(cm, content); + return; + } + var index = 0; + var nextCommand = function() { + if (index < matchedLines.length) { + var command = matchedLines[index] + cmd; + exCommandDispatcher.processCommand(cm, command, { + callback: nextCommand + }); + } + index++; + }; + nextCommand(); + }, + substitute: function(cm, params) { + if (!cm.getSearchCursor) { + throw new Error('Search feature not available. Requires searchcursor.js or ' + + 'any other getSearchCursor implementation.'); + } + var argString = params.argString; + var tokens = argString ? splitBySeparator(argString, argString[0]) : []; + var regexPart, replacePart = '', trailing, flagsPart, count; + var confirm = false; // Whether to confirm each replace. + var global = false; // True to replace all instances on a line, false to replace only 1. + if (tokens.length) { + regexPart = tokens[0]; + replacePart = tokens[1]; + if (regexPart && regexPart[regexPart.length - 1] === '$') { + regexPart = regexPart.slice(0, regexPart.length - 1) + '\\n'; + replacePart = replacePart ? replacePart + '\n' : '\n'; + } + if (replacePart !== undefined) { + if (getOption('pcre')) { + replacePart = unescapeRegexReplace(replacePart); + } else { + replacePart = translateRegexReplace(replacePart); + } + vimGlobalState.lastSubstituteReplacePart = replacePart; + } + trailing = tokens[2] ? tokens[2].split(' ') : []; + } else { + // either the argString is empty or its of the form ' hello/world' + // actually splitBySlash returns a list of tokens + // only if the string starts with a '/' + if (argString && argString.length) { + showConfirm(cm, 'Substitutions should be of the form ' + + ':s/pattern/replace/'); + return; + } + } + // After the 3rd slash, we can have flags followed by a space followed + // by count. + if (trailing) { + flagsPart = trailing[0]; + count = parseInt(trailing[1]); + if (flagsPart) { + if (flagsPart.indexOf('c') != -1) { + confirm = true; + flagsPart.replace('c', ''); + } + if (flagsPart.indexOf('g') != -1) { + global = true; + flagsPart.replace('g', ''); + } + regexPart = regexPart.replace(/\//g, "\\/") + '/' + flagsPart; + } + } + if (regexPart) { + // If regex part is empty, then use the previous query. Otherwise use + // the regex part as the new query. + try { + updateSearchQuery(cm, regexPart, true /** ignoreCase */, + true /** smartCase */); + } catch (e) { + showConfirm(cm, 'Invalid regex: ' + regexPart); + return; + } + } + replacePart = replacePart || vimGlobalState.lastSubstituteReplacePart; + if (replacePart === undefined) { + showConfirm(cm, 'No previous substitute regular expression'); + return; + } + var state = getSearchState(cm); + var query = state.getQuery(); + var lineStart = (params.line !== undefined) ? params.line : cm.getCursor().line; + var lineEnd = params.lineEnd || lineStart; + if (lineStart == cm.firstLine() && lineEnd == cm.lastLine()) { + lineEnd = Infinity; + } + if (count) { + lineStart = lineEnd; + lineEnd = lineStart + count - 1; + } + var startPos = clipCursorToContent(cm, Pos(lineStart, 0)); + var cursor = cm.getSearchCursor(query, startPos); + doReplace(cm, confirm, global, lineStart, lineEnd, cursor, query, replacePart, params.callback); + }, + redo: CodeMirror.commands.redo, + undo: CodeMirror.commands.undo, + write: function(cm) { + if (CodeMirror.commands.save) { + // If a save command is defined, call it. + CodeMirror.commands.save(cm); + } else if (cm.save) { + // Saves to text area if no save command is defined and cm.save() is available. + cm.save(); + } + }, + nohlsearch: function(cm) { + clearSearchHighlight(cm); + }, + yank: function (cm) { + var cur = copyCursor(cm.getCursor()); + var line = cur.line; + var lineText = cm.getLine(line); + vimGlobalState.registerController.pushText( + '0', 'yank', lineText, true, true); + }, + delmarks: function(cm, params) { + if (!params.argString || !trim(params.argString)) { + showConfirm(cm, 'Argument required'); + return; + } + + var state = cm.state.vim; + var stream = new CodeMirror.StringStream(trim(params.argString)); + while (!stream.eol()) { + stream.eatSpace(); + + // Record the streams position at the beginning of the loop for use + // in error messages. + var count = stream.pos; + + if (!stream.match(/[a-zA-Z]/, false)) { + showConfirm(cm, 'Invalid argument: ' + params.argString.substring(count)); + return; + } + + var sym = stream.next(); + // Check if this symbol is part of a range + if (stream.match('-', true)) { + // This symbol is part of a range. + + // The range must terminate at an alphabetic character. + if (!stream.match(/[a-zA-Z]/, false)) { + showConfirm(cm, 'Invalid argument: ' + params.argString.substring(count)); + return; + } + + var startMark = sym; + var finishMark = stream.next(); + // The range must terminate at an alphabetic character which + // shares the same case as the start of the range. + if (isLowerCase(startMark) && isLowerCase(finishMark) || + isUpperCase(startMark) && isUpperCase(finishMark)) { + var start = startMark.charCodeAt(0); + var finish = finishMark.charCodeAt(0); + if (start >= finish) { + showConfirm(cm, 'Invalid argument: ' + params.argString.substring(count)); + return; + } + + // Because marks are always ASCII values, and we have + // determined that they are the same case, we can use + // their char codes to iterate through the defined range. + for (var j = 0; j <= finish - start; j++) { + var mark = String.fromCharCode(start + j); + delete state.marks[mark]; + } + } else { + showConfirm(cm, 'Invalid argument: ' + startMark + '-'); + return; + } + } else { + // This symbol is a valid mark, and is not part of a range. + delete state.marks[sym]; + } + } + } + }; + + var exCommandDispatcher = new ExCommandDispatcher(); + + /** + * @param {CodeMirror} cm CodeMirror instance we are in. + * @param {boolean} confirm Whether to confirm each replace. + * @param {Cursor} lineStart Line to start replacing from. + * @param {Cursor} lineEnd Line to stop replacing at. + * @param {RegExp} query Query for performing matches with. + * @param {string} replaceWith Text to replace matches with. May contain $1, + * $2, etc for replacing captured groups using Javascript replace. + * @param {function()} callback A callback for when the replace is done. + */ + function doReplace(cm, confirm, global, lineStart, lineEnd, searchCursor, query, + replaceWith, callback) { + // Set up all the functions. + cm.state.vim.exMode = true; + var done = false; + var lastPos = searchCursor.from(); + function replaceAll() { + cm.operation(function() { + while (!done) { + replace(); + next(); + } + stop(); + }); + } + function replace() { + var text = cm.getRange(searchCursor.from(), searchCursor.to()); + var newText = text.replace(query, replaceWith); + searchCursor.replace(newText); + } + function next() { + // The below only loops to skip over multiple occurrences on the same + // line when 'global' is not true. + while(searchCursor.findNext() && + isInRange(searchCursor.from(), lineStart, lineEnd)) { + if (!global && lastPos && searchCursor.from().line == lastPos.line) { + continue; + } + cm.scrollIntoView(searchCursor.from(), 30); + cm.setSelection(searchCursor.from(), searchCursor.to()); + lastPos = searchCursor.from(); + done = false; + return; + } + done = true; + } + function stop(close) { + if (close) { close(); } + cm.focus(); + if (lastPos) { + cm.setCursor(lastPos); + var vim = cm.state.vim; + vim.exMode = false; + vim.lastHPos = vim.lastHSPos = lastPos.ch; + } + if (callback) { callback(); } + } + function onPromptKeyDown(e, _value, close) { + // Swallow all keys. + CodeMirror.e_stop(e); + var keyName = CodeMirror.keyName(e); + switch (keyName) { + case 'Y': + replace(); next(); break; + case 'N': + next(); break; + case 'A': + // replaceAll contains a call to close of its own. We don't want it + // to fire too early or multiple times. + var savedCallback = callback; + callback = undefined; + cm.operation(replaceAll); + callback = savedCallback; + break; + case 'L': + replace(); + // fall through and exit. + case 'Q': + case 'Esc': + case 'Ctrl-C': + case 'Ctrl-[': + stop(close); + break; + } + if (done) { stop(close); } + return true; + } + + // Actually do replace. + next(); + if (done) { + showConfirm(cm, 'No matches for ' + query.source); + return; + } + if (!confirm) { + replaceAll(); + if (callback) { callback(); } + return; + } + showPrompt(cm, { + prefix: 'replace with ' + replaceWith + ' (y/n/a/q/l)', + onKeyDown: onPromptKeyDown + }); + } + + CodeMirror.keyMap.vim = { + attach: attachVimMap, + detach: detachVimMap, + call: cmKey + }; + + function exitInsertMode(cm) { + var vim = cm.state.vim; + var macroModeState = vimGlobalState.macroModeState; + var insertModeChangeRegister = vimGlobalState.registerController.getRegister('.'); + var isPlaying = macroModeState.isPlaying; + var lastChange = macroModeState.lastInsertModeChanges; + // In case of visual block, the insertModeChanges are not saved as a + // single word, so we convert them to a single word + // so as to update the ". register as expected in real vim. + var text = []; + if (!isPlaying) { + var selLength = lastChange.inVisualBlock && vim.lastSelection ? + vim.lastSelection.visualBlock.height : 1; + var changes = lastChange.changes; + var text = []; + var i = 0; + // In case of multiple selections in blockwise visual, + // the inserted text, for example: 'foo', is stored as + // 'f', 'f', InsertModeKey 'o', 'o', 'o', 'o'. (if you have a block with 2 lines). + // We push the contents of the changes array as per the following: + // 1. In case of InsertModeKey, just increment by 1. + // 2. In case of a character, jump by selLength (2 in the example). + while (i < changes.length) { + // This loop will convert 'ffoooo' to 'foo'. + text.push(changes[i]); + if (changes[i] instanceof InsertModeKey) { + i++; + } else { + i+= selLength; + } + } + lastChange.changes = text; + cm.off('change', onChange); + CodeMirror.off(cm.getInputField(), 'keydown', onKeyEventTargetKeyDown); + } + if (!isPlaying && vim.insertModeRepeat > 1) { + // Perform insert mode repeat for commands like 3,a and 3,o. + repeatLastEdit(cm, vim, vim.insertModeRepeat - 1, + true /** repeatForInsert */); + vim.lastEditInputState.repeatOverride = vim.insertModeRepeat; + } + delete vim.insertModeRepeat; + vim.insertMode = false; + cm.setCursor(cm.getCursor().line, cm.getCursor().ch-1); + cm.setOption('keyMap', 'vim'); + cm.setOption('disableInput', true); + cm.toggleOverwrite(false); // exit replace mode if we were in it. + // update the ". register before exiting insert mode + insertModeChangeRegister.setText(lastChange.changes.join('')); + CodeMirror.signal(cm, "vim-mode-change", {mode: "normal"}); + if (macroModeState.isRecording) { + logInsertModeChange(macroModeState); + } + } + + function _mapCommand(command) { + defaultKeymap.unshift(command); + } + + function mapCommand(keys, type, name, args, extra) { + var command = {keys: keys, type: type}; + command[type] = name; + command[type + "Args"] = args; + for (var key in extra) + command[key] = extra[key]; + _mapCommand(command); + } + + // The timeout in milliseconds for the two-character ESC keymap should be + // adjusted according to your typing speed to prevent false positives. + defineOption('insertModeEscKeysTimeout', 200, 'number'); + + CodeMirror.keyMap['vim-insert'] = { + // TODO: override navigation keys so that Esc will cancel automatic + // indentation from o, O, i_ + fallthrough: ['default'], + attach: attachVimMap, + detach: detachVimMap, + call: cmKey + }; + + CodeMirror.keyMap['vim-replace'] = { + 'Backspace': 'goCharLeft', + fallthrough: ['vim-insert'], + attach: attachVimMap, + detach: detachVimMap, + call: cmKey + }; + + function executeMacroRegister(cm, vim, macroModeState, registerName) { + var register = vimGlobalState.registerController.getRegister(registerName); + if (registerName == ':') { + // Read-only register containing last Ex command. + if (register.keyBuffer[0]) { + exCommandDispatcher.processCommand(cm, register.keyBuffer[0]); + } + macroModeState.isPlaying = false; + return; + } + var keyBuffer = register.keyBuffer; + var imc = 0; + macroModeState.isPlaying = true; + macroModeState.replaySearchQueries = register.searchQueries.slice(0); + for (var i = 0; i < keyBuffer.length; i++) { + var text = keyBuffer[i]; + var match, key; + while (text) { + // Pull off one command key, which is either a single character + // or a special sequence wrapped in '<' and '>', e.g. ''. + match = (/<\w+-.+?>|<\w+>|./).exec(text); + key = match[0]; + text = text.substring(match.index + key.length); + CodeMirror.Vim.handleKey(cm, key, 'macro'); + if (vim.insertMode) { + var changes = register.insertModeChanges[imc++].changes; + vimGlobalState.macroModeState.lastInsertModeChanges.changes = + changes; + repeatInsertModeChanges(cm, changes, 1); + exitInsertMode(cm); + } + } + } + macroModeState.isPlaying = false; + } + + function logKey(macroModeState, key) { + if (macroModeState.isPlaying) { return; } + var registerName = macroModeState.latestRegister; + var register = vimGlobalState.registerController.getRegister(registerName); + if (register) { + register.pushText(key); + } + } + + function logInsertModeChange(macroModeState) { + if (macroModeState.isPlaying) { return; } + var registerName = macroModeState.latestRegister; + var register = vimGlobalState.registerController.getRegister(registerName); + if (register && register.pushInsertModeChanges) { + register.pushInsertModeChanges(macroModeState.lastInsertModeChanges); + } + } + + function logSearchQuery(macroModeState, query) { + if (macroModeState.isPlaying) { return; } + var registerName = macroModeState.latestRegister; + var register = vimGlobalState.registerController.getRegister(registerName); + if (register && register.pushSearchQuery) { + register.pushSearchQuery(query); + } + } + + /** + * Listens for changes made in insert mode. + * Should only be active in insert mode. + */ + function onChange(cm, changeObj) { + var macroModeState = vimGlobalState.macroModeState; + var lastChange = macroModeState.lastInsertModeChanges; + if (!macroModeState.isPlaying) { + while(changeObj) { + lastChange.expectCursorActivityForChange = true; + if (changeObj.origin == '+input' || changeObj.origin == 'paste' + || changeObj.origin === undefined /* only in testing */) { + var text = changeObj.text.join('\n'); + if (lastChange.maybeReset) { + lastChange.changes = []; + lastChange.maybeReset = false; + } + if (cm.state.overwrite && !/\n/.test(text)) { + lastChange.changes.push([text]); + } else { + lastChange.changes.push(text); + } + } + // Change objects may be chained with next. + changeObj = changeObj.next; + } + } + } + + /** + * Listens for any kind of cursor activity on CodeMirror. + */ + function onCursorActivity(cm) { + var vim = cm.state.vim; + if (vim.insertMode) { + // Tracking cursor activity in insert mode (for macro support). + var macroModeState = vimGlobalState.macroModeState; + if (macroModeState.isPlaying) { return; } + var lastChange = macroModeState.lastInsertModeChanges; + if (lastChange.expectCursorActivityForChange) { + lastChange.expectCursorActivityForChange = false; + } else { + // Cursor moved outside the context of an edit. Reset the change. + lastChange.maybeReset = true; + } + } else if (!cm.curOp.isVimOp) { + handleExternalSelection(cm, vim); + } + if (vim.visualMode) { + updateFakeCursor(cm); + } + } + function updateFakeCursor(cm) { + var vim = cm.state.vim; + var from = clipCursorToContent(cm, copyCursor(vim.sel.head)); + var to = offsetCursor(from, 0, 1); + if (vim.fakeCursor) { + vim.fakeCursor.clear(); + } + vim.fakeCursor = cm.markText(from, to, {className: 'cm-animate-fat-cursor'}); + } + function handleExternalSelection(cm, vim) { + var anchor = cm.getCursor('anchor'); + var head = cm.getCursor('head'); + // Enter or exit visual mode to match mouse selection. + if (vim.visualMode && !cm.somethingSelected()) { + exitVisualMode(cm, false); + } else if (!vim.visualMode && !vim.insertMode && cm.somethingSelected()) { + vim.visualMode = true; + vim.visualLine = false; + CodeMirror.signal(cm, "vim-mode-change", {mode: "visual"}); + } + if (vim.visualMode) { + // Bind CodeMirror selection model to vim selection model. + // Mouse selections are considered visual characterwise. + var headOffset = !cursorIsBefore(head, anchor) ? -1 : 0; + var anchorOffset = cursorIsBefore(head, anchor) ? -1 : 0; + head = offsetCursor(head, 0, headOffset); + anchor = offsetCursor(anchor, 0, anchorOffset); + vim.sel = { + anchor: anchor, + head: head + }; + updateMark(cm, vim, '<', cursorMin(head, anchor)); + updateMark(cm, vim, '>', cursorMax(head, anchor)); + } else if (!vim.insertMode) { + // Reset lastHPos if selection was modified by something outside of vim mode e.g. by mouse. + vim.lastHPos = cm.getCursor().ch; + } + } + + /** Wrapper for special keys pressed in insert mode */ + function InsertModeKey(keyName) { + this.keyName = keyName; + } + + /** + * Handles raw key down events from the text area. + * - Should only be active in insert mode. + * - For recording deletes in insert mode. + */ + function onKeyEventTargetKeyDown(e) { + var macroModeState = vimGlobalState.macroModeState; + var lastChange = macroModeState.lastInsertModeChanges; + var keyName = CodeMirror.keyName(e); + if (!keyName) { return; } + function onKeyFound() { + if (lastChange.maybeReset) { + lastChange.changes = []; + lastChange.maybeReset = false; + } + lastChange.changes.push(new InsertModeKey(keyName)); + return true; + } + if (keyName.indexOf('Delete') != -1 || keyName.indexOf('Backspace') != -1) { + CodeMirror.lookupKey(keyName, 'vim-insert', onKeyFound); + } + } + + /** + * Repeats the last edit, which includes exactly 1 command and at most 1 + * insert. Operator and motion commands are read from lastEditInputState, + * while action commands are read from lastEditActionCommand. + * + * If repeatForInsert is true, then the function was called by + * exitInsertMode to repeat the insert mode changes the user just made. The + * corresponding enterInsertMode call was made with a count. + */ + function repeatLastEdit(cm, vim, repeat, repeatForInsert) { + var macroModeState = vimGlobalState.macroModeState; + macroModeState.isPlaying = true; + var isAction = !!vim.lastEditActionCommand; + var cachedInputState = vim.inputState; + function repeatCommand() { + if (isAction) { + commandDispatcher.processAction(cm, vim, vim.lastEditActionCommand); + } else { + commandDispatcher.evalInput(cm, vim); + } + } + function repeatInsert(repeat) { + if (macroModeState.lastInsertModeChanges.changes.length > 0) { + // For some reason, repeat cw in desktop VIM does not repeat + // insert mode changes. Will conform to that behavior. + repeat = !vim.lastEditActionCommand ? 1 : repeat; + var changeObject = macroModeState.lastInsertModeChanges; + repeatInsertModeChanges(cm, changeObject.changes, repeat); + } + } + vim.inputState = vim.lastEditInputState; + if (isAction && vim.lastEditActionCommand.interlaceInsertRepeat) { + // o and O repeat have to be interlaced with insert repeats so that the + // insertions appear on separate lines instead of the last line. + for (var i = 0; i < repeat; i++) { + repeatCommand(); + repeatInsert(1); + } + } else { + if (!repeatForInsert) { + // Hack to get the cursor to end up at the right place. If I is + // repeated in insert mode repeat, cursor will be 1 insert + // change set left of where it should be. + repeatCommand(); + } + repeatInsert(repeat); + } + vim.inputState = cachedInputState; + if (vim.insertMode && !repeatForInsert) { + // Don't exit insert mode twice. If repeatForInsert is set, then we + // were called by an exitInsertMode call lower on the stack. + exitInsertMode(cm); + } + macroModeState.isPlaying = false; + } + + function repeatInsertModeChanges(cm, changes, repeat) { + function keyHandler(binding) { + if (typeof binding == 'string') { + CodeMirror.commands[binding](cm); + } else { + binding(cm); + } + return true; + } + var head = cm.getCursor('head'); + var inVisualBlock = vimGlobalState.macroModeState.lastInsertModeChanges.inVisualBlock; + if (inVisualBlock) { + // Set up block selection again for repeating the changes. + var vim = cm.state.vim; + var lastSel = vim.lastSelection; + var offset = getOffset(lastSel.anchor, lastSel.head); + selectForInsert(cm, head, offset.line + 1); + repeat = cm.listSelections().length; + cm.setCursor(head); + } + for (var i = 0; i < repeat; i++) { + if (inVisualBlock) { + cm.setCursor(offsetCursor(head, i, 0)); + } + for (var j = 0; j < changes.length; j++) { + var change = changes[j]; + if (change instanceof InsertModeKey) { + CodeMirror.lookupKey(change.keyName, 'vim-insert', keyHandler); + } else if (typeof change == "string") { + var cur = cm.getCursor(); + cm.replaceRange(change, cur, cur); + } else { + var start = cm.getCursor(); + var end = offsetCursor(start, 0, change[0].length); + cm.replaceRange(change[0], start, end); + } + } + } + if (inVisualBlock) { + cm.setCursor(offsetCursor(head, 0, 1)); + } + } + + resetVimGlobalState(); + return vimApi; + }; + // Initialize Vim and make it available as an API. + CodeMirror.Vim = Vim(); + }); + + +/***/ }), +/* 21 */ +/***/ (function(module, exports, __webpack_require__) { + + // CodeMirror, copyright (c) by Marijn Haverbeke and others + // Distributed under an MIT license: http://codemirror.net/LICENSE + + // A rough approximation of Sublime Text's keybindings + // Depends on addon/search/searchcursor.js and optionally addon/dialog/dialogs.js + + (function(mod) { + if (true) // CommonJS + mod(__webpack_require__(2), __webpack_require__(3), __webpack_require__(5)); + else if (typeof define == "function" && define.amd) // AMD + define(["../lib/codemirror", "../addon/search/searchcursor", "../addon/edit/matchbrackets"], mod); + else // Plain browser env + mod(CodeMirror); + })(function(CodeMirror) { + "use strict"; + + var cmds = CodeMirror.commands; + var Pos = CodeMirror.Pos; + + // This is not exactly Sublime's algorithm. I couldn't make heads or tails of that. + function findPosSubword(doc, start, dir) { + if (dir < 0 && start.ch == 0) return doc.clipPos(Pos(start.line - 1)); + var line = doc.getLine(start.line); + if (dir > 0 && start.ch >= line.length) return doc.clipPos(Pos(start.line + 1, 0)); + var state = "start", type; + for (var pos = start.ch, e = dir < 0 ? 0 : line.length, i = 0; pos != e; pos += dir, i++) { + var next = line.charAt(dir < 0 ? pos - 1 : pos); + var cat = next != "_" && CodeMirror.isWordChar(next) ? "w" : "o"; + if (cat == "w" && next.toUpperCase() == next) cat = "W"; + if (state == "start") { + if (cat != "o") { state = "in"; type = cat; } + } else if (state == "in") { + if (type != cat) { + if (type == "w" && cat == "W" && dir < 0) pos--; + if (type == "W" && cat == "w" && dir > 0) { type = "w"; continue; } + break; + } + } + } + return Pos(start.line, pos); + } + + function moveSubword(cm, dir) { + cm.extendSelectionsBy(function(range) { + if (cm.display.shift || cm.doc.extend || range.empty()) + return findPosSubword(cm.doc, range.head, dir); + else + return dir < 0 ? range.from() : range.to(); + }); + } + + cmds.goSubwordLeft = function(cm) { moveSubword(cm, -1); }; + cmds.goSubwordRight = function(cm) { moveSubword(cm, 1); }; + + cmds.scrollLineUp = function(cm) { + var info = cm.getScrollInfo(); + if (!cm.somethingSelected()) { + var visibleBottomLine = cm.lineAtHeight(info.top + info.clientHeight, "local"); + if (cm.getCursor().line >= visibleBottomLine) + cm.execCommand("goLineUp"); + } + cm.scrollTo(null, info.top - cm.defaultTextHeight()); + }; + cmds.scrollLineDown = function(cm) { + var info = cm.getScrollInfo(); + if (!cm.somethingSelected()) { + var visibleTopLine = cm.lineAtHeight(info.top, "local")+1; + if (cm.getCursor().line <= visibleTopLine) + cm.execCommand("goLineDown"); + } + cm.scrollTo(null, info.top + cm.defaultTextHeight()); + }; + + cmds.splitSelectionByLine = function(cm) { + var ranges = cm.listSelections(), lineRanges = []; + for (var i = 0; i < ranges.length; i++) { + var from = ranges[i].from(), to = ranges[i].to(); + for (var line = from.line; line <= to.line; ++line) + if (!(to.line > from.line && line == to.line && to.ch == 0)) + lineRanges.push({anchor: line == from.line ? from : Pos(line, 0), + head: line == to.line ? to : Pos(line)}); + } + cm.setSelections(lineRanges, 0); + }; + + cmds.singleSelectionTop = function(cm) { + var range = cm.listSelections()[0]; + cm.setSelection(range.anchor, range.head, {scroll: false}); + }; + + cmds.selectLine = function(cm) { + var ranges = cm.listSelections(), extended = []; + for (var i = 0; i < ranges.length; i++) { + var range = ranges[i]; + extended.push({anchor: Pos(range.from().line, 0), + head: Pos(range.to().line + 1, 0)}); + } + cm.setSelections(extended); + }; + + function insertLine(cm, above) { + if (cm.isReadOnly()) return CodeMirror.Pass + cm.operation(function() { + var len = cm.listSelections().length, newSelection = [], last = -1; + for (var i = 0; i < len; i++) { + var head = cm.listSelections()[i].head; + if (head.line <= last) continue; + var at = Pos(head.line + (above ? 0 : 1), 0); + cm.replaceRange("\n", at, null, "+insertLine"); + cm.indentLine(at.line, null, true); + newSelection.push({head: at, anchor: at}); + last = head.line + 1; + } + cm.setSelections(newSelection); + }); + cm.execCommand("indentAuto"); + } + + cmds.insertLineAfter = function(cm) { return insertLine(cm, false); }; + + cmds.insertLineBefore = function(cm) { return insertLine(cm, true); }; + + function wordAt(cm, pos) { + var start = pos.ch, end = start, line = cm.getLine(pos.line); + while (start && CodeMirror.isWordChar(line.charAt(start - 1))) --start; + while (end < line.length && CodeMirror.isWordChar(line.charAt(end))) ++end; + return {from: Pos(pos.line, start), to: Pos(pos.line, end), word: line.slice(start, end)}; + } + + cmds.selectNextOccurrence = function(cm) { + var from = cm.getCursor("from"), to = cm.getCursor("to"); + var fullWord = cm.state.sublimeFindFullWord == cm.doc.sel; + if (CodeMirror.cmpPos(from, to) == 0) { + var word = wordAt(cm, from); + if (!word.word) return; + cm.setSelection(word.from, word.to); + fullWord = true; + } else { + var text = cm.getRange(from, to); + var query = fullWord ? new RegExp("\\b" + text + "\\b") : text; + var cur = cm.getSearchCursor(query, to); + var found = cur.findNext(); + if (!found) { + cur = cm.getSearchCursor(query, Pos(cm.firstLine(), 0)); + found = cur.findNext(); + } + if (!found || isSelectedRange(cm.listSelections(), cur.from(), cur.to())) + return CodeMirror.Pass + cm.addSelection(cur.from(), cur.to()); + } + if (fullWord) + cm.state.sublimeFindFullWord = cm.doc.sel; + }; + + function addCursorToSelection(cm, dir) { + var ranges = cm.listSelections(), newRanges = []; + for (var i = 0; i < ranges.length; i++) { + var range = ranges[i]; + var newAnchor = cm.findPosV( + range.anchor, dir, "line", range.anchor.goalColumn); + var newHead = cm.findPosV( + range.head, dir, "line", range.head.goalColumn); + newAnchor.goalColumn = range.anchor.goalColumn != null ? + range.anchor.goalColumn : cm.cursorCoords(range.anchor, "div").left; + newHead.goalColumn = range.head.goalColumn != null ? + range.head.goalColumn : cm.cursorCoords(range.head, "div").left; + var newRange = {anchor: newAnchor, head: newHead}; + newRanges.push(range); + newRanges.push(newRange); + } + cm.setSelections(newRanges); + } + cmds.addCursorToPrevLine = function(cm) { addCursorToSelection(cm, -1); }; + cmds.addCursorToNextLine = function(cm) { addCursorToSelection(cm, 1); }; + + function isSelectedRange(ranges, from, to) { + for (var i = 0; i < ranges.length; i++) + if (ranges[i].from() == from && ranges[i].to() == to) return true + return false + } + + var mirror = "(){}[]"; + function selectBetweenBrackets(cm) { + var ranges = cm.listSelections(), newRanges = [] + for (var i = 0; i < ranges.length; i++) { + var range = ranges[i], pos = range.head, opening = cm.scanForBracket(pos, -1); + if (!opening) return false; + for (;;) { + var closing = cm.scanForBracket(pos, 1); + if (!closing) return false; + if (closing.ch == mirror.charAt(mirror.indexOf(opening.ch) + 1)) { + var startPos = Pos(opening.pos.line, opening.pos.ch + 1); + if (CodeMirror.cmpPos(startPos, range.from()) == 0 && + CodeMirror.cmpPos(closing.pos, range.to()) == 0) { + opening = cm.scanForBracket(opening.pos, -1); + if (!opening) return false; + } else { + newRanges.push({anchor: startPos, head: closing.pos}); + break; + } + } + pos = Pos(closing.pos.line, closing.pos.ch + 1); + } + } + cm.setSelections(newRanges); + return true; + } + + cmds.selectScope = function(cm) { + selectBetweenBrackets(cm) || cm.execCommand("selectAll"); + }; + cmds.selectBetweenBrackets = function(cm) { + if (!selectBetweenBrackets(cm)) return CodeMirror.Pass; + }; + + cmds.goToBracket = function(cm) { + cm.extendSelectionsBy(function(range) { + var next = cm.scanForBracket(range.head, 1); + if (next && CodeMirror.cmpPos(next.pos, range.head) != 0) return next.pos; + var prev = cm.scanForBracket(range.head, -1); + return prev && Pos(prev.pos.line, prev.pos.ch + 1) || range.head; + }); + }; + + cmds.swapLineUp = function(cm) { + if (cm.isReadOnly()) return CodeMirror.Pass + var ranges = cm.listSelections(), linesToMove = [], at = cm.firstLine() - 1, newSels = []; + for (var i = 0; i < ranges.length; i++) { + var range = ranges[i], from = range.from().line - 1, to = range.to().line; + newSels.push({anchor: Pos(range.anchor.line - 1, range.anchor.ch), + head: Pos(range.head.line - 1, range.head.ch)}); + if (range.to().ch == 0 && !range.empty()) --to; + if (from > at) linesToMove.push(from, to); + else if (linesToMove.length) linesToMove[linesToMove.length - 1] = to; + at = to; + } + cm.operation(function() { + for (var i = 0; i < linesToMove.length; i += 2) { + var from = linesToMove[i], to = linesToMove[i + 1]; + var line = cm.getLine(from); + cm.replaceRange("", Pos(from, 0), Pos(from + 1, 0), "+swapLine"); + if (to > cm.lastLine()) + cm.replaceRange("\n" + line, Pos(cm.lastLine()), null, "+swapLine"); + else + cm.replaceRange(line + "\n", Pos(to, 0), null, "+swapLine"); + } + cm.setSelections(newSels); + cm.scrollIntoView(); + }); + }; + + cmds.swapLineDown = function(cm) { + if (cm.isReadOnly()) return CodeMirror.Pass + var ranges = cm.listSelections(), linesToMove = [], at = cm.lastLine() + 1; + for (var i = ranges.length - 1; i >= 0; i--) { + var range = ranges[i], from = range.to().line + 1, to = range.from().line; + if (range.to().ch == 0 && !range.empty()) from--; + if (from < at) linesToMove.push(from, to); + else if (linesToMove.length) linesToMove[linesToMove.length - 1] = to; + at = to; + } + cm.operation(function() { + for (var i = linesToMove.length - 2; i >= 0; i -= 2) { + var from = linesToMove[i], to = linesToMove[i + 1]; + var line = cm.getLine(from); + if (from == cm.lastLine()) + cm.replaceRange("", Pos(from - 1), Pos(from), "+swapLine"); + else + cm.replaceRange("", Pos(from, 0), Pos(from + 1, 0), "+swapLine"); + cm.replaceRange(line + "\n", Pos(to, 0), null, "+swapLine"); + } + cm.scrollIntoView(); + }); + }; + + cmds.toggleCommentIndented = function(cm) { + cm.toggleComment({ indent: true }); + } + + cmds.joinLines = function(cm) { + var ranges = cm.listSelections(), joined = []; + for (var i = 0; i < ranges.length; i++) { + var range = ranges[i], from = range.from(); + var start = from.line, end = range.to().line; + while (i < ranges.length - 1 && ranges[i + 1].from().line == end) + end = ranges[++i].to().line; + joined.push({start: start, end: end, anchor: !range.empty() && from}); + } + cm.operation(function() { + var offset = 0, ranges = []; + for (var i = 0; i < joined.length; i++) { + var obj = joined[i]; + var anchor = obj.anchor && Pos(obj.anchor.line - offset, obj.anchor.ch), head; + for (var line = obj.start; line <= obj.end; line++) { + var actual = line - offset; + if (line == obj.end) head = Pos(actual, cm.getLine(actual).length + 1); + if (actual < cm.lastLine()) { + cm.replaceRange(" ", Pos(actual), Pos(actual + 1, /^\s*/.exec(cm.getLine(actual + 1))[0].length)); + ++offset; + } + } + ranges.push({anchor: anchor || head, head: head}); + } + cm.setSelections(ranges, 0); + }); + }; + + cmds.duplicateLine = function(cm) { + cm.operation(function() { + var rangeCount = cm.listSelections().length; + for (var i = 0; i < rangeCount; i++) { + var range = cm.listSelections()[i]; + if (range.empty()) + cm.replaceRange(cm.getLine(range.head.line) + "\n", Pos(range.head.line, 0)); + else + cm.replaceRange(cm.getRange(range.from(), range.to()), range.from()); + } + cm.scrollIntoView(); + }); + }; + + + function sortLines(cm, caseSensitive) { + if (cm.isReadOnly()) return CodeMirror.Pass + var ranges = cm.listSelections(), toSort = [], selected; + for (var i = 0; i < ranges.length; i++) { + var range = ranges[i]; + if (range.empty()) continue; + var from = range.from().line, to = range.to().line; + while (i < ranges.length - 1 && ranges[i + 1].from().line == to) + to = ranges[++i].to().line; + if (!ranges[i].to().ch) to--; + toSort.push(from, to); + } + if (toSort.length) selected = true; + else toSort.push(cm.firstLine(), cm.lastLine()); + + cm.operation(function() { + var ranges = []; + for (var i = 0; i < toSort.length; i += 2) { + var from = toSort[i], to = toSort[i + 1]; + var start = Pos(from, 0), end = Pos(to); + var lines = cm.getRange(start, end, false); + if (caseSensitive) + lines.sort(); + else + lines.sort(function(a, b) { + var au = a.toUpperCase(), bu = b.toUpperCase(); + if (au != bu) { a = au; b = bu; } + return a < b ? -1 : a == b ? 0 : 1; + }); + cm.replaceRange(lines, start, end); + if (selected) ranges.push({anchor: start, head: Pos(to + 1, 0)}); + } + if (selected) cm.setSelections(ranges, 0); + }); + } + + cmds.sortLines = function(cm) { sortLines(cm, true); }; + cmds.sortLinesInsensitive = function(cm) { sortLines(cm, false); }; + + cmds.nextBookmark = function(cm) { + var marks = cm.state.sublimeBookmarks; + if (marks) while (marks.length) { + var current = marks.shift(); + var found = current.find(); + if (found) { + marks.push(current); + return cm.setSelection(found.from, found.to); + } + } + }; + + cmds.prevBookmark = function(cm) { + var marks = cm.state.sublimeBookmarks; + if (marks) while (marks.length) { + marks.unshift(marks.pop()); + var found = marks[marks.length - 1].find(); + if (!found) + marks.pop(); + else + return cm.setSelection(found.from, found.to); + } + }; + + cmds.toggleBookmark = function(cm) { + var ranges = cm.listSelections(); + var marks = cm.state.sublimeBookmarks || (cm.state.sublimeBookmarks = []); + for (var i = 0; i < ranges.length; i++) { + var from = ranges[i].from(), to = ranges[i].to(); + var found = ranges[i].empty() ? cm.findMarksAt(from) : cm.findMarks(from, to); + for (var j = 0; j < found.length; j++) { + if (found[j].sublimeBookmark) { + found[j].clear(); + for (var k = 0; k < marks.length; k++) + if (marks[k] == found[j]) + marks.splice(k--, 1); + break; + } + } + if (j == found.length) + marks.push(cm.markText(from, to, {sublimeBookmark: true, clearWhenEmpty: false})); + } + }; + + cmds.clearBookmarks = function(cm) { + var marks = cm.state.sublimeBookmarks; + if (marks) for (var i = 0; i < marks.length; i++) marks[i].clear(); + marks.length = 0; + }; + + cmds.selectBookmarks = function(cm) { + var marks = cm.state.sublimeBookmarks, ranges = []; + if (marks) for (var i = 0; i < marks.length; i++) { + var found = marks[i].find(); + if (!found) + marks.splice(i--, 0); + else + ranges.push({anchor: found.from, head: found.to}); + } + if (ranges.length) + cm.setSelections(ranges, 0); + }; + + function modifyWordOrSelection(cm, mod) { + cm.operation(function() { + var ranges = cm.listSelections(), indices = [], replacements = []; + for (var i = 0; i < ranges.length; i++) { + var range = ranges[i]; + if (range.empty()) { indices.push(i); replacements.push(""); } + else replacements.push(mod(cm.getRange(range.from(), range.to()))); + } + cm.replaceSelections(replacements, "around", "case"); + for (var i = indices.length - 1, at; i >= 0; i--) { + var range = ranges[indices[i]]; + if (at && CodeMirror.cmpPos(range.head, at) > 0) continue; + var word = wordAt(cm, range.head); + at = word.from; + cm.replaceRange(mod(word.word), word.from, word.to); + } + }); + } + + cmds.smartBackspace = function(cm) { + if (cm.somethingSelected()) return CodeMirror.Pass; + + cm.operation(function() { + var cursors = cm.listSelections(); + var indentUnit = cm.getOption("indentUnit"); + + for (var i = cursors.length - 1; i >= 0; i--) { + var cursor = cursors[i].head; + var toStartOfLine = cm.getRange({line: cursor.line, ch: 0}, cursor); + var column = CodeMirror.countColumn(toStartOfLine, null, cm.getOption("tabSize")); + + // Delete by one character by default + var deletePos = cm.findPosH(cursor, -1, "char", false); + + if (toStartOfLine && !/\S/.test(toStartOfLine) && column % indentUnit == 0) { + var prevIndent = new Pos(cursor.line, + CodeMirror.findColumn(toStartOfLine, column - indentUnit, indentUnit)); + + // Smart delete only if we found a valid prevIndent location + if (prevIndent.ch != cursor.ch) deletePos = prevIndent; + } + + cm.replaceRange("", deletePos, cursor, "+delete"); + } + }); + }; + + cmds.delLineRight = function(cm) { + cm.operation(function() { + var ranges = cm.listSelections(); + for (var i = ranges.length - 1; i >= 0; i--) + cm.replaceRange("", ranges[i].anchor, Pos(ranges[i].to().line), "+delete"); + cm.scrollIntoView(); + }); + }; + + cmds.upcaseAtCursor = function(cm) { + modifyWordOrSelection(cm, function(str) { return str.toUpperCase(); }); + }; + cmds.downcaseAtCursor = function(cm) { + modifyWordOrSelection(cm, function(str) { return str.toLowerCase(); }); + }; + + cmds.setSublimeMark = function(cm) { + if (cm.state.sublimeMark) cm.state.sublimeMark.clear(); + cm.state.sublimeMark = cm.setBookmark(cm.getCursor()); + }; + cmds.selectToSublimeMark = function(cm) { + var found = cm.state.sublimeMark && cm.state.sublimeMark.find(); + if (found) cm.setSelection(cm.getCursor(), found); + }; + cmds.deleteToSublimeMark = function(cm) { + var found = cm.state.sublimeMark && cm.state.sublimeMark.find(); + if (found) { + var from = cm.getCursor(), to = found; + if (CodeMirror.cmpPos(from, to) > 0) { var tmp = to; to = from; from = tmp; } + cm.state.sublimeKilled = cm.getRange(from, to); + cm.replaceRange("", from, to); + } + }; + cmds.swapWithSublimeMark = function(cm) { + var found = cm.state.sublimeMark && cm.state.sublimeMark.find(); + if (found) { + cm.state.sublimeMark.clear(); + cm.state.sublimeMark = cm.setBookmark(cm.getCursor()); + cm.setCursor(found); + } + }; + cmds.sublimeYank = function(cm) { + if (cm.state.sublimeKilled != null) + cm.replaceSelection(cm.state.sublimeKilled, null, "paste"); + }; + + cmds.showInCenter = function(cm) { + var pos = cm.cursorCoords(null, "local"); + cm.scrollTo(null, (pos.top + pos.bottom) / 2 - cm.getScrollInfo().clientHeight / 2); + }; + + function getTarget(cm) { + var from = cm.getCursor("from"), to = cm.getCursor("to"); + if (CodeMirror.cmpPos(from, to) == 0) { + var word = wordAt(cm, from); + if (!word.word) return; + from = word.from; + to = word.to; + } + return {from: from, to: to, query: cm.getRange(from, to), word: word}; + } + + function findAndGoTo(cm, forward) { + var target = getTarget(cm); + if (!target) return; + var query = target.query; + var cur = cm.getSearchCursor(query, forward ? target.to : target.from); + + if (forward ? cur.findNext() : cur.findPrevious()) { + cm.setSelection(cur.from(), cur.to()); + } else { + cur = cm.getSearchCursor(query, forward ? Pos(cm.firstLine(), 0) + : cm.clipPos(Pos(cm.lastLine()))); + if (forward ? cur.findNext() : cur.findPrevious()) + cm.setSelection(cur.from(), cur.to()); + else if (target.word) + cm.setSelection(target.from, target.to); + } + }; + cmds.findUnder = function(cm) { findAndGoTo(cm, true); }; + cmds.findUnderPrevious = function(cm) { findAndGoTo(cm,false); }; + cmds.findAllUnder = function(cm) { + var target = getTarget(cm); + if (!target) return; + var cur = cm.getSearchCursor(target.query); + var matches = []; + var primaryIndex = -1; + while (cur.findNext()) { + matches.push({anchor: cur.from(), head: cur.to()}); + if (cur.from().line <= target.from.line && cur.from().ch <= target.from.ch) + primaryIndex++; + } + cm.setSelections(matches, primaryIndex); + }; + + + var keyMap = CodeMirror.keyMap; + keyMap.macSublime = { + "Cmd-Left": "goLineStartSmart", + "Shift-Tab": "indentLess", + "Shift-Ctrl-K": "deleteLine", + "Alt-Q": "wrapLines", + "Ctrl-Left": "goSubwordLeft", + "Ctrl-Right": "goSubwordRight", + "Ctrl-Alt-Up": "scrollLineUp", + "Ctrl-Alt-Down": "scrollLineDown", + "Cmd-L": "selectLine", + "Shift-Cmd-L": "splitSelectionByLine", + "Esc": "singleSelectionTop", + "Cmd-Enter": "insertLineAfter", + "Shift-Cmd-Enter": "insertLineBefore", + "Cmd-D": "selectNextOccurrence", + "Shift-Cmd-Space": "selectScope", + "Shift-Cmd-M": "selectBetweenBrackets", + "Cmd-M": "goToBracket", + "Cmd-Ctrl-Up": "swapLineUp", + "Cmd-Ctrl-Down": "swapLineDown", + "Cmd-/": "toggleCommentIndented", + "Cmd-J": "joinLines", + "Shift-Cmd-D": "duplicateLine", + "F9": "sortLines", + "Cmd-F9": "sortLinesInsensitive", + "F2": "nextBookmark", + "Shift-F2": "prevBookmark", + "Cmd-F2": "toggleBookmark", + "Shift-Cmd-F2": "clearBookmarks", + "Alt-F2": "selectBookmarks", + "Backspace": "smartBackspace", + "Cmd-K Cmd-K": "delLineRight", + "Cmd-K Cmd-U": "upcaseAtCursor", + "Cmd-K Cmd-L": "downcaseAtCursor", + "Cmd-K Cmd-Space": "setSublimeMark", + "Cmd-K Cmd-A": "selectToSublimeMark", + "Cmd-K Cmd-W": "deleteToSublimeMark", + "Cmd-K Cmd-X": "swapWithSublimeMark", + "Cmd-K Cmd-Y": "sublimeYank", + "Cmd-K Cmd-C": "showInCenter", + "Cmd-K Cmd-G": "clearBookmarks", + "Cmd-K Cmd-Backspace": "delLineLeft", + "Cmd-K Cmd-0": "unfoldAll", + "Cmd-K Cmd-J": "unfoldAll", + "Ctrl-Shift-Up": "addCursorToPrevLine", + "Ctrl-Shift-Down": "addCursorToNextLine", + "Cmd-F3": "findUnder", + "Shift-Cmd-F3": "findUnderPrevious", + "Alt-F3": "findAllUnder", + "Shift-Cmd-[": "fold", + "Shift-Cmd-]": "unfold", + "Cmd-I": "findIncremental", + "Shift-Cmd-I": "findIncrementalReverse", + "Cmd-H": "replace", + "F3": "findNext", + "Shift-F3": "findPrev", + "fallthrough": "macDefault" + }; + CodeMirror.normalizeKeyMap(keyMap.macSublime); + + keyMap.pcSublime = { + "Shift-Tab": "indentLess", + "Shift-Ctrl-K": "deleteLine", + "Alt-Q": "wrapLines", + "Ctrl-T": "transposeChars", + "Alt-Left": "goSubwordLeft", + "Alt-Right": "goSubwordRight", + "Ctrl-Up": "scrollLineUp", + "Ctrl-Down": "scrollLineDown", + "Ctrl-L": "selectLine", + "Shift-Ctrl-L": "splitSelectionByLine", + "Esc": "singleSelectionTop", + "Ctrl-Enter": "insertLineAfter", + "Shift-Ctrl-Enter": "insertLineBefore", + "Ctrl-D": "selectNextOccurrence", + "Shift-Ctrl-Space": "selectScope", + "Shift-Ctrl-M": "selectBetweenBrackets", + "Ctrl-M": "goToBracket", + "Shift-Ctrl-Up": "swapLineUp", + "Shift-Ctrl-Down": "swapLineDown", + "Ctrl-/": "toggleCommentIndented", + "Ctrl-J": "joinLines", + "Shift-Ctrl-D": "duplicateLine", + "F9": "sortLines", + "Ctrl-F9": "sortLinesInsensitive", + "F2": "nextBookmark", + "Shift-F2": "prevBookmark", + "Ctrl-F2": "toggleBookmark", + "Shift-Ctrl-F2": "clearBookmarks", + "Alt-F2": "selectBookmarks", + "Backspace": "smartBackspace", + "Ctrl-K Ctrl-K": "delLineRight", + "Ctrl-K Ctrl-U": "upcaseAtCursor", + "Ctrl-K Ctrl-L": "downcaseAtCursor", + "Ctrl-K Ctrl-Space": "setSublimeMark", + "Ctrl-K Ctrl-A": "selectToSublimeMark", + "Ctrl-K Ctrl-W": "deleteToSublimeMark", + "Ctrl-K Ctrl-X": "swapWithSublimeMark", + "Ctrl-K Ctrl-Y": "sublimeYank", + "Ctrl-K Ctrl-C": "showInCenter", + "Ctrl-K Ctrl-G": "clearBookmarks", + "Ctrl-K Ctrl-Backspace": "delLineLeft", + "Ctrl-K Ctrl-0": "unfoldAll", + "Ctrl-K Ctrl-J": "unfoldAll", + "Ctrl-Alt-Up": "addCursorToPrevLine", + "Ctrl-Alt-Down": "addCursorToNextLine", + "Ctrl-F3": "findUnder", + "Shift-Ctrl-F3": "findUnderPrevious", + "Alt-F3": "findAllUnder", + "Shift-Ctrl-[": "fold", + "Shift-Ctrl-]": "unfold", + "Ctrl-I": "findIncremental", + "Shift-Ctrl-I": "findIncrementalReverse", + "Ctrl-H": "replace", + "F3": "findNext", + "Shift-F3": "findPrev", + "fallthrough": "pcDefault" + }; + CodeMirror.normalizeKeyMap(keyMap.pcSublime); + + var mac = keyMap.default == keyMap.macDefault; + keyMap.sublime = mac ? keyMap.macSublime : keyMap.pcSublime; + }); + + +/***/ }), +/* 22 */ +/***/ (function(module, exports, __webpack_require__) { + + // CodeMirror, copyright (c) by Marijn Haverbeke and others + // Distributed under an MIT license: http://codemirror.net/LICENSE + + (function(mod) { + if (true) // CommonJS + mod(__webpack_require__(2)); + else if (typeof define == "function" && define.amd) // AMD + define(["../../lib/codemirror"], mod); + else // Plain browser env + mod(CodeMirror); + })(function(CodeMirror) { + "use strict"; + + function doFold(cm, pos, options, force) { + if (options && options.call) { + var finder = options; + options = null; + } else { + var finder = getOption(cm, options, "rangeFinder"); + } + if (typeof pos == "number") pos = CodeMirror.Pos(pos, 0); + var minSize = getOption(cm, options, "minFoldSize"); + + function getRange(allowFolded) { + var range = finder(cm, pos); + if (!range || range.to.line - range.from.line < minSize) return null; + var marks = cm.findMarksAt(range.from); + for (var i = 0; i < marks.length; ++i) { + if (marks[i].__isFold && force !== "fold") { + if (!allowFolded) return null; + range.cleared = true; + marks[i].clear(); + } + } + return range; + } + + var range = getRange(true); + if (getOption(cm, options, "scanUp")) while (!range && pos.line > cm.firstLine()) { + pos = CodeMirror.Pos(pos.line - 1, 0); + range = getRange(false); + } + if (!range || range.cleared || force === "unfold") return; + + var myWidget = makeWidget(cm, options); + CodeMirror.on(myWidget, "mousedown", function(e) { + myRange.clear(); + CodeMirror.e_preventDefault(e); + }); + var myRange = cm.markText(range.from, range.to, { + replacedWith: myWidget, + clearOnEnter: getOption(cm, options, "clearOnEnter"), + __isFold: true + }); + myRange.on("clear", function(from, to) { + CodeMirror.signal(cm, "unfold", cm, from, to); + }); + CodeMirror.signal(cm, "fold", cm, range.from, range.to); + } + + function makeWidget(cm, options) { + var widget = getOption(cm, options, "widget"); + if (typeof widget == "string") { + var text = document.createTextNode(widget); + widget = document.createElement("span"); + widget.appendChild(text); + widget.className = "CodeMirror-foldmarker"; + } else if (widget) { + widget = widget.cloneNode(true) + } + return widget; + } + + // Clumsy backwards-compatible interface + CodeMirror.newFoldFunction = function(rangeFinder, widget) { + return function(cm, pos) { doFold(cm, pos, {rangeFinder: rangeFinder, widget: widget}); }; + }; + + // New-style interface + CodeMirror.defineExtension("foldCode", function(pos, options, force) { + doFold(this, pos, options, force); + }); + + CodeMirror.defineExtension("isFolded", function(pos) { + var marks = this.findMarksAt(pos); + for (var i = 0; i < marks.length; ++i) + if (marks[i].__isFold) return true; + }); + + CodeMirror.commands.toggleFold = function(cm) { + cm.foldCode(cm.getCursor()); + }; + CodeMirror.commands.fold = function(cm) { + cm.foldCode(cm.getCursor(), null, "fold"); + }; + CodeMirror.commands.unfold = function(cm) { + cm.foldCode(cm.getCursor(), null, "unfold"); + }; + CodeMirror.commands.foldAll = function(cm) { + cm.operation(function() { + for (var i = cm.firstLine(), e = cm.lastLine(); i <= e; i++) + cm.foldCode(CodeMirror.Pos(i, 0), null, "fold"); + }); + }; + CodeMirror.commands.unfoldAll = function(cm) { + cm.operation(function() { + for (var i = cm.firstLine(), e = cm.lastLine(); i <= e; i++) + cm.foldCode(CodeMirror.Pos(i, 0), null, "unfold"); + }); + }; + + CodeMirror.registerHelper("fold", "combine", function() { + var funcs = Array.prototype.slice.call(arguments, 0); + return function(cm, start) { + for (var i = 0; i < funcs.length; ++i) { + var found = funcs[i](cm, start); + if (found) return found; + } + }; + }); + + CodeMirror.registerHelper("fold", "auto", function(cm, start) { + var helpers = cm.getHelpers(start, "fold"); + for (var i = 0; i < helpers.length; i++) { + var cur = helpers[i](cm, start); + if (cur) return cur; + } + }); + + var defaultOptions = { + rangeFinder: CodeMirror.fold.auto, + widget: "\u2194", + minFoldSize: 0, + scanUp: false, + clearOnEnter: true + }; + + CodeMirror.defineOption("foldOptions", null); + + function getOption(cm, options, name) { + if (options && options[name] !== undefined) + return options[name]; + var editorOptions = cm.options.foldOptions; + if (editorOptions && editorOptions[name] !== undefined) + return editorOptions[name]; + return defaultOptions[name]; + } + + CodeMirror.defineExtension("foldOption", function(options, name) { + return getOption(this, options, name); + }); + }); + + +/***/ }), +/* 23 */ +/***/ (function(module, exports, __webpack_require__) { + + // CodeMirror, copyright (c) by Marijn Haverbeke and others + // Distributed under an MIT license: http://codemirror.net/LICENSE + + (function(mod) { + if (true) // CommonJS + mod(__webpack_require__(2)); + else if (typeof define == "function" && define.amd) // AMD + define(["../../lib/codemirror"], mod); + else // Plain browser env + mod(CodeMirror); + })(function(CodeMirror) { + "use strict"; + + CodeMirror.registerHelper("fold", "brace", function(cm, start) { + var line = start.line, lineText = cm.getLine(line); + var tokenType; + + function findOpening(openCh) { + for (var at = start.ch, pass = 0;;) { + var found = at <= 0 ? -1 : lineText.lastIndexOf(openCh, at - 1); + if (found == -1) { + if (pass == 1) break; + pass = 1; + at = lineText.length; + continue; + } + if (pass == 1 && found < start.ch) break; + tokenType = cm.getTokenTypeAt(CodeMirror.Pos(line, found + 1)); + if (!/^(comment|string)/.test(tokenType)) return found + 1; + at = found - 1; + } + } + + var startToken = "{", endToken = "}", startCh = findOpening("{"); + if (startCh == null) { + startToken = "[", endToken = "]"; + startCh = findOpening("["); + } + + if (startCh == null) return; + var count = 1, lastLine = cm.lastLine(), end, endCh; + outer: for (var i = line; i <= lastLine; ++i) { + var text = cm.getLine(i), pos = i == line ? startCh : 0; + for (;;) { + var nextOpen = text.indexOf(startToken, pos), nextClose = text.indexOf(endToken, pos); + if (nextOpen < 0) nextOpen = text.length; + if (nextClose < 0) nextClose = text.length; + pos = Math.min(nextOpen, nextClose); + if (pos == text.length) break; + if (cm.getTokenTypeAt(CodeMirror.Pos(i, pos + 1)) == tokenType) { + if (pos == nextOpen) ++count; + else if (!--count) { end = i; endCh = pos; break outer; } + } + ++pos; + } + } + if (end == null || line == end && endCh == startCh) return; + return {from: CodeMirror.Pos(line, startCh), + to: CodeMirror.Pos(end, endCh)}; + }); + + CodeMirror.registerHelper("fold", "import", function(cm, start) { + function hasImport(line) { + if (line < cm.firstLine() || line > cm.lastLine()) return null; + var start = cm.getTokenAt(CodeMirror.Pos(line, 1)); + if (!/\S/.test(start.string)) start = cm.getTokenAt(CodeMirror.Pos(line, start.end + 1)); + if (start.type != "keyword" || start.string != "import") return null; + // Now find closing semicolon, return its position + for (var i = line, e = Math.min(cm.lastLine(), line + 10); i <= e; ++i) { + var text = cm.getLine(i), semi = text.indexOf(";"); + if (semi != -1) return {startCh: start.end, end: CodeMirror.Pos(i, semi)}; + } + } + + var startLine = start.line, has = hasImport(startLine), prev; + if (!has || hasImport(startLine - 1) || ((prev = hasImport(startLine - 2)) && prev.end.line == startLine - 1)) + return null; + for (var end = has.end;;) { + var next = hasImport(end.line + 1); + if (next == null) break; + end = next.end; + } + return {from: cm.clipPos(CodeMirror.Pos(startLine, has.startCh + 1)), to: end}; + }); + + CodeMirror.registerHelper("fold", "include", function(cm, start) { + function hasInclude(line) { + if (line < cm.firstLine() || line > cm.lastLine()) return null; + var start = cm.getTokenAt(CodeMirror.Pos(line, 1)); + if (!/\S/.test(start.string)) start = cm.getTokenAt(CodeMirror.Pos(line, start.end + 1)); + if (start.type == "meta" && start.string.slice(0, 8) == "#include") return start.start + 8; + } + + var startLine = start.line, has = hasInclude(startLine); + if (has == null || hasInclude(startLine - 1) != null) return null; + for (var end = startLine;;) { + var next = hasInclude(end + 1); + if (next == null) break; + ++end; + } + return {from: CodeMirror.Pos(startLine, has + 1), + to: cm.clipPos(CodeMirror.Pos(end))}; + }); + + }); + + +/***/ }), +/* 24 */ +/***/ (function(module, exports, __webpack_require__) { + + // CodeMirror, copyright (c) by Marijn Haverbeke and others + // Distributed under an MIT license: http://codemirror.net/LICENSE + + (function(mod) { + if (true) // CommonJS + mod(__webpack_require__(2)); + else if (typeof define == "function" && define.amd) // AMD + define(["../../lib/codemirror"], mod); + else // Plain browser env + mod(CodeMirror); + })(function(CodeMirror) { + "use strict"; + + CodeMirror.registerGlobalHelper("fold", "comment", function(mode) { + return mode.blockCommentStart && mode.blockCommentEnd; + }, function(cm, start) { + var mode = cm.getModeAt(start), startToken = mode.blockCommentStart, endToken = mode.blockCommentEnd; + if (!startToken || !endToken) return; + var line = start.line, lineText = cm.getLine(line); + + var startCh; + for (var at = start.ch, pass = 0;;) { + var found = at <= 0 ? -1 : lineText.lastIndexOf(startToken, at - 1); + if (found == -1) { + if (pass == 1) return; + pass = 1; + at = lineText.length; + continue; + } + if (pass == 1 && found < start.ch) return; + if (/comment/.test(cm.getTokenTypeAt(CodeMirror.Pos(line, found + 1))) && + (found == 0 || lineText.slice(found - endToken.length, found) == endToken || + !/comment/.test(cm.getTokenTypeAt(CodeMirror.Pos(line, found))))) { + startCh = found + startToken.length; + break; + } + at = found - 1; + } + + var depth = 1, lastLine = cm.lastLine(), end, endCh; + outer: for (var i = line; i <= lastLine; ++i) { + var text = cm.getLine(i), pos = i == line ? startCh : 0; + for (;;) { + var nextOpen = text.indexOf(startToken, pos), nextClose = text.indexOf(endToken, pos); + if (nextOpen < 0) nextOpen = text.length; + if (nextClose < 0) nextClose = text.length; + pos = Math.min(nextOpen, nextClose); + if (pos == text.length) break; + if (pos == nextOpen) ++depth; + else if (!--depth) { end = i; endCh = pos; break outer; } + ++pos; + } + } + if (end == null || line == end && endCh == startCh) return; + return {from: CodeMirror.Pos(line, startCh), + to: CodeMirror.Pos(end, endCh)}; + }); + + }); + + +/***/ }), +/* 25 */ +/***/ (function(module, exports, __webpack_require__) { + + // CodeMirror, copyright (c) by Marijn Haverbeke and others + // Distributed under an MIT license: http://codemirror.net/LICENSE + + (function(mod) { + if (true) // CommonJS + mod(__webpack_require__(2)); + else if (typeof define == "function" && define.amd) // AMD + define(["../../lib/codemirror"], mod); + else // Plain browser env + mod(CodeMirror); + })(function(CodeMirror) { + "use strict"; + + var Pos = CodeMirror.Pos; + function cmp(a, b) { return a.line - b.line || a.ch - b.ch; } + + var nameStartChar = "A-Z_a-z\\u00C0-\\u00D6\\u00D8-\\u00F6\\u00F8-\\u02FF\\u0370-\\u037D\\u037F-\\u1FFF\\u200C-\\u200D\\u2070-\\u218F\\u2C00-\\u2FEF\\u3001-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFFD"; + var nameChar = nameStartChar + "\-\:\.0-9\\u00B7\\u0300-\\u036F\\u203F-\\u2040"; + var xmlTagStart = new RegExp("<(/?)([" + nameStartChar + "][" + nameChar + "]*)", "g"); + + function Iter(cm, line, ch, range) { + this.line = line; this.ch = ch; + this.cm = cm; this.text = cm.getLine(line); + this.min = range ? Math.max(range.from, cm.firstLine()) : cm.firstLine(); + this.max = range ? Math.min(range.to - 1, cm.lastLine()) : cm.lastLine(); + } + + function tagAt(iter, ch) { + var type = iter.cm.getTokenTypeAt(Pos(iter.line, ch)); + return type && /\btag\b/.test(type); + } + + function nextLine(iter) { + if (iter.line >= iter.max) return; + iter.ch = 0; + iter.text = iter.cm.getLine(++iter.line); + return true; + } + function prevLine(iter) { + if (iter.line <= iter.min) return; + iter.text = iter.cm.getLine(--iter.line); + iter.ch = iter.text.length; + return true; + } + + function toTagEnd(iter) { + for (;;) { + var gt = iter.text.indexOf(">", iter.ch); + if (gt == -1) { if (nextLine(iter)) continue; else return; } + if (!tagAt(iter, gt + 1)) { iter.ch = gt + 1; continue; } + var lastSlash = iter.text.lastIndexOf("/", gt); + var selfClose = lastSlash > -1 && !/\S/.test(iter.text.slice(lastSlash + 1, gt)); + iter.ch = gt + 1; + return selfClose ? "selfClose" : "regular"; + } + } + function toTagStart(iter) { + for (;;) { + var lt = iter.ch ? iter.text.lastIndexOf("<", iter.ch - 1) : -1; + if (lt == -1) { if (prevLine(iter)) continue; else return; } + if (!tagAt(iter, lt + 1)) { iter.ch = lt; continue; } + xmlTagStart.lastIndex = lt; + iter.ch = lt; + var match = xmlTagStart.exec(iter.text); + if (match && match.index == lt) return match; + } + } + + function toNextTag(iter) { + for (;;) { + xmlTagStart.lastIndex = iter.ch; + var found = xmlTagStart.exec(iter.text); + if (!found) { if (nextLine(iter)) continue; else return; } + if (!tagAt(iter, found.index + 1)) { iter.ch = found.index + 1; continue; } + iter.ch = found.index + found[0].length; + return found; + } + } + function toPrevTag(iter) { + for (;;) { + var gt = iter.ch ? iter.text.lastIndexOf(">", iter.ch - 1) : -1; + if (gt == -1) { if (prevLine(iter)) continue; else return; } + if (!tagAt(iter, gt + 1)) { iter.ch = gt; continue; } + var lastSlash = iter.text.lastIndexOf("/", gt); + var selfClose = lastSlash > -1 && !/\S/.test(iter.text.slice(lastSlash + 1, gt)); + iter.ch = gt + 1; + return selfClose ? "selfClose" : "regular"; + } + } + + function findMatchingClose(iter, tag) { + var stack = []; + for (;;) { + var next = toNextTag(iter), end, startLine = iter.line, startCh = iter.ch - (next ? next[0].length : 0); + if (!next || !(end = toTagEnd(iter))) return; + if (end == "selfClose") continue; + if (next[1]) { // closing tag + for (var i = stack.length - 1; i >= 0; --i) if (stack[i] == next[2]) { + stack.length = i; + break; + } + if (i < 0 && (!tag || tag == next[2])) return { + tag: next[2], + from: Pos(startLine, startCh), + to: Pos(iter.line, iter.ch) + }; + } else { // opening tag + stack.push(next[2]); + } + } + } + function findMatchingOpen(iter, tag) { + var stack = []; + for (;;) { + var prev = toPrevTag(iter); + if (!prev) return; + if (prev == "selfClose") { toTagStart(iter); continue; } + var endLine = iter.line, endCh = iter.ch; + var start = toTagStart(iter); + if (!start) return; + if (start[1]) { // closing tag + stack.push(start[2]); + } else { // opening tag + for (var i = stack.length - 1; i >= 0; --i) if (stack[i] == start[2]) { + stack.length = i; + break; + } + if (i < 0 && (!tag || tag == start[2])) return { + tag: start[2], + from: Pos(iter.line, iter.ch), + to: Pos(endLine, endCh) + }; + } + } + } + + CodeMirror.registerHelper("fold", "xml", function(cm, start) { + var iter = new Iter(cm, start.line, 0); + for (;;) { + var openTag = toNextTag(iter) + if (!openTag || iter.line != start.line) return + var end = toTagEnd(iter) + if (!end) return + if (!openTag[1] && end != "selfClose") { + var startPos = Pos(iter.line, iter.ch); + var endPos = findMatchingClose(iter, openTag[2]); + return endPos && cmp(endPos.from, startPos) > 0 ? {from: startPos, to: endPos.from} : null + } + } + }); + CodeMirror.findMatchingTag = function(cm, pos, range) { + var iter = new Iter(cm, pos.line, pos.ch, range); + if (iter.text.indexOf(">") == -1 && iter.text.indexOf("<") == -1) return; + var end = toTagEnd(iter), to = end && Pos(iter.line, iter.ch); + var start = end && toTagStart(iter); + if (!end || !start || cmp(iter, pos) > 0) return; + var here = {from: Pos(iter.line, iter.ch), to: to, tag: start[2]}; + if (end == "selfClose") return {open: here, close: null, at: "open"}; + + if (start[1]) { // closing tag + return {open: findMatchingOpen(iter, start[2]), close: here, at: "close"}; + } else { // opening tag + iter = new Iter(cm, to.line, to.ch, range); + return {open: here, close: findMatchingClose(iter, start[2]), at: "open"}; + } + }; + + CodeMirror.findEnclosingTag = function(cm, pos, range, tag) { + var iter = new Iter(cm, pos.line, pos.ch, range); + for (;;) { + var open = findMatchingOpen(iter, tag); + if (!open) break; + var forward = new Iter(cm, pos.line, pos.ch, range); + var close = findMatchingClose(forward, open.tag); + if (close) return {open: open, close: close}; + } + }; + + // Used by addon/edit/closetag.js + CodeMirror.scanForClosingTag = function(cm, pos, name, end) { + var iter = new Iter(cm, pos.line, pos.ch, end ? {from: 0, to: end} : null); + return findMatchingClose(iter, name); + }; + }); + + +/***/ }), +/* 26 */ +/***/ (function(module, exports, __webpack_require__) { + + // CodeMirror, copyright (c) by Marijn Haverbeke and others + // Distributed under an MIT license: http://codemirror.net/LICENSE + + (function(mod) { + if (true) // CommonJS + mod(__webpack_require__(2), __webpack_require__(22)); + else if (typeof define == "function" && define.amd) // AMD + define(["../../lib/codemirror", "./foldcode"], mod); + else // Plain browser env + mod(CodeMirror); + })(function(CodeMirror) { + "use strict"; + + CodeMirror.defineOption("foldGutter", false, function(cm, val, old) { + if (old && old != CodeMirror.Init) { + cm.clearGutter(cm.state.foldGutter.options.gutter); + cm.state.foldGutter = null; + cm.off("gutterClick", onGutterClick); + cm.off("change", onChange); + cm.off("viewportChange", onViewportChange); + cm.off("fold", onFold); + cm.off("unfold", onFold); + cm.off("swapDoc", onChange); + } + if (val) { + cm.state.foldGutter = new State(parseOptions(val)); + updateInViewport(cm); + cm.on("gutterClick", onGutterClick); + cm.on("change", onChange); + cm.on("viewportChange", onViewportChange); + cm.on("fold", onFold); + cm.on("unfold", onFold); + cm.on("swapDoc", onChange); + } + }); + + var Pos = CodeMirror.Pos; + + function State(options) { + this.options = options; + this.from = this.to = 0; + } + + function parseOptions(opts) { + if (opts === true) opts = {}; + if (opts.gutter == null) opts.gutter = "CodeMirror-foldgutter"; + if (opts.indicatorOpen == null) opts.indicatorOpen = "CodeMirror-foldgutter-open"; + if (opts.indicatorFolded == null) opts.indicatorFolded = "CodeMirror-foldgutter-folded"; + return opts; + } + + function isFolded(cm, line) { + var marks = cm.findMarks(Pos(line, 0), Pos(line + 1, 0)); + for (var i = 0; i < marks.length; ++i) + if (marks[i].__isFold && marks[i].find().from.line == line) return marks[i]; + } + + function marker(spec) { + if (typeof spec == "string") { + var elt = document.createElement("div"); + elt.className = spec + " CodeMirror-guttermarker-subtle"; + return elt; + } else { + return spec.cloneNode(true); + } + } + + function updateFoldInfo(cm, from, to) { + var opts = cm.state.foldGutter.options, cur = from; + var minSize = cm.foldOption(opts, "minFoldSize"); + var func = cm.foldOption(opts, "rangeFinder"); + cm.eachLine(from, to, function(line) { + var mark = null; + if (isFolded(cm, cur)) { + mark = marker(opts.indicatorFolded); + } else { + var pos = Pos(cur, 0); + var range = func && func(cm, pos); + if (range && range.to.line - range.from.line >= minSize) + mark = marker(opts.indicatorOpen); + } + cm.setGutterMarker(line, opts.gutter, mark); + ++cur; + }); + } + + function updateInViewport(cm) { + var vp = cm.getViewport(), state = cm.state.foldGutter; + if (!state) return; + cm.operation(function() { + updateFoldInfo(cm, vp.from, vp.to); + }); + state.from = vp.from; state.to = vp.to; + } + + function onGutterClick(cm, line, gutter) { + var state = cm.state.foldGutter; + if (!state) return; + var opts = state.options; + if (gutter != opts.gutter) return; + var folded = isFolded(cm, line); + if (folded) folded.clear(); + else cm.foldCode(Pos(line, 0), opts.rangeFinder); + } + + function onChange(cm) { + var state = cm.state.foldGutter; + if (!state) return; + var opts = state.options; + state.from = state.to = 0; + clearTimeout(state.changeUpdate); + state.changeUpdate = setTimeout(function() { updateInViewport(cm); }, opts.foldOnChangeTimeSpan || 600); + } + + function onViewportChange(cm) { + var state = cm.state.foldGutter; + if (!state) return; + var opts = state.options; + clearTimeout(state.changeUpdate); + state.changeUpdate = setTimeout(function() { + var vp = cm.getViewport(); + if (state.from == state.to || vp.from - state.to > 20 || state.from - vp.to > 20) { + updateInViewport(cm); + } else { + cm.operation(function() { + if (vp.from < state.from) { + updateFoldInfo(cm, vp.from, state.from); + state.from = vp.from; + } + if (vp.to > state.to) { + updateFoldInfo(cm, state.to, vp.to); + state.to = vp.to; + } + }); + } + }, opts.updateViewportTimeSpan || 400); + } + + function onFold(cm, from) { + var state = cm.state.foldGutter; + if (!state) return; + var line = from.line; + if (line >= state.from && line < state.to) + updateFoldInfo(cm, line, line + 1); + } + }); + + +/***/ }), +/* 27 */ +/***/ (function(module, exports, __webpack_require__) { + + // CodeMirror, copyright (c) by Marijn Haverbeke and others + // Distributed under an MIT license: http://codemirror.net/LICENSE + + (function(mod) { + if (true) // CommonJS + mod(__webpack_require__(2)); + else if (typeof define == "function" && define.amd) // AMD + define(["../../lib/codemirror"], mod); + else // Plain browser env + mod(CodeMirror); + })(function(CodeMirror) { + "use strict"; + + CodeMirror.runMode = function(string, modespec, callback, options) { + var mode = CodeMirror.getMode(CodeMirror.defaults, modespec); + var ie = /MSIE \d/.test(navigator.userAgent); + var ie_lt9 = ie && (document.documentMode == null || document.documentMode < 9); + + if (callback.appendChild) { + var tabSize = (options && options.tabSize) || CodeMirror.defaults.tabSize; + var node = callback, col = 0; + node.innerHTML = ""; + callback = function(text, style) { + if (text == "\n") { + // Emitting LF or CRLF on IE8 or earlier results in an incorrect display. + // Emitting a carriage return makes everything ok. + node.appendChild(document.createTextNode(ie_lt9 ? '\r' : text)); + col = 0; + return; + } + var content = ""; + // replace tabs + for (var pos = 0;;) { + var idx = text.indexOf("\t", pos); + if (idx == -1) { + content += text.slice(pos); + col += text.length - pos; + break; + } else { + col += idx - pos; + content += text.slice(pos, idx); + var size = tabSize - col % tabSize; + col += size; + for (var i = 0; i < size; ++i) content += " "; + pos = idx + 1; + } + } + + if (style) { + var sp = node.appendChild(document.createElement("span")); + sp.className = "cm-" + style.replace(/ +/g, " cm-"); + sp.appendChild(document.createTextNode(content)); + } else { + node.appendChild(document.createTextNode(content)); + } + }; + } + + var lines = CodeMirror.splitLines(string), state = (options && options.state) || CodeMirror.startState(mode); + for (var i = 0, e = lines.length; i < e; ++i) { + if (i) callback("\n"); + var stream = new CodeMirror.StringStream(lines[i]); + if (!stream.string && mode.blankLine) mode.blankLine(state); + while (!stream.eol()) { + var style = mode.token(stream, state); + callback(stream.current(), style, i, stream.start, state); + stream.start = stream.pos; + } + } + }; + + }); + +/***/ }) +/******/ ]); \ No newline at end of file diff --git a/devtools/client/sourceeditor/webpack.config.js b/devtools/client/sourceeditor/webpack.config.js index f0ed8068adef..0ec45fa73a49 100644 --- a/devtools/client/sourceeditor/webpack.config.js +++ b/devtools/client/sourceeditor/webpack.config.js @@ -32,6 +32,7 @@ module.exports = [{ "./codemirror/addon/fold/comment-fold.js", "./codemirror/addon/fold/xml-fold.js", "./codemirror/addon/fold/foldgutter.js", + "./codemirror/addon/runmode/runmode.js", "./codemirror/lib/codemirror.js", ], output: { diff --git a/devtools/server/actors/object/previewers.js b/devtools/server/actors/object/previewers.js index d535fc09a688..1444774b4292 100644 --- a/devtools/server/actors/object/previewers.js +++ b/devtools/server/actors/object/previewers.js @@ -613,7 +613,7 @@ previewers.Object = [ isConnected: rawObj.isConnected === true, }; - if (rawObj instanceof Ci.nsIDOMDocument && rawObj.location) { + if (rawObj.nodeType == rawObj.DOCUMENT_NODE && rawObj.location) { preview.location = hooks.createValueGrip(rawObj.location.href); } else if (obj.class == "DocumentFragment") { preview.childNodesLength = rawObj.childNodes.length; diff --git a/docshell/base/nsDocShell.cpp b/docshell/base/nsDocShell.cpp index cd44f0de8455..d23de893a8ae 100644 --- a/docshell/base/nsDocShell.cpp +++ b/docshell/base/nsDocShell.cpp @@ -81,7 +81,6 @@ #include "nsIDocShellTreeOwner.h" #include "nsIDocument.h" #include "nsIDocumentLoaderFactory.h" -#include "nsIDOMDocument.h" #include "nsIDOMNode.h" #include "nsIDOMStorage.h" #include "nsIDOMWindow.h" @@ -552,12 +551,6 @@ nsDocShell::GetInterface(const nsIID& aIID, void** aSink) aIID.Equals(NS_GET_IID(nsIDOMWindow))) && NS_SUCCEEDED(EnsureScriptEnvironment())) { return mScriptGlobal->QueryInterface(aIID, aSink); - } else if (aIID.Equals(NS_GET_IID(nsIDOMDocument)) && - NS_SUCCEEDED(EnsureContentViewer())) { - nsCOMPtr doc = - do_QueryInterface(mContentViewer->GetDocument()); - doc.forget(aSink); - return *aSink ? NS_OK : NS_NOINTERFACE; } else if (aIID.Equals(NS_GET_IID(nsIDocument)) && NS_SUCCEEDED(EnsureContentViewer())) { nsCOMPtr doc = mContentViewer->GetDocument(); diff --git a/dom/base/nsDocument.cpp b/dom/base/nsDocument.cpp index 13aa29b893b1..fabe45fa1f21 100644 --- a/dom/base/nsDocument.cpp +++ b/dom/base/nsDocument.cpp @@ -1730,7 +1730,6 @@ NS_INTERFACE_TABLE_HEAD(nsDocument) NS_INTERFACE_TABLE_ENTRY_AMBIGUOUS(nsDocument, nsISupports, nsINode) NS_INTERFACE_TABLE_ENTRY(nsDocument, nsINode) NS_INTERFACE_TABLE_ENTRY(nsDocument, nsIDocument) - NS_INTERFACE_TABLE_ENTRY(nsDocument, nsIDOMDocument) NS_INTERFACE_TABLE_ENTRY(nsDocument, nsIDOMNode) NS_INTERFACE_TABLE_ENTRY(nsDocument, nsIScriptObjectPrincipal) NS_INTERFACE_TABLE_ENTRY(nsDocument, mozilla::dom::EventTarget) diff --git a/dom/base/nsDocument.h b/dom/base/nsDocument.h index 577d2a731e76..4867bff1aeb7 100644 --- a/dom/base/nsDocument.h +++ b/dom/base/nsDocument.h @@ -21,7 +21,7 @@ #include "nsWeakPtr.h" #include "nsTArray.h" #include "nsIdentifierMapEntry.h" -#include "nsIDOMDocument.h" +#include "nsIDOMNode.h" #include "nsStubDocumentObserver.h" #include "nsIScriptGlobalObject.h" #include "nsIContent.h" @@ -130,7 +130,7 @@ private: // Base class for our document implementations. class nsDocument : public nsIDocument, - public nsIDOMDocument, + public nsIDOMNode, public nsSupportsWeakReference, public nsIScriptObjectPrincipal, public nsIRadioGroupContainer, diff --git a/dom/base/test/unit/head_xml.js b/dom/base/test/unit/head_xml.js index 213cd31f31ed..0ed4b5e8a8a0 100644 --- a/dom/base/test/unit/head_xml.js +++ b/dom/base/test/unit/head_xml.js @@ -12,7 +12,6 @@ const nsIProperties = I.nsIProperties; const nsIFileInputStream = I.nsIFileInputStream; const nsIInputStream = I.nsIInputStream; -const nsIDOMDocument = I.nsIDOMDocument; const nsIDOMNode = I.nsIDOMNode; Cu.importGlobalProperties(["DOMParser", "Element", "XMLSerializer"]); diff --git a/dom/base/test/unit/test_range.js b/dom/base/test/unit/test_range.js index 9ce3d293a72b..16e9aad85c79 100644 --- a/dom/base/test/unit/test_range.js +++ b/dom/base/test/unit/test_range.js @@ -177,7 +177,7 @@ function getParsedDocument(aPath) { function processParsedDocument(doc) { Assert.ok(doc.documentElement.localName != "parsererror"); - Assert.ok(doc instanceof Ci.nsIDOMDocument); + Assert.equal(ChromeUtils.getClassName(doc), "XMLDocument"); // Clean out whitespace. var walker = doc.createTreeWalker(doc, @@ -447,7 +447,7 @@ function do_miscellaneous_tests(doc) { // Requested by smaug: A range involving a comment as a document child. doc = parser.parseFromString("", "application/xml"); - Assert.ok(doc instanceof Ci.nsIDOMDocument); + Assert.equal(ChromeUtils.getClassName(doc), "XMLDocument"); Assert.equal(doc.childNodes.length, 2); baseRange = doc.createRange(); baseRange.setStart(doc.firstChild, 1); diff --git a/dom/base/test/unit/test_xml_parser.js b/dom/base/test/unit/test_xml_parser.js index 0486ec64380d..ff13fde8acaa 100644 --- a/dom/base/test/unit/test_xml_parser.js +++ b/dom/base/test/unit/test_xml_parser.js @@ -8,7 +8,7 @@ function run_test () { var tests = [ [ test1, "Unable to parse basic XML document" ], - [ test2, "ParseXML doesn't return nsIDOMDocument" ], + [ test2, "ParseXML doesn't return Document" ], [ test3, "ParseXML return value's documentElement is not Element" ], [ test4, "" ], [ test5, "" ], @@ -21,7 +21,7 @@ function test1() { } function test2() { - return (ParseXML("") instanceof nsIDOMDocument); + return (ChromeUtils.getClassName(ParseXML("")) === "XMLDocument"); } function test3() { diff --git a/dom/console/tests/test_timer.html b/dom/console/tests/test_timer.html index e5f07e7273bc..f408f848af85 100644 --- a/dom/console/tests/test_timer.html +++ b/dom/console/tests/test_timer.html @@ -21,16 +21,11 @@ function ConsoleListener() { ConsoleListener.prototype = { observe(aSubject, aTopic, aData) { let obj = aSubject.wrappedJSObject; - if (obj.arguments[0] != 'test') { + if (obj.arguments[0] != "test_bug1463614") { return; } - if (!this._cb) { - ok(false, "Callback not set!"); - return; - } - - if (!this._cb(obj)) { + if (!this._cb || !this._cb(obj)) { return; } @@ -57,10 +52,10 @@ async function runTest() { let cl = listener.waitFor(obj => { return ("timer" in obj) && ("name" in obj.timer) && - obj.timer.name == 'test'; + obj.timer.name == "test_bug1463614"; }); - console.time('test'); + console.time("test_bug1463614"); await cl; ok(true, "Console.time received!"); @@ -68,7 +63,7 @@ async function runTest() { cl = listener.waitFor(obj => { return ("timer" in obj) && ("name" in obj.timer) && - obj.timer.name == 'test' && + obj.timer.name == "test_bug1463614" && ("duration" in obj.timer) && obj.timer.duration >= 0 && obj.arguments[1] == 1 && @@ -76,7 +71,7 @@ async function runTest() { obj.arguments[3] == 3 && obj.arguments[4] == 4; }); - console.timeLog('test', 1, 2, 3, 4); + console.timeLog("test_bug1463614", 1, 2, 3, 4); await cl; ok(true, "Console.timeLog received!"); @@ -84,11 +79,11 @@ async function runTest() { cl = listener.waitFor(obj => { return ("timer" in obj) && ("name" in obj.timer) && - obj.timer.name == 'test' && + obj.timer.name == "test_bug1463614" && ("duration" in obj.timer) && obj.timer.duration >= 0; }); - console.timeEnd('test'); + console.timeEnd("test_bug1463614"); await cl; ok(true, "Console.timeEnd received!"); @@ -96,10 +91,10 @@ async function runTest() { cl = listener.waitFor(obj => { return ("timer" in obj) && ("name" in obj.timer) && - obj.timer.name == 'test' && + obj.timer.name == "test_bug1463614" && ("error" in obj.timer); }); - console.timeLog('test'); + console.timeLog("test_bug1463614"); await cl; ok(true, "Console.time with error received!"); } diff --git a/dom/file/ipc/IPCBlobInputStream.cpp b/dom/file/ipc/IPCBlobInputStream.cpp index ded7d4cc7f6f..725401a37e07 100644 --- a/dom/file/ipc/IPCBlobInputStream.cpp +++ b/dom/file/ipc/IPCBlobInputStream.cpp @@ -127,6 +127,7 @@ NS_INTERFACE_MAP_BEGIN(IPCBlobInputStream) NS_INTERFACE_MAP_ENTRY(nsIAsyncFileMetadata) NS_INTERFACE_MAP_ENTRY(nsIInputStreamLength) NS_INTERFACE_MAP_ENTRY(nsIAsyncInputStreamLength) + NS_INTERFACE_MAP_ENTRY(nsIIPCBlobInputStream) NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIInputStream) NS_INTERFACE_MAP_END diff --git a/dom/file/ipc/IPCBlobInputStream.h b/dom/file/ipc/IPCBlobInputStream.h index 34dc077e807c..ffad17519a65 100644 --- a/dom/file/ipc/IPCBlobInputStream.h +++ b/dom/file/ipc/IPCBlobInputStream.h @@ -20,6 +20,22 @@ namespace dom { class IPCBlobInputStreamChild; +#define IPCBLOBINPUTSTREAM_IID \ + { 0xbcfa38fc, 0x8b7f, 0x4d79, \ + { 0xbe, 0x3a, 0x1e, 0x7b, 0xbe, 0x52, 0x38, 0xcd } } + +class nsIIPCBlobInputStream : public nsISupports +{ +public: + NS_DECLARE_STATIC_IID_ACCESSOR(IPCBLOBINPUTSTREAM_IID) + + virtual nsIInputStream* + GetInternalStream() const = 0; +}; + +NS_DEFINE_STATIC_IID_ACCESSOR(nsIIPCBlobInputStream, + IPCBLOBINPUTSTREAM_IID) + class IPCBlobInputStream final : public nsIAsyncInputStream , public nsIInputStreamCallback , public nsICloneableInputStreamWithRange @@ -27,6 +43,7 @@ class IPCBlobInputStream final : public nsIAsyncInputStream , public nsIAsyncFileMetadata , public nsIInputStreamLength , public nsIAsyncInputStreamLength + , public nsIIPCBlobInputStream { public: NS_DECL_THREADSAFE_ISUPPORTS @@ -49,6 +66,21 @@ public: void LengthReady(int64_t aLength); + // nsIIPCBlobInputStream + nsIInputStream* + GetInternalStream() const override + { + if (mRemoteStream) { + return mRemoteStream; + } + + if (mAsyncRemoteStream) { + return mAsyncRemoteStream; + } + + return nullptr; + } + private: ~IPCBlobInputStream(); diff --git a/dom/file/ipc/IPCBlobUtils.cpp b/dom/file/ipc/IPCBlobUtils.cpp index e825140052fb..73e6ce21296a 100644 --- a/dom/file/ipc/IPCBlobUtils.cpp +++ b/dom/file/ipc/IPCBlobUtils.cpp @@ -89,10 +89,26 @@ SerializeInputStreamParent(nsIInputStream* aInputStream, uint64_t aSize, // Parent to Child we always send a IPCBlobInputStream. MOZ_ASSERT(XRE_IsParentProcess()); + nsCOMPtr stream = aInputStream; + + // In case this is a IPCBlobInputStream, we don't want to create a loop: + // IPCBlobInputStreamParent -> IPCBlobInputStream -> + // IPCBlobInputStreamParent. Let's use the underlying inputStream instead. + nsCOMPtr ipcBlobInputStream = + do_QueryInterface(aInputStream); + if (ipcBlobInputStream) { + stream = ipcBlobInputStream->GetInternalStream(); + // If we don't have an underlying stream, it's better to terminate here + // instead of sending an 'empty' IPCBlobInputStream actor on the other side, + // unable to be used. + if (NS_WARN_IF(!stream)) { + return NS_ERROR_FAILURE; + } + } + nsresult rv; RefPtr parentActor = - IPCBlobInputStreamParent::Create(aInputStream, aSize, aChildID, &rv, - aManager); + IPCBlobInputStreamParent::Create(stream, aSize, aChildID, &rv, aManager); if (!parentActor) { return rv; } diff --git a/dom/interfaces/base/domstubs.idl b/dom/interfaces/base/domstubs.idl index 0fd11f2911bf..11db982baa76 100644 --- a/dom/interfaces/base/domstubs.idl +++ b/dom/interfaces/base/domstubs.idl @@ -16,7 +16,6 @@ typedef double DOMHighResTimeStamp; typedef unsigned long long nsViewID; // Core -interface nsIDOMDocument; interface nsIDOMNode; // Needed for raises() in our IDL diff --git a/dom/interfaces/core/moz.build b/dom/interfaces/core/moz.build index 9ae23cdb7da7..d961cf155671 100644 --- a/dom/interfaces/core/moz.build +++ b/dom/interfaces/core/moz.build @@ -8,7 +8,6 @@ with Files("**"): BUG_COMPONENT = ("Core", "DOM") XPIDL_SOURCES += [ - 'nsIDOMDocument.idl', 'nsIDOMNode.idl', 'nsIDOMNSEditableElement.idl', ] diff --git a/dom/interfaces/core/nsIDOMDocument.idl b/dom/interfaces/core/nsIDOMDocument.idl deleted file mode 100644 index f5595c979f64..000000000000 --- a/dom/interfaces/core/nsIDOMDocument.idl +++ /dev/null @@ -1,24 +0,0 @@ -/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -#include "nsIDOMNode.idl" - -/** - * The nsIDOMDocument interface represents the entire HTML or XML document. - * Conceptually, it is the root of the document tree, and provides the - * primary access to the document's data. - * Since elements, text nodes, comments, processing instructions, etc. - * cannot exist outside the context of a Document, the nsIDOMDocument - * interface also contains the factory methods needed to create these - * objects. - * - * For more information on this interface please see - * http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html - */ - -[shim(Document), uuid(b15fa0f4-97c1-4388-af62-2ceff7a89bdf)] -interface nsIDOMDocument : nsIDOMNode -{ -}; diff --git a/dom/webidl/Document.webidl b/dom/webidl/Document.webidl index fff315487b84..5f783eb76d16 100644 --- a/dom/webidl/Document.webidl +++ b/dom/webidl/Document.webidl @@ -349,7 +349,7 @@ partial interface Document { [Throws, Func="IsChromeOrXBL", NeedsSubjectPrincipal] void loadBindingDocument(DOMString documentURL); - // nsIDOMDocumentTouch + // Touch bits // XXXbz I can't find the sane spec for this stuff, so just cribbing // from our xpidl for now. [NewObject, Func="nsGenericHTMLElement::TouchEventsEnabled"] diff --git a/gfx/2d/2D.h b/gfx/2d/2D.h index 4cbe6c0480ee..6346753f220d 100644 --- a/gfx/2d/2D.h +++ b/gfx/2d/2D.h @@ -473,13 +473,35 @@ public: * * Use IsMapped() to verify whether Map() succeeded or not. */ - class ScopedMap { + class ScopedMap final { public: explicit ScopedMap(DataSourceSurface* aSurface, MapType aType) : mSurface(aSurface) , mIsMapped(aSurface->Map(aType, &mMap)) {} - virtual ~ScopedMap() + ScopedMap(ScopedMap&& aOther) + : mSurface(Move(aOther.mSurface)) + , mMap(aOther.mMap) + , mIsMapped(aOther.mIsMapped) + { + aOther.mMap.mData = nullptr; + aOther.mIsMapped = false; + } + + ScopedMap& operator=(ScopedMap&& aOther) + { + if (mIsMapped) { + mSurface->Unmap(); + } + mSurface = Move(aOther.mSurface); + mMap = aOther.mMap; + mIsMapped = aOther.mIsMapped; + aOther.mMap.mData = nullptr; + aOther.mIsMapped = false; + return *this; + } + + ~ScopedMap() { if (mIsMapped) { mSurface->Unmap(); @@ -507,6 +529,9 @@ public: bool IsMapped() const { return mIsMapped; } private: + ScopedMap(const ScopedMap& aOther) = delete; + ScopedMap& operator=(const ScopedMap& aOther) = delete; + RefPtr mSurface; MappedSurface mMap; bool mIsMapped; diff --git a/gfx/thebes/gfxFont.cpp b/gfx/thebes/gfxFont.cpp index 79d9423a2968..dd6876bb72e9 100644 --- a/gfx/thebes/gfxFont.cpp +++ b/gfx/thebes/gfxFont.cpp @@ -2038,6 +2038,7 @@ gfxFont::DrawOneGlyph(uint32_t aGlyphID, const gfx::Point& aPt, } if (fontParams.haveColorGlyphs && + !gfxPlatform::GetPlatform()->HasNativeColrFontSupport() && RenderColorGlyph(runParams.dt, runParams.context, fontParams.scaledFont, fontParams.drawOptions, diff --git a/gfx/thebes/gfxPlatform.h b/gfx/thebes/gfxPlatform.h index 66a7910c81a8..2b36178945ef 100644 --- a/gfx/thebes/gfxPlatform.h +++ b/gfx/thebes/gfxPlatform.h @@ -737,6 +737,10 @@ public: return mHasVariationFontSupport; } + bool HasNativeColrFontSupport() const { + return mHasNativeColrFontSupport; + } + // you probably want to use gfxVars::UseWebRender() instead of this static bool WebRenderPrefEnabled(); // you probably want to use gfxVars::UseWebRender() instead of this @@ -830,6 +834,10 @@ protected: // Whether the platform supports rendering OpenType font variations bool mHasVariationFontSupport; + // Whether the platform font APIs have native support for COLR fonts. + // Set to true during initialization on platforms that implement this. + bool mHasNativeColrFontSupport = false; + // max character limit for words in word cache int32_t mWordCacheCharLimit; diff --git a/gfx/thebes/gfxPlatformMac.cpp b/gfx/thebes/gfxPlatformMac.cpp index 07747ad25510..ed2daf8825c0 100644 --- a/gfx/thebes/gfxPlatformMac.cpp +++ b/gfx/thebes/gfxPlatformMac.cpp @@ -82,6 +82,10 @@ gfxPlatformMac::gfxPlatformMac() InitBackendPrefs(GetBackendPrefs()); MacIOSurfaceLib::LoadLibrary(); + + if (nsCocoaFeatures::OnHighSierraOrLater()) { + mHasNativeColrFontSupport = true; + } } gfxPlatformMac::~gfxPlatformMac() diff --git a/image/AnimationFrameBuffer.cpp b/image/AnimationFrameBuffer.cpp index 5d8b672f6665..404c9571f30c 100644 --- a/image/AnimationFrameBuffer.cpp +++ b/image/AnimationFrameBuffer.cpp @@ -176,18 +176,18 @@ AnimationFrameBuffer::MarkComplete() return mPending > 0; } -DrawableFrameRef +imgFrame* AnimationFrameBuffer::Get(size_t aFrame) { // We should not have asked for a frame if we never inserted. if (mFrames.IsEmpty()) { MOZ_ASSERT_UNREACHABLE("Calling Get() when we have no frames"); - return DrawableFrameRef(); + return nullptr; } // If we don't have that frame, return an empty frame ref. if (aFrame >= mFrames.Length()) { - return DrawableFrameRef(); + return nullptr; } // We've got the requested frame because we are not discarding frames. While @@ -195,13 +195,13 @@ AnimationFrameBuffer::Get(size_t aFrame) // we want them, it is possible the decoder is behind. if (!mFrames[aFrame]) { MOZ_ASSERT(MayDiscard()); - return DrawableFrameRef(); + return nullptr; } // If we are advancing on behalf of the animation, we don't expect it to be // getting any frames (besides the first) until we get the desired frame. MOZ_ASSERT(aFrame == 0 || mAdvance == 0); - return mFrames[aFrame]->DrawableRef(); + return mFrames[aFrame].get(); } bool diff --git a/image/AnimationFrameBuffer.h b/image/AnimationFrameBuffer.h index aa23327e9186..2773fa3f6f2b 100644 --- a/image/AnimationFrameBuffer.h +++ b/image/AnimationFrameBuffer.h @@ -63,7 +63,7 @@ public: * * @returns The frame, if available. */ - DrawableFrameRef Get(size_t aFrame); + imgFrame* Get(size_t aFrame); /** * Inserts a frame into the frame buffer. If it has yet to fully decode the diff --git a/image/AnimationParams.h b/image/AnimationParams.h new file mode 100644 index 000000000000..dc403a4e8eab --- /dev/null +++ b/image/AnimationParams.h @@ -0,0 +1,47 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#ifndef mozilla_image_AnimationParams_h +#define mozilla_image_AnimationParams_h + +#include +#include "mozilla/gfx/Rect.h" +#include "FrameTimeout.h" + +namespace mozilla { +namespace image { + +enum class BlendMethod : int8_t { + // All color components of the frame, including alpha, overwrite the current + // contents of the frame's output buffer region. + SOURCE, + + // The frame should be composited onto the output buffer based on its alpha, + // using a simple OVER operation. + OVER +}; + +enum class DisposalMethod : int8_t { + CLEAR_ALL = -1, // Clear the whole image, revealing what's underneath. + NOT_SPECIFIED, // Leave the frame and let the new frame draw on top. + KEEP, // Leave the frame and let the new frame draw on top. + CLEAR, // Clear the frame's area, revealing what's underneath. + RESTORE_PREVIOUS // Restore the previous (composited) frame. +}; + +struct AnimationParams +{ + gfx::IntRect mBlendRect; + FrameTimeout mTimeout; + uint32_t mFrameNum; + BlendMethod mBlendMethod; + DisposalMethod mDisposalMethod; +}; + +} // namespace image +} // namespace mozilla + +#endif // mozilla_image_AnimationParams_h diff --git a/image/AnimationSurfaceProvider.cpp b/image/AnimationSurfaceProvider.cpp index f1d6695c09fa..6ad22ec5a21e 100644 --- a/image/AnimationSurfaceProvider.cpp +++ b/image/AnimationSurfaceProvider.cpp @@ -134,7 +134,30 @@ AnimationSurfaceProvider::DrawableRef(size_t aFrame) return DrawableFrameRef(); } - return mFrames.Get(aFrame); + imgFrame* frame = mFrames.Get(aFrame); + if (!frame) { + return DrawableFrameRef(); + } + + return frame->DrawableRef(); +} + +RawAccessFrameRef +AnimationSurfaceProvider::RawAccessRef(size_t aFrame) +{ + MutexAutoLock lock(mFramesMutex); + + if (Availability().IsPlaceholder()) { + MOZ_ASSERT_UNREACHABLE("Calling RawAccessRef() on a placeholder"); + return RawAccessFrameRef(); + } + + imgFrame* frame = mFrames.Get(aFrame); + if (!frame) { + return RawAccessFrameRef(); + } + + return frame->RawAccessRef(/* aOnlyFinished */ true); } bool diff --git a/image/AnimationSurfaceProvider.h b/image/AnimationSurfaceProvider.h index 4853009a1a5b..06ad89a9c11e 100644 --- a/image/AnimationSurfaceProvider.h +++ b/image/AnimationSurfaceProvider.h @@ -57,6 +57,7 @@ public: protected: DrawableFrameRef DrawableRef(size_t aFrame) override; + RawAccessFrameRef RawAccessRef(size_t aFrame) override; // Animation frames are always locked. This is because we only want to release // their memory atomically (due to the surface cache discarding them). If they diff --git a/image/Decoder.cpp b/image/Decoder.cpp index 626840b2ef6f..6f4191a16d37 100644 --- a/image/Decoder.cpp +++ b/image/Decoder.cpp @@ -283,14 +283,14 @@ Decoder::Telemetry() const } nsresult -Decoder::AllocateFrame(uint32_t aFrameNum, - const gfx::IntSize& aOutputSize, +Decoder::AllocateFrame(const gfx::IntSize& aOutputSize, const gfx::IntRect& aFrameRect, gfx::SurfaceFormat aFormat, - uint8_t aPaletteDepth) + uint8_t aPaletteDepth, + const Maybe& aAnimParams) { - mCurrentFrame = AllocateFrameInternal(aFrameNum, aOutputSize, aFrameRect, - aFormat, aPaletteDepth, + mCurrentFrame = AllocateFrameInternal(aOutputSize, aFrameRect, aFormat, + aPaletteDepth, aAnimParams, mCurrentFrame.get()); if (mCurrentFrame) { @@ -302,7 +302,7 @@ Decoder::AllocateFrame(uint32_t aFrameNum, // We should now be on |aFrameNum|. (Note that we're comparing the frame // number, which is zero-based, with the frame count, which is one-based.) - MOZ_ASSERT(aFrameNum + 1 == mFrameCount); + MOZ_ASSERT_IF(aAnimParams, aAnimParams->mFrameNum + 1 == mFrameCount); // If we're past the first frame, PostIsAnimated() should've been called. MOZ_ASSERT_IF(mFrameCount > 1, HasAnimation()); @@ -316,18 +316,19 @@ Decoder::AllocateFrame(uint32_t aFrameNum, } RawAccessFrameRef -Decoder::AllocateFrameInternal(uint32_t aFrameNum, - const gfx::IntSize& aOutputSize, +Decoder::AllocateFrameInternal(const gfx::IntSize& aOutputSize, const gfx::IntRect& aFrameRect, SurfaceFormat aFormat, uint8_t aPaletteDepth, + const Maybe& aAnimParams, imgFrame* aPreviousFrame) { if (HasError()) { return RawAccessFrameRef(); } - if (aFrameNum != mFrameCount) { + uint32_t frameNum = aAnimParams ? aAnimParams->mFrameNum : 0; + if (frameNum != mFrameCount) { MOZ_ASSERT_UNREACHABLE("Allocating frames out of order"); return RawAccessFrameRef(); } @@ -342,7 +343,7 @@ Decoder::AllocateFrameInternal(uint32_t aFrameNum, bool nonPremult = bool(mSurfaceFlags & SurfaceFlags::NO_PREMULTIPLY_ALPHA); if (NS_FAILED(frame->InitForDecoder(aOutputSize, aFrameRect, aFormat, aPaletteDepth, nonPremult, - aFrameNum > 0))) { + aAnimParams))) { NS_WARNING("imgFrame::Init should succeed"); return RawAccessFrameRef(); } @@ -353,24 +354,20 @@ Decoder::AllocateFrameInternal(uint32_t aFrameNum, return RawAccessFrameRef(); } - if (aFrameNum == 1) { + if (frameNum == 1) { MOZ_ASSERT(aPreviousFrame, "Must provide a previous frame when animated"); - aPreviousFrame->SetRawAccessOnly(); - // If we dispose of the first frame by clearing it, then the first frame's // refresh area is all of itself. // RESTORE_PREVIOUS is invalid (assumed to be DISPOSE_CLEAR). - AnimationData previousFrameData = aPreviousFrame->GetAnimationData(); - if (previousFrameData.mDisposalMethod == DisposalMethod::CLEAR || - previousFrameData.mDisposalMethod == DisposalMethod::CLEAR_ALL || - previousFrameData.mDisposalMethod == DisposalMethod::RESTORE_PREVIOUS) { - mFirstFrameRefreshArea = previousFrameData.mRect; + DisposalMethod prevDisposal = aPreviousFrame->GetDisposalMethod(); + if (prevDisposal == DisposalMethod::CLEAR || + prevDisposal == DisposalMethod::CLEAR_ALL || + prevDisposal == DisposalMethod::RESTORE_PREVIOUS) { + mFirstFrameRefreshArea = aPreviousFrame->GetRect(); } } - if (aFrameNum > 0) { - ref->SetRawAccessOnly(); - + if (frameNum > 0) { // Some GIFs are huge but only have a small area that they animate. We only // need to refresh that small area when frame 0 comes around again. mFirstFrameRefreshArea.UnionRect(mFirstFrameRefreshArea, frame->GetRect()); @@ -453,13 +450,7 @@ Decoder::PostIsAnimated(FrameTimeout aFirstFrameTimeout) } void -Decoder::PostFrameStop(Opacity aFrameOpacity - /* = Opacity::SOME_TRANSPARENCY */, - DisposalMethod aDisposalMethod - /* = DisposalMethod::KEEP */, - FrameTimeout aTimeout /* = FrameTimeout::Forever() */, - BlendMethod aBlendMethod /* = BlendMethod::OVER */, - const Maybe& aBlendRect /* = Nothing() */) +Decoder::PostFrameStop(Opacity aFrameOpacity) { // We should be mid-frame MOZ_ASSERT(!IsMetadataDecode(), "Stopping frame during metadata decode"); @@ -470,12 +461,11 @@ Decoder::PostFrameStop(Opacity aFrameOpacity mInFrame = false; mFinishedNewFrame = true; - mCurrentFrame->Finish(aFrameOpacity, aDisposalMethod, aTimeout, - aBlendMethod, aBlendRect, mFinalizeFrames); + mCurrentFrame->Finish(aFrameOpacity, mFinalizeFrames); mProgress |= FLAG_FRAME_COMPLETE; - mLoopLength += aTimeout; + mLoopLength += mCurrentFrame->GetTimeout(); // If we're not sending partial invalidations, then we send an invalidation // here when the first frame is complete. diff --git a/image/Decoder.h b/image/Decoder.h index cd900a1f98c7..fcb9dc90fa48 100644 --- a/image/Decoder.h +++ b/image/Decoder.h @@ -11,6 +11,7 @@ #include "mozilla/Maybe.h" #include "mozilla/NotNull.h" #include "mozilla/RefPtr.h" +#include "AnimationParams.h" #include "DecoderFlags.h" #include "Downscaler.h" #include "ImageMetadata.h" @@ -27,6 +28,8 @@ namespace Telemetry { namespace image { +class imgFrame; + struct DecoderFinalStatus final { DecoderFinalStatus(bool aWasMetadataDecode, @@ -477,11 +480,7 @@ protected: // Specify whether this frame is opaque as an optimization. // For animated images, specify the disposal, blend method and timeout for // this frame. - void PostFrameStop(Opacity aFrameOpacity = Opacity::SOME_TRANSPARENCY, - DisposalMethod aDisposalMethod = DisposalMethod::KEEP, - FrameTimeout aTimeout = FrameTimeout::Forever(), - BlendMethod aBlendMethod = BlendMethod::OVER, - const Maybe& aBlendRect = Nothing()); + void PostFrameStop(Opacity aFrameOpacity = Opacity::SOME_TRANSPARENCY); /** * Called by the decoders when they have a region to invalidate. We may not @@ -510,16 +509,13 @@ protected: /** * Allocates a new frame, making it our current frame if successful. * - * The @aFrameNum parameter only exists as a sanity check; it's illegal to - * create a new frame anywhere but immediately after the existing frames. - * * If a non-paletted frame is desired, pass 0 for aPaletteDepth. */ - nsresult AllocateFrame(uint32_t aFrameNum, - const gfx::IntSize& aOutputSize, + nsresult AllocateFrame(const gfx::IntSize& aOutputSize, const gfx::IntRect& aFrameRect, gfx::SurfaceFormat aFormat, - uint8_t aPaletteDepth = 0); + uint8_t aPaletteDepth = 0, + const Maybe& aAnimParams = Nothing()); private: /// Report that an error was encountered while decoding. @@ -543,11 +539,11 @@ private: return mInFrame ? mFrameCount - 1 : mFrameCount; } - RawAccessFrameRef AllocateFrameInternal(uint32_t aFrameNum, - const gfx::IntSize& aOutputSize, + RawAccessFrameRef AllocateFrameInternal(const gfx::IntSize& aOutputSize, const gfx::IntRect& aFrameRect, gfx::SurfaceFormat aFormat, uint8_t aPaletteDepth, + const Maybe& aAnimParams, imgFrame* aPreviousFrame); protected: diff --git a/image/DownscalingFilter.h b/image/DownscalingFilter.h index 764aade2e63b..f965dd878f11 100644 --- a/image/DownscalingFilter.h +++ b/image/DownscalingFilter.h @@ -70,7 +70,7 @@ public: Maybe TakeInvalidRect() override { return Nothing(); } template - nsresult Configure(const DownscalingConfig& aConfig, Rest... aRest) + nsresult Configure(const DownscalingConfig& aConfig, const Rest&... aRest) { return NS_ERROR_FAILURE; } @@ -106,7 +106,7 @@ public: } template - nsresult Configure(const DownscalingConfig& aConfig, Rest... aRest) + nsresult Configure(const DownscalingConfig& aConfig, const Rest&... aRest) { nsresult rv = mNext.Configure(aRest...); if (NS_FAILED(rv)) { diff --git a/image/FrameAnimator.cpp b/image/FrameAnimator.cpp index ab72a3a0c07c..7e3fb76c1f1c 100644 --- a/image/FrameAnimator.cpp +++ b/image/FrameAnimator.cpp @@ -212,40 +212,30 @@ AnimationState::LoopLength() const // FrameAnimator implementation. /////////////////////////////////////////////////////////////////////////////// -Maybe +TimeStamp FrameAnimator::GetCurrentImgFrameEndTime(AnimationState& aState, - DrawableSurface& aFrames) const + FrameTimeout aCurrentTimeout) const { - TimeStamp currentFrameTime = aState.mCurrentAnimationFrameTime; - Maybe timeout = - GetTimeoutForFrame(aState, aFrames, aState.mCurrentAnimationFrameIndex); - - if (timeout.isNothing()) { - MOZ_ASSERT(aState.GetHasRequestedDecode() && !aState.GetIsCurrentlyDecoded()); - return Nothing(); - } - - if (*timeout == FrameTimeout::Forever()) { + if (aCurrentTimeout == FrameTimeout::Forever()) { // We need to return a sentinel value in this case, because our logic // doesn't work correctly if we have an infinitely long timeout. We use one // year in the future as the sentinel because it works with the loop in // RequestRefresh() below. // XXX(seth): It'd be preferable to make our logic work correctly with // infinitely long timeouts. - return Some(TimeStamp::NowLoRes() + - TimeDuration::FromMilliseconds(31536000.0)); + return TimeStamp::NowLoRes() + + TimeDuration::FromMilliseconds(31536000.0); } TimeDuration durationOfTimeout = - TimeDuration::FromMilliseconds(double(timeout->AsMilliseconds())); - TimeStamp currentFrameEndTime = currentFrameTime + durationOfTimeout; - - return Some(currentFrameEndTime); + TimeDuration::FromMilliseconds(double(aCurrentTimeout.AsMilliseconds())); + return aState.mCurrentAnimationFrameTime + durationOfTimeout; } RefreshResult FrameAnimator::AdvanceFrame(AnimationState& aState, DrawableSurface& aFrames, + RawAccessFrameRef& aCurrentFrame, TimeStamp aTime) { NS_ASSERTION(aTime <= TimeStamp::Now(), @@ -306,13 +296,14 @@ FrameAnimator::AdvanceFrame(AnimationState& aState, // the appropriate notification on the main thread. Make sure we stay in sync // with AnimationState. MOZ_ASSERT(nextFrameIndex < aState.KnownFrameCount()); - RawAccessFrameRef nextFrame = GetRawFrame(aFrames, nextFrameIndex); + RawAccessFrameRef nextFrame = aFrames.RawAccessRef(nextFrameIndex); // We should always check to see if we have the next frame even if we have // previously finished decoding. If we needed to redecode (e.g. due to a draw // failure) we would have discarded all the old frames and may not yet have - // the new ones. - if (!nextFrame || !nextFrame->IsFinished()) { + // the new ones. DrawableSurface::RawAccessRef promises to only return + // finished frames. + if (!nextFrame) { // Uh oh, the frame we want to show is currently being decoded (partial). // Similar to the above case, we could be blocked by network or decoding, // and so we should advance our current time rather than risk jumping @@ -322,11 +313,7 @@ FrameAnimator::AdvanceFrame(AnimationState& aState, return ret; } - Maybe nextFrameTimeout = GetTimeoutForFrame(aState, aFrames, nextFrameIndex); - // GetTimeoutForFrame can only return none if frame doesn't exist, - // but we just got it above. - MOZ_ASSERT(nextFrameTimeout.isSome()); - if (*nextFrameTimeout == FrameTimeout::Forever()) { + if (nextFrame->GetTimeout() == FrameTimeout::Forever()) { ret.mAnimationFinished = true; } @@ -336,15 +323,15 @@ FrameAnimator::AdvanceFrame(AnimationState& aState, MOZ_ASSERT(nextFrameIndex == currentFrameIndex + 1); // Change frame - if (!DoBlend(aFrames, &ret.mDirtyRect, currentFrameIndex, nextFrameIndex)) { + if (!DoBlend(aCurrentFrame, nextFrame, nextFrameIndex, &ret.mDirtyRect)) { // something went wrong, move on to next NS_WARNING("FrameAnimator::AdvanceFrame(): Compositing of frame failed"); nextFrame->SetCompositingFailed(true); - Maybe currentFrameEndTime = GetCurrentImgFrameEndTime(aState, aFrames); - MOZ_ASSERT(currentFrameEndTime.isSome()); - aState.mCurrentAnimationFrameTime = *currentFrameEndTime; + aState.mCurrentAnimationFrameTime = + GetCurrentImgFrameEndTime(aState, aCurrentFrame->GetTimeout()); aState.mCurrentAnimationFrameIndex = nextFrameIndex; aState.mCompositedFrameRequested = false; + aCurrentFrame = Move(nextFrame); aFrames.Advance(nextFrameIndex); return ret; @@ -353,9 +340,8 @@ FrameAnimator::AdvanceFrame(AnimationState& aState, nextFrame->SetCompositingFailed(false); } - Maybe currentFrameEndTime = GetCurrentImgFrameEndTime(aState, aFrames); - MOZ_ASSERT(currentFrameEndTime.isSome()); - aState.mCurrentAnimationFrameTime = *currentFrameEndTime; + aState.mCurrentAnimationFrameTime = + GetCurrentImgFrameEndTime(aState, aCurrentFrame->GetTimeout()); // If we can get closer to the current time by a multiple of the image's loop // time, we should. We can only do this if we're done decoding; otherwise, we @@ -392,6 +378,7 @@ FrameAnimator::AdvanceFrame(AnimationState& aState, // Set currentAnimationFrameIndex at the last possible moment aState.mCurrentAnimationFrameIndex = nextFrameIndex; aState.mCompositedFrameRequested = false; + aCurrentFrame = Move(nextFrame); aFrames.Advance(nextFrameIndex); // If we're here, we successfully advanced the frame. @@ -451,11 +438,12 @@ FrameAnimator::RequestRefresh(AnimationState& aState, return ret; } + RawAccessFrameRef currentFrame = + result.Surface().RawAccessRef(aState.mCurrentAnimationFrameIndex); + // only advance the frame if the current time is greater than or // equal to the current frame's end time. - Maybe currentFrameEndTime = - GetCurrentImgFrameEndTime(aState, result.Surface()); - if (currentFrameEndTime.isNothing()) { + if (!currentFrame) { MOZ_ASSERT(gfxPrefs::ImageMemAnimatedDiscardable()); MOZ_ASSERT(aState.GetHasRequestedDecode() && !aState.GetIsCurrentlyDecoded()); MOZ_ASSERT(aState.mCompositedFrameInvalid); @@ -465,6 +453,9 @@ FrameAnimator::RequestRefresh(AnimationState& aState, return ret; } + TimeStamp currentFrameEndTime = + GetCurrentImgFrameEndTime(aState, currentFrame->GetTimeout()); + // If nothing has accessed the composited frame since the last time we // advanced, then there is no point in continuing to advance the animation. // This has the effect of freezing the animation while not in view. @@ -473,28 +464,29 @@ FrameAnimator::RequestRefresh(AnimationState& aState, return ret; } - while (*currentFrameEndTime <= aTime) { - TimeStamp oldFrameEndTime = *currentFrameEndTime; + while (currentFrameEndTime <= aTime) { + TimeStamp oldFrameEndTime = currentFrameEndTime; - RefreshResult frameRes = AdvanceFrame(aState, result.Surface(), aTime); + RefreshResult frameRes = AdvanceFrame(aState, result.Surface(), + currentFrame, aTime); // Accumulate our result for returning to callers. ret.Accumulate(frameRes); - currentFrameEndTime = GetCurrentImgFrameEndTime(aState, result.Surface()); - // AdvanceFrame can't advance to a frame that doesn't exist yet. - MOZ_ASSERT(currentFrameEndTime.isSome()); + // currentFrame was updated by AdvanceFrame so it is still current. + currentFrameEndTime = + GetCurrentImgFrameEndTime(aState, currentFrame->GetTimeout()); // If we didn't advance a frame, and our frame end time didn't change, // then we need to break out of this loop & wait for the frame(s) // to finish downloading. - if (!frameRes.mFrameAdvanced && (*currentFrameEndTime == oldFrameEndTime)) { + if (!frameRes.mFrameAdvanced && currentFrameEndTime == oldFrameEndTime) { break; } } // Advanced to the correct frame, the composited frame is now valid to be drawn. - if (*currentFrameEndTime > aTime) { + if (currentFrameEndTime > aTime) { aState.mCompositedFrameInvalid = false; ret.mDirtyRect = IntRect(IntPoint(0,0), mSize); } @@ -509,6 +501,13 @@ FrameAnimator::GetCompositedFrame(AnimationState& aState) { aState.mCompositedFrameRequested = true; + // If we have a composited version of this frame, return that. + if (!aState.mCompositedFrameInvalid && mLastCompositedFrameIndex >= 0 && + (uint32_t(mLastCompositedFrameIndex) == aState.mCurrentAnimationFrameIndex)) { + return LookupResult(DrawableSurface(mCompositingFrame->DrawableRef()), + MatchType::EXACT); + } + LookupResult result = SurfaceCache::Lookup(ImageKey(mImage), RasterSurfaceKey(mSize, @@ -525,13 +524,6 @@ FrameAnimator::GetCompositedFrame(AnimationState& aState) return LookupResult(MatchType::PENDING); } - // If we have a composited version of this frame, return that. - if (mLastCompositedFrameIndex >= 0 && - (uint32_t(mLastCompositedFrameIndex) == aState.mCurrentAnimationFrameIndex)) { - return LookupResult(DrawableSurface(mCompositingFrame->DrawableRef()), - MatchType::EXACT); - } - // Otherwise return the raw frame. DoBlend is required to ensure that we only // hit this case if the frame is not paletted and doesn't require compositing. if (!result) { @@ -553,21 +545,6 @@ FrameAnimator::GetCompositedFrame(AnimationState& aState) return result; } -Maybe -FrameAnimator::GetTimeoutForFrame(AnimationState& aState, - DrawableSurface& aFrames, - uint32_t aFrameNum) const -{ - RawAccessFrameRef frame = GetRawFrame(aFrames, aFrameNum); - if (frame) { - AnimationData data = frame->GetAnimationData(); - return Some(data.mTimeout); - } - - MOZ_ASSERT(aState.mHasRequestedDecode && !aState.mIsCurrentlyDecoded); - return Nothing(); -} - static void DoCollectSizeOfCompositingSurfaces(const RawAccessFrameRef& aSurface, SurfaceMemoryCounterType aType, @@ -615,64 +592,44 @@ FrameAnimator::CollectSizeOfCompositingSurfaces( } } -RawAccessFrameRef -FrameAnimator::GetRawFrame(DrawableSurface& aFrames, uint32_t aFrameNum) const -{ - // Seek to the frame we want. If seeking fails, it means we couldn't get the - // frame we're looking for, so we bail here to avoid returning the wrong frame - // to the caller. - if (NS_FAILED(aFrames.Seek(aFrameNum))) { - return RawAccessFrameRef(); // Not available yet. - } - - return aFrames->RawAccessRef(); -} - //****************************************************************************** // DoBlend gets called when the timer for animation get fired and we have to // update the composited frame of the animation. bool -FrameAnimator::DoBlend(DrawableSurface& aFrames, - IntRect* aDirtyRect, - uint32_t aPrevFrameIndex, - uint32_t aNextFrameIndex) +FrameAnimator::DoBlend(const RawAccessFrameRef& aPrevFrame, + const RawAccessFrameRef& aNextFrame, + uint32_t aNextFrameIndex, + IntRect* aDirtyRect) { - RawAccessFrameRef prevFrame = GetRawFrame(aFrames, aPrevFrameIndex); - RawAccessFrameRef nextFrame = GetRawFrame(aFrames, aNextFrameIndex); + MOZ_ASSERT(aPrevFrame && aNextFrame, "Should have frames here"); - MOZ_ASSERT(prevFrame && nextFrame, "Should have frames here"); - - AnimationData prevFrameData = prevFrame->GetAnimationData(); - if (prevFrameData.mDisposalMethod == DisposalMethod::RESTORE_PREVIOUS && + DisposalMethod prevDisposalMethod = aPrevFrame->GetDisposalMethod(); + bool prevHasAlpha = aPrevFrame->FormatHasAlpha(); + if (prevDisposalMethod == DisposalMethod::RESTORE_PREVIOUS && !mCompositingPrevFrame) { - prevFrameData.mDisposalMethod = DisposalMethod::CLEAR; + prevDisposalMethod = DisposalMethod::CLEAR; } - IntRect prevRect = prevFrameData.mBlendRect - ? prevFrameData.mRect.Intersect(*prevFrameData.mBlendRect) - : prevFrameData.mRect; - + IntRect prevRect = aPrevFrame->GetBoundedBlendRect(); bool isFullPrevFrame = prevRect.IsEqualRect(0, 0, mSize.width, mSize.height); // Optimization: DisposeClearAll if the previous frame is the same size as // container and it's clearing itself if (isFullPrevFrame && - (prevFrameData.mDisposalMethod == DisposalMethod::CLEAR)) { - prevFrameData.mDisposalMethod = DisposalMethod::CLEAR_ALL; + (prevDisposalMethod == DisposalMethod::CLEAR)) { + prevDisposalMethod = DisposalMethod::CLEAR_ALL; } - AnimationData nextFrameData = nextFrame->GetAnimationData(); - - IntRect nextRect = nextFrameData.mBlendRect - ? nextFrameData.mRect.Intersect(*nextFrameData.mBlendRect) - : nextFrameData.mRect; + DisposalMethod nextDisposalMethod = aNextFrame->GetDisposalMethod(); + bool nextHasAlpha = aNextFrame->FormatHasAlpha(); + IntRect nextRect = aNextFrame->GetBoundedBlendRect(); bool isFullNextFrame = nextRect.IsEqualRect(0, 0, mSize.width, mSize.height); - if (!nextFrame->GetIsPaletted()) { + if (!aNextFrame->GetIsPaletted()) { // Optimization: Skip compositing if the previous frame wants to clear the // whole image - if (prevFrameData.mDisposalMethod == DisposalMethod::CLEAR_ALL) { + if (prevDisposalMethod == DisposalMethod::CLEAR_ALL) { aDirtyRect->SetRect(0, 0, mSize.width, mSize.height); return true; } @@ -680,15 +637,15 @@ FrameAnimator::DoBlend(DrawableSurface& aFrames, // Optimization: Skip compositing if this frame is the same size as the // container and it's fully drawing over prev frame (no alpha) if (isFullNextFrame && - (nextFrameData.mDisposalMethod != DisposalMethod::RESTORE_PREVIOUS) && - !nextFrameData.mHasAlpha) { + (nextDisposalMethod != DisposalMethod::RESTORE_PREVIOUS) && + !nextHasAlpha) { aDirtyRect->SetRect(0, 0, mSize.width, mSize.height); return true; } } // Calculate area that needs updating - switch (prevFrameData.mDisposalMethod) { + switch (prevDisposalMethod) { default: MOZ_FALLTHROUGH_ASSERT("Unexpected DisposalMethod"); case DisposalMethod::NOT_SPECIFIED: @@ -705,7 +662,7 @@ FrameAnimator::DoBlend(DrawableSurface& aFrames, // Calc area that needs to be redrawn (the combination of previous and // this frame) // XXX - This could be done with multiple framechanged calls - // Having prevFrame way at the top of the image, and nextFrame + // Having aPrevFrame way at the top of the image, and aNextFrame // way at the bottom, and both frames being small, we'd be // telling framechanged to refresh the whole image when only two // small areas are needed. @@ -747,8 +704,6 @@ FrameAnimator::DoBlend(DrawableSurface& aFrames, needToBlankComposite = true; } - AnimationData compositingFrameData = mCompositingFrame->GetAnimationData(); - // More optimizations possible when next frame is not transparent // But if the next frame has DisposalMethod::RESTORE_PREVIOUS, // this "no disposal" optimization is not possible, @@ -756,8 +711,7 @@ FrameAnimator::DoBlend(DrawableSurface& aFrames, // needs to be stored in compositingFrame, so it can be // copied into compositingPrevFrame later. bool doDisposal = true; - if (!nextFrameData.mHasAlpha && - nextFrameData.mDisposalMethod != DisposalMethod::RESTORE_PREVIOUS) { + if (!nextHasAlpha && nextDisposalMethod != DisposalMethod::RESTORE_PREVIOUS) { if (isFullNextFrame) { // Optimization: No need to dispose prev.frame when // next frame is full frame and not transparent. @@ -777,46 +731,42 @@ FrameAnimator::DoBlend(DrawableSurface& aFrames, if (doDisposal) { // Dispose of previous: clear, restore, or keep (copy) - switch (prevFrameData.mDisposalMethod) { + switch (prevDisposalMethod) { case DisposalMethod::CLEAR: if (needToBlankComposite) { // If we just created the composite, it could have anything in its // buffer. Clear whole frame - ClearFrame(compositingFrameData.mRawData, - compositingFrameData.mRect); + ClearFrame(mCompositingFrame.Data(), + mCompositingFrame->GetRect()); } else { // Only blank out previous frame area (both color & Mask/Alpha) - ClearFrame(compositingFrameData.mRawData, - compositingFrameData.mRect, + ClearFrame(mCompositingFrame.Data(), + mCompositingFrame->GetRect(), prevRect); } break; case DisposalMethod::CLEAR_ALL: - ClearFrame(compositingFrameData.mRawData, - compositingFrameData.mRect); + ClearFrame(mCompositingFrame.Data(), + mCompositingFrame->GetRect()); break; case DisposalMethod::RESTORE_PREVIOUS: // It would be better to copy only the area changed back to // compositingFrame. if (mCompositingPrevFrame) { - AnimationData compositingPrevFrameData = - mCompositingPrevFrame->GetAnimationData(); - - CopyFrameImage(compositingPrevFrameData.mRawData, - compositingPrevFrameData.mRect, - compositingFrameData.mRawData, - compositingFrameData.mRect); + CopyFrameImage(mCompositingPrevFrame.Data(), + mCompositingPrevFrame->GetRect(), + mCompositingFrame.Data(), + mCompositingFrame->GetRect()); // destroy only if we don't need it for this frame's disposal - if (nextFrameData.mDisposalMethod != - DisposalMethod::RESTORE_PREVIOUS) { + if (nextDisposalMethod != DisposalMethod::RESTORE_PREVIOUS) { mCompositingPrevFrame.reset(); } } else { - ClearFrame(compositingFrameData.mRawData, - compositingFrameData.mRect); + ClearFrame(mCompositingFrame.Data(), + mCompositingFrame->GetRect()); } break; @@ -832,44 +782,44 @@ FrameAnimator::DoBlend(DrawableSurface& aFrames, // Note: Frame 1 never gets into DoBlend(), so (aNextFrameIndex - 1) // will always be a valid frame number. if (mLastCompositedFrameIndex != int32_t(aNextFrameIndex - 1)) { - if (isFullPrevFrame && !prevFrame->GetIsPaletted()) { + if (isFullPrevFrame && !aPrevFrame->GetIsPaletted()) { // Just copy the bits - CopyFrameImage(prevFrameData.mRawData, + CopyFrameImage(aPrevFrame.Data(), prevRect, - compositingFrameData.mRawData, - compositingFrameData.mRect); + mCompositingFrame.Data(), + mCompositingFrame->GetRect()); } else { if (needToBlankComposite) { // Only blank composite when prev is transparent or not full. - if (prevFrameData.mHasAlpha || !isFullPrevFrame) { - ClearFrame(compositingFrameData.mRawData, - compositingFrameData.mRect); + if (prevHasAlpha || !isFullPrevFrame) { + ClearFrame(mCompositingFrame.Data(), + mCompositingFrame->GetRect()); } } - DrawFrameTo(prevFrameData.mRawData, prevFrameData.mRect, - prevFrameData.mPaletteDataLength, - prevFrameData.mHasAlpha, - compositingFrameData.mRawData, - compositingFrameData.mRect, - prevFrameData.mBlendMethod, - prevFrameData.mBlendRect); + DrawFrameTo(aPrevFrame.Data(), aPrevFrame->GetRect(), + aPrevFrame.PaletteDataLength(), + prevHasAlpha, + mCompositingFrame.Data(), + mCompositingFrame->GetRect(), + aPrevFrame->GetBlendMethod(), + aPrevFrame->GetBlendRect()); } } } } else if (needToBlankComposite) { // If we just created the composite, it could have anything in its // buffers. Clear them - ClearFrame(compositingFrameData.mRawData, - compositingFrameData.mRect); + ClearFrame(mCompositingFrame.Data(), + mCompositingFrame->GetRect()); } // Check if the frame we are composing wants the previous image restored after // it is done. Don't store it (again) if last frame wanted its image restored // too - if ((nextFrameData.mDisposalMethod == DisposalMethod::RESTORE_PREVIOUS) && - (prevFrameData.mDisposalMethod != DisposalMethod::RESTORE_PREVIOUS)) { + if ((nextDisposalMethod == DisposalMethod::RESTORE_PREVIOUS) && + (prevDisposalMethod != DisposalMethod::RESTORE_PREVIOUS)) { // We are storing the whole image. - // It would be better if we just stored the area that nextFrame is going to + // It would be better if we just stored the area that aNextFrame is going to // overwrite. if (!mCompositingPrevFrame) { RefPtr newFrame = new imgFrame; @@ -883,25 +833,22 @@ FrameAnimator::DoBlend(DrawableSurface& aFrames, mCompositingPrevFrame = newFrame->RawAccessRef(); } - AnimationData compositingPrevFrameData = - mCompositingPrevFrame->GetAnimationData(); - - CopyFrameImage(compositingFrameData.mRawData, - compositingFrameData.mRect, - compositingPrevFrameData.mRawData, - compositingPrevFrameData.mRect); + CopyFrameImage(mCompositingFrame.Data(), + mCompositingFrame->GetRect(), + mCompositingPrevFrame.Data(), + mCompositingPrevFrame->GetRect()); mCompositingPrevFrame->Finish(); } // blit next frame into it's correct spot - DrawFrameTo(nextFrameData.mRawData, nextFrameData.mRect, - nextFrameData.mPaletteDataLength, - nextFrameData.mHasAlpha, - compositingFrameData.mRawData, - compositingFrameData.mRect, - nextFrameData.mBlendMethod, - nextFrameData.mBlendRect); + DrawFrameTo(aNextFrame.Data(), aNextFrame->GetRect(), + aNextFrame.PaletteDataLength(), + nextHasAlpha, + mCompositingFrame.Data(), + mCompositingFrame->GetRect(), + aNextFrame->GetBlendMethod(), + aNextFrame->GetBlendRect()); // Tell the image that it is fully 'downloaded'. mCompositingFrame->Finish(); @@ -970,7 +917,7 @@ nsresult FrameAnimator::DrawFrameTo(const uint8_t* aSrcData, const IntRect& aSrcRect, uint32_t aSrcPaletteLength, bool aSrcHasAlpha, uint8_t* aDstPixels, const IntRect& aDstRect, - BlendMethod aBlendMethod, const Maybe& aBlendRect) + BlendMethod aBlendMethod, const IntRect& aBlendRect) { NS_ENSURE_ARG_POINTER(aSrcData); NS_ENSURE_ARG_POINTER(aDstPixels); @@ -1067,8 +1014,8 @@ FrameAnimator::DrawFrameTo(const uint8_t* aSrcData, const IntRect& aSrcRect, auto op = aBlendMethod == BlendMethod::SOURCE ? PIXMAN_OP_SRC : PIXMAN_OP_OVER; - if (aBlendMethod == BlendMethod::OVER || !aBlendRect || - (aBlendMethod == BlendMethod::SOURCE && aSrcRect.IsEqualEdges(*aBlendRect))) { + if (aBlendMethod == BlendMethod::OVER || + (aBlendMethod == BlendMethod::SOURCE && aSrcRect.IsEqualEdges(aBlendRect))) { // We don't need to do anything clever. (Or, in the case where no blend // rect was specified, we can't.) pixman_image_composite32(op, @@ -1093,10 +1040,10 @@ FrameAnimator::DrawFrameTo(const uint8_t* aSrcData, const IntRect& aSrcRect, src, nullptr, dst, - aBlendRect->X(), aBlendRect->Y(), + aBlendRect.X(), aBlendRect.Y(), 0, 0, - aBlendRect->X(), aBlendRect->Y(), - aBlendRect->Width(), aBlendRect->Height()); + aBlendRect.X(), aBlendRect.Y(), + aBlendRect.Width(), aBlendRect.Height()); } pixman_image_unref(src); diff --git a/image/FrameAnimator.h b/image/FrameAnimator.h index ec46dccb3581..c8f3b26a85f0 100644 --- a/image/FrameAnimator.h +++ b/image/FrameAnimator.h @@ -343,37 +343,31 @@ private: // methods * @param aTime the time that the animation should advance to. This will * typically be <= TimeStamp::Now(). * + * @param aCurrentFrame the currently displayed frame of the animation. If + * we advance, it will replace aCurrentFrame with the + * new current frame we advanced to. + * * @returns a RefreshResult that shows whether the frame was successfully * advanced, and its resulting dirty rect. */ RefreshResult AdvanceFrame(AnimationState& aState, DrawableSurface& aFrames, + RawAccessFrameRef& aCurrentFrame, TimeStamp aTime); - /** - * Get the @aIndex-th frame in the frame index, ignoring results of blending. - */ - RawAccessFrameRef GetRawFrame(DrawableSurface& aFrames, - uint32_t aFrameNum) const; - - /// @return the given frame's timeout if it is available - Maybe GetTimeoutForFrame(AnimationState& aState, - DrawableSurface& aFrames, - uint32_t aFrameNum) const; - /** * Get the time the frame we're currently displaying is supposed to end. * * In the error case (like if the requested frame is not currently * decoded), returns None(). */ - Maybe GetCurrentImgFrameEndTime(AnimationState& aState, - DrawableSurface& aFrames) const; + TimeStamp GetCurrentImgFrameEndTime(AnimationState& aState, + FrameTimeout aCurrentTimeout) const; - bool DoBlend(DrawableSurface& aFrames, - gfx::IntRect* aDirtyRect, - uint32_t aPrevFrameIndex, - uint32_t aNextFrameIndex); + bool DoBlend(const RawAccessFrameRef& aPrevFrame, + const RawAccessFrameRef& aNextFrame, + uint32_t aNextFrameIndex, + gfx::IntRect* aDirtyRect); /** Clears an area of with transparent black. * @@ -413,7 +407,7 @@ private: // methods uint32_t aSrcPaletteLength, bool aSrcHasAlpha, uint8_t* aDstPixels, const gfx::IntRect& aDstRect, BlendMethod aBlendMethod, - const Maybe& aBlendRect); + const gfx::IntRect& aBlendRect); private: // data //! A weak pointer to our owning image. diff --git a/image/ISurfaceProvider.h b/image/ISurfaceProvider.h index 852072eb34db..38094b5ee99b 100644 --- a/image/ISurfaceProvider.h +++ b/image/ISurfaceProvider.h @@ -110,6 +110,15 @@ protected: /// index of the desired frame. virtual DrawableFrameRef DrawableRef(size_t aFrame) = 0; + /// @return an eagerly computed raw access reference to a surface. For + /// dynamically generated animation surfaces, @aFrame specifies the 0-based + /// index of the desired frame. + virtual RawAccessFrameRef RawAccessRef(size_t aFrame) + { + MOZ_ASSERT_UNREACHABLE("Surface provider does not support raw access!"); + return RawAccessFrameRef(); + } + /// @return true if this ISurfaceProvider is locked. (@see SetLocked()) /// Should only be called from SurfaceCache code as it relies on SurfaceCache /// for synchronization. @@ -199,6 +208,18 @@ public: return mDrawableRef ? NS_OK : NS_ERROR_FAILURE; } + RawAccessFrameRef RawAccessRef(size_t aFrame) + { + MOZ_ASSERT(mHaveSurface, "Trying to get on an empty DrawableSurface?"); + + if (!mProvider) { + MOZ_ASSERT_UNREACHABLE("Trying to get on a static DrawableSurface?"); + return RawAccessFrameRef(); + } + + return mProvider->RawAccessRef(aFrame); + } + void Reset() { if (!mProvider) { diff --git a/image/SurfaceFilters.h b/image/SurfaceFilters.h index 495759b2fc05..ab4339402161 100644 --- a/image/SurfaceFilters.h +++ b/image/SurfaceFilters.h @@ -70,7 +70,7 @@ public: { } template - nsresult Configure(const DeinterlacingConfig& aConfig, Rest... aRest) + nsresult Configure(const DeinterlacingConfig& aConfig, const Rest&... aRest) { nsresult rv = mNext.Configure(aRest...); if (NS_FAILED(rv)) { @@ -360,7 +360,7 @@ public: { } template - nsresult Configure(const RemoveFrameRectConfig& aConfig, Rest... aRest) + nsresult Configure(const RemoveFrameRectConfig& aConfig, const Rest&... aRest) { nsresult rv = mNext.Configure(aRest...); if (NS_FAILED(rv)) { @@ -590,7 +590,7 @@ public: { } template - nsresult Configure(const ADAM7InterpolatingConfig& aConfig, Rest... aRest) + nsresult Configure(const ADAM7InterpolatingConfig& aConfig, const Rest&... aRest) { nsresult rv = mNext.Configure(aRest...); if (NS_FAILED(rv)) { diff --git a/image/SurfacePipe.cpp b/image/SurfacePipe.cpp index cd6c7fe6124c..06869c421cb6 100644 --- a/image/SurfacePipe.cpp +++ b/image/SurfacePipe.cpp @@ -75,10 +75,11 @@ SurfaceSink::Configure(const SurfaceConfig& aConfig) // XXX(seth): Once every Decoder subclass uses SurfacePipe, we probably want // to allocate the frame directly here and get rid of Decoder::AllocateFrame // altogether. - nsresult rv = aConfig.mDecoder->AllocateFrame(aConfig.mFrameNum, - surfaceSize, + nsresult rv = aConfig.mDecoder->AllocateFrame(surfaceSize, frameRect, - aConfig.mFormat); + aConfig.mFormat, + /* aPaletteDepth */ 0, + aConfig.mAnimParams); if (NS_FAILED(rv)) { return rv; } @@ -127,11 +128,11 @@ PalettedSurfaceSink::Configure(const PalettedSurfaceConfig& aConfig) // XXX(seth): Once every Decoder subclass uses SurfacePipe, we probably want // to allocate the frame directly here and get rid of Decoder::AllocateFrame // altogether. - nsresult rv = aConfig.mDecoder->AllocateFrame(aConfig.mFrameNum, - aConfig.mOutputSize, + nsresult rv = aConfig.mDecoder->AllocateFrame(aConfig.mOutputSize, aConfig.mFrameRect, aConfig.mFormat, - aConfig.mPaletteDepth); + aConfig.mPaletteDepth, + aConfig.mAnimParams); if (NS_FAILED(rv)) { return rv; } diff --git a/image/SurfacePipe.h b/image/SurfacePipe.h index fd2b5c823f01..cd4b3a1843d3 100644 --- a/image/SurfacePipe.h +++ b/image/SurfacePipe.h @@ -35,6 +35,8 @@ #include "mozilla/Variant.h" #include "mozilla/gfx/2D.h" +#include "AnimationParams.h" + namespace mozilla { namespace image { @@ -775,10 +777,10 @@ struct SurfaceConfig { using Filter = SurfaceSink; Decoder* mDecoder; /// Which Decoder to use to allocate the surface. - uint32_t mFrameNum; /// Which frame of animation this surface is for. gfx::IntSize mOutputSize; /// The size of the surface. gfx::SurfaceFormat mFormat; /// The surface format (BGRA or BGRX). bool mFlipVertically; /// If true, write the rows from bottom to top. + Maybe mAnimParams; /// Given for animated images. }; /** @@ -803,12 +805,12 @@ struct PalettedSurfaceConfig { using Filter = PalettedSurfaceSink; Decoder* mDecoder; /// Which Decoder to use to allocate the surface. - uint32_t mFrameNum; /// Which frame of animation this surface is for. gfx::IntSize mOutputSize; /// The logical size of the surface. gfx::IntRect mFrameRect; /// The surface subrect which contains data. gfx::SurfaceFormat mFormat; /// The surface format (BGRA or BGRX). uint8_t mPaletteDepth; /// The palette depth of this surface. bool mFlipVertically; /// If true, write the rows from bottom to top. + Maybe mAnimParams; /// Given for animated images. }; /** diff --git a/image/SurfacePipeFactory.h b/image/SurfacePipeFactory.h index ff53fec5c233..4571f2e1367f 100644 --- a/image/SurfacePipeFactory.h +++ b/image/SurfacePipeFactory.h @@ -70,8 +70,6 @@ public: * * @param aDecoder The decoder whose current frame the SurfacePipe will write * to. - * @param aFrameNum Which frame the SurfacePipe will write to. This will be 0 - * for non-animated images. * @param aInputSize The original size of the image. * @param aOutputSize The size the SurfacePipe should output. Must be the same * as @aInputSize or smaller. If smaller, the image will be @@ -79,6 +77,7 @@ public: * @param aFrameRect The portion of the image that actually contains data. * @param aFormat The surface format of the image; generally B8G8R8A8 or * B8G8R8X8. + * @param aAnimParams Extra parameters used by animated images. * @param aFlags Flags enabling or disabling various functionality for the * SurfacePipe; see the SurfacePipeFlags documentation for more * information. @@ -89,11 +88,11 @@ public: */ static Maybe CreateSurfacePipe(Decoder* aDecoder, - uint32_t aFrameNum, const nsIntSize& aInputSize, const nsIntSize& aOutputSize, const nsIntRect& aFrameRect, gfx::SurfaceFormat aFormat, + const Maybe& aAnimParams, SurfacePipeFlags aFlags) { const bool deinterlace = bool(aFlags & SurfacePipeFlags::DEINTERLACE); @@ -125,8 +124,8 @@ public: ADAM7InterpolatingConfig interpolatingConfig; RemoveFrameRectConfig removeFrameRectConfig { aFrameRect }; DownscalingConfig downscalingConfig { aInputSize, aFormat }; - SurfaceConfig surfaceConfig { aDecoder, aFrameNum, aOutputSize, - aFormat, flipVertically }; + SurfaceConfig surfaceConfig { aDecoder, aOutputSize, aFormat, + flipVertically, aAnimParams }; Maybe pipe; @@ -181,13 +180,12 @@ public: * * @param aDecoder The decoder whose current frame the SurfacePipe will write * to. - * @param aFrameNum Which frame the SurfacePipe will write to. This will be 0 - * for non-animated images. * @param aInputSize The original size of the image. * @param aFrameRect The portion of the image that actually contains data. * @param aFormat The surface format of the image; generally B8G8R8A8 or * B8G8R8X8. * @param aPaletteDepth The palette depth of the image. + * @param aAnimParams Extra parameters used by animated images. * @param aFlags Flags enabling or disabling various functionality for the * SurfacePipe; see the SurfacePipeFlags documentation for more * information. @@ -198,11 +196,11 @@ public: */ static Maybe CreatePalettedSurfacePipe(Decoder* aDecoder, - uint32_t aFrameNum, const nsIntSize& aInputSize, const nsIntRect& aFrameRect, gfx::SurfaceFormat aFormat, uint8_t aPaletteDepth, + const Maybe& aAnimParams, SurfacePipeFlags aFlags) { const bool deinterlace = bool(aFlags & SurfacePipeFlags::DEINTERLACE); @@ -211,9 +209,9 @@ public: // Construct configurations for the SurfaceFilters. DeinterlacingConfig deinterlacingConfig { progressiveDisplay }; - PalettedSurfaceConfig palettedSurfaceConfig { aDecoder, aFrameNum, aInputSize, - aFrameRect, aFormat, aPaletteDepth, - flipVertically }; + PalettedSurfaceConfig palettedSurfaceConfig { aDecoder, aInputSize, aFrameRect, + aFormat, aPaletteDepth, + flipVertically, aAnimParams }; Maybe pipe; @@ -229,7 +227,7 @@ public: private: template static Maybe - MakePipe(Configs... aConfigs) + MakePipe(const Configs&... aConfigs) { auto pipe = MakeUnique::Type>(); nsresult rv = pipe->Configure(aConfigs...); diff --git a/image/decoders/icon/nsIconURI.cpp b/image/decoders/icon/nsIconURI.cpp index 3c9e07f67f09..7b4cbd31ecad 100644 --- a/image/decoders/icon/nsIconURI.cpp +++ b/image/decoders/icon/nsIconURI.cpp @@ -715,7 +715,17 @@ nsMozIconURI::Deserialize(const URIParams& aParams) mContentType = params.contentType(); mFileName = params.fileName(); mStockIcon = params.stockIcon(); + + if (params.iconSize() < -1 || + params.iconSize() >= (int32_t) ArrayLength(kSizeStrings)) { + return false; + } mIconSize = params.iconSize(); + + if (params.iconState() < -1 || + params.iconState() >= (int32_t) ArrayLength(kStateStrings)) { + return false; + } mIconState = params.iconState(); return true; diff --git a/image/decoders/nsBMPDecoder.cpp b/image/decoders/nsBMPDecoder.cpp index bf1cce199499..4f37819d6a5e 100644 --- a/image/decoders/nsBMPDecoder.cpp +++ b/image/decoders/nsBMPDecoder.cpp @@ -685,8 +685,7 @@ nsBMPDecoder::ReadBitfields(const char* aData, size_t aLength) } MOZ_ASSERT(!mImageData, "Already have a buffer allocated?"); - nsresult rv = AllocateFrame(/* aFrameNum = */ 0, OutputSize(), - FullOutputFrame(), + nsresult rv = AllocateFrame(OutputSize(), FullOutputFrame(), mMayHaveTransparency ? SurfaceFormat::B8G8R8A8 : SurfaceFormat::B8G8R8X8); if (NS_FAILED(rv)) { diff --git a/image/decoders/nsGIFDecoder2.cpp b/image/decoders/nsGIFDecoder2.cpp index f649de48fa20..5eaf4a5e7a62 100644 --- a/image/decoders/nsGIFDecoder2.cpp +++ b/image/decoders/nsGIFDecoder2.cpp @@ -182,6 +182,14 @@ nsGIFDecoder2::BeginImageFrame(const IntRect& aFrameRect, // Make sure there's no animation if we're downscaling. MOZ_ASSERT_IF(Size() != OutputSize(), !GetImageMetadata().HasAnimation()); + AnimationParams animParams { + aFrameRect, + FrameTimeout::FromRawMilliseconds(mGIFStruct.delay_time), + uint32_t(mGIFStruct.images_decoded), + BlendMethod::OVER, + DisposalMethod(mGIFStruct.disposal_method) + }; + SurfacePipeFlags pipeFlags = aIsInterlaced ? SurfacePipeFlags::DEINTERLACE : SurfacePipeFlags(); @@ -196,9 +204,9 @@ nsGIFDecoder2::BeginImageFrame(const IntRect& aFrameRect, // The first frame is always decoded into an RGB surface. pipe = - SurfacePipeFactory::CreateSurfacePipe(this, mGIFStruct.images_decoded, - Size(), OutputSize(), - aFrameRect, format, pipeFlags); + SurfacePipeFactory::CreateSurfacePipe(this, Size(), OutputSize(), + aFrameRect, format, + Some(animParams), pipeFlags); } else { // This is an animation frame (and not the first). To minimize the memory // usage of animations, the image data is stored in paletted form. @@ -210,10 +218,10 @@ nsGIFDecoder2::BeginImageFrame(const IntRect& aFrameRect, // historically. MOZ_ASSERT(Size() == OutputSize()); pipe = - SurfacePipeFactory::CreatePalettedSurfacePipe(this, mGIFStruct.images_decoded, - Size(), aFrameRect, + SurfacePipeFactory::CreatePalettedSurfacePipe(this, Size(), aFrameRect, SurfaceFormat::B8G8R8A8, - aDepth, pipeFlags); + aDepth, Some(animParams), + pipeFlags); } mCurrentFrameIndex = mGIFStruct.images_decoded; @@ -254,9 +262,7 @@ nsGIFDecoder2::EndImageFrame() mGIFStruct.images_decoded++; // Tell the superclass we finished a frame - PostFrameStop(opacity, - DisposalMethod(mGIFStruct.disposal_method), - FrameTimeout::FromRawMilliseconds(mGIFStruct.delay_time)); + PostFrameStop(opacity); // Reset the transparent pixel if (mOldColor) { diff --git a/image/decoders/nsIconDecoder.cpp b/image/decoders/nsIconDecoder.cpp index 9ca63f5adb49..b186874c66d5 100644 --- a/image/decoders/nsIconDecoder.cpp +++ b/image/decoders/nsIconDecoder.cpp @@ -70,8 +70,9 @@ nsIconDecoder::ReadHeader(const char* aData) MOZ_ASSERT(!mImageData, "Already have a buffer allocated?"); Maybe pipe = - SurfacePipeFactory::CreateSurfacePipe(this, 0, Size(), OutputSize(), + SurfacePipeFactory::CreateSurfacePipe(this, Size(), OutputSize(), FullFrame(), SurfaceFormat::B8G8R8A8, + /* aAnimParams */ Nothing(), SurfacePipeFlags()); if (!pipe) { return Transition::TerminateFailure(); diff --git a/image/decoders/nsJPEGDecoder.cpp b/image/decoders/nsJPEGDecoder.cpp index c68577eb897c..c0662a98a51f 100644 --- a/image/decoders/nsJPEGDecoder.cpp +++ b/image/decoders/nsJPEGDecoder.cpp @@ -385,8 +385,8 @@ nsJPEGDecoder::ReadJPEGData(const char* aData, size_t aLength) jpeg_calc_output_dimensions(&mInfo); MOZ_ASSERT(!mImageData, "Already have a buffer allocated?"); - nsresult rv = AllocateFrame(/* aFrameNum = */ 0, OutputSize(), - FullOutputFrame(), SurfaceFormat::B8G8R8X8); + nsresult rv = AllocateFrame(OutputSize(), FullOutputFrame(), + SurfaceFormat::B8G8R8X8); if (NS_FAILED(rv)) { mState = JPEG_ERROR; MOZ_LOG(sJPEGDecoderAccountingLog, LogLevel::Debug, diff --git a/image/decoders/nsPNGDecoder.cpp b/image/decoders/nsPNGDecoder.cpp index 33e8c0e2b7db..d3cb2735c2ba 100644 --- a/image/decoders/nsPNGDecoder.cpp +++ b/image/decoders/nsPNGDecoder.cpp @@ -203,6 +203,25 @@ nsPNGDecoder::CreateFrame(const FrameInfo& aFrameInfo) MOZ_ASSERT_IF(Size() != OutputSize(), transparency != TransparencyType::eFrameRect); + Maybe animParams; +#ifdef PNG_APNG_SUPPORTED + if (png_get_valid(mPNG, mInfo, PNG_INFO_acTL)) { + mAnimInfo = AnimFrameInfo(mPNG, mInfo); + + if (mAnimInfo.mDispose == DisposalMethod::CLEAR) { + // We may have to display the background under this image during + // animation playback, so we regard it as transparent. + PostHasTransparency(); + } + + animParams.emplace(AnimationParams { + aFrameInfo.mFrameRect, + FrameTimeout::FromRawMilliseconds(mAnimInfo.mTimeout), + mNumFrames, mAnimInfo.mBlend, mAnimInfo.mDispose + }); + } +#endif + // If this image is interlaced, we can display better quality intermediate // results to the user by post processing them with ADAM7InterpolatingFilter. SurfacePipeFlags pipeFlags = aFrameInfo.mIsInterlaced @@ -215,9 +234,9 @@ nsPNGDecoder::CreateFrame(const FrameInfo& aFrameInfo) } Maybe pipe = - SurfacePipeFactory::CreateSurfacePipe(this, mNumFrames, Size(), - OutputSize(), aFrameInfo.mFrameRect, - mFormat, pipeFlags); + SurfacePipeFactory::CreateSurfacePipe(this, Size(), OutputSize(), + aFrameInfo.mFrameRect, mFormat, + animParams, pipeFlags); if (!pipe) { mPipe = SurfacePipe(); @@ -234,18 +253,6 @@ nsPNGDecoder::CreateFrame(const FrameInfo& aFrameInfo) "image frame with %dx%d pixels for decoder %p", mFrameRect.Width(), mFrameRect.Height(), this)); -#ifdef PNG_APNG_SUPPORTED - if (png_get_valid(mPNG, mInfo, PNG_INFO_acTL)) { - mAnimInfo = AnimFrameInfo(mPNG, mInfo); - - if (mAnimInfo.mDispose == DisposalMethod::CLEAR) { - // We may have to display the background under this image during - // animation playback, so we regard it as transparent. - PostHasTransparency(); - } - } -#endif - return NS_OK; } @@ -263,9 +270,7 @@ nsPNGDecoder::EndImageFrame() ? Opacity::FULLY_OPAQUE : Opacity::SOME_TRANSPARENCY; - PostFrameStop(opacity, mAnimInfo.mDispose, - FrameTimeout::FromRawMilliseconds(mAnimInfo.mTimeout), - mAnimInfo.mBlend, Some(mFrameRect)); + PostFrameStop(opacity); } nsresult diff --git a/image/imgFrame.cpp b/image/imgFrame.cpp index bd1b01d86b0f..fd7f02a6a0f5 100644 --- a/image/imgFrame.cpp +++ b/image/imgFrame.cpp @@ -203,12 +203,12 @@ imgFrame::imgFrame() : mMonitor("imgFrame") , mDecoded(0, 0, 0, 0) , mLockCount(0) - , mTimeout(FrameTimeout::FromRawMilliseconds(100)) - , mDisposalMethod(DisposalMethod::NOT_SPECIFIED) - , mBlendMethod(BlendMethod::OVER) , mAborted(false) , mFinished(false) , mOptimizable(false) + , mTimeout(FrameTimeout::FromRawMilliseconds(100)) + , mDisposalMethod(DisposalMethod::NOT_SPECIFIED) + , mBlendMethod(BlendMethod::OVER) , mPalettedImageData(nullptr) , mPaletteDepth(0) , mNonPremult(false) @@ -234,7 +234,7 @@ imgFrame::InitForDecoder(const nsIntSize& aImageSize, SurfaceFormat aFormat, uint8_t aPaletteDepth /* = 0 */, bool aNonPremult /* = false */, - bool aIsAnimated /* = false */) + const Maybe& aAnimParams /* = Nothing() */) { // Assert for properties that should be verified by decoders, // warn for properties related to bad content. @@ -247,6 +247,15 @@ imgFrame::InitForDecoder(const nsIntSize& aImageSize, mImageSize = aImageSize; mFrameRect = aRect; + if (aAnimParams) { + mBlendRect = aAnimParams->mBlendRect; + mTimeout = aAnimParams->mTimeout; + mBlendMethod = aAnimParams->mBlendMethod; + mDisposalMethod = aAnimParams->mDisposalMethod; + } else { + mBlendRect = aRect; + } + // We only allow a non-trivial frame rect (i.e., a frame rect that doesn't // cover the entire image) for paletted animation frames. We never draw those // frames directly; we just use FrameAnimator to composite them and produce a @@ -284,7 +293,8 @@ imgFrame::InitForDecoder(const nsIntSize& aImageSize, } else { MOZ_ASSERT(!mLockedSurface, "Called imgFrame::InitForDecoder() twice?"); - mRawSurface = AllocateBufferForImage(mFrameRect.Size(), mFormat, aIsAnimated); + bool postFirstFrame = aAnimParams && aAnimParams->mFrameNum > 0; + mRawSurface = AllocateBufferForImage(mFrameRect.Size(), mFormat, postFirstFrame); if (!mRawSurface) { mAborted = true; return NS_ERROR_OUT_OF_MEMORY; @@ -304,6 +314,13 @@ imgFrame::InitForDecoder(const nsIntSize& aImageSize, } } + if (aAnimParams) { + // We never want to unlock animated frames because we need the raw frame + // buffer for blending with future frames. Adding an extra unmatched lock + // here will guarantee that. + ++mLockCount; + } + return NS_OK; } @@ -485,21 +502,11 @@ imgFrame::DrawableRef() } RawAccessFrameRef -imgFrame::RawAccessRef() +imgFrame::RawAccessRef(bool aOnlyFinished /*= false*/) { - return RawAccessFrameRef(this); + return RawAccessFrameRef(this, aOnlyFinished); } -void -imgFrame::SetRawAccessOnly() -{ - AssertImageDataLocked(); - - // Lock our data and throw away the key. - LockImageData(); -} - - imgFrame::SurfaceWithFormat imgFrame::SurfaceForDrawing(bool aDoPartialDecode, bool aDoTile, @@ -627,20 +634,11 @@ imgFrame::ImageUpdatedInternal(const nsIntRect& aUpdateRect) void imgFrame::Finish(Opacity aFrameOpacity /* = Opacity::SOME_TRANSPARENCY */, - DisposalMethod aDisposalMethod /* = DisposalMethod::KEEP */, - FrameTimeout aTimeout - /* = FrameTimeout::FromRawMilliseconds(0) */, - BlendMethod aBlendMethod /* = BlendMethod::OVER */, - const Maybe& aBlendRect /* = Nothing() */, bool aFinalize /* = true */) { MonitorAutoLock lock(mMonitor); MOZ_ASSERT(mLockCount > 0, "Image data should be locked"); - mDisposalMethod = aDisposalMethod; - mTimeout = aTimeout; - mBlendMethod = aBlendMethod; - mBlendRect = aBlendRect; ImageUpdatedInternal(GetRect()); if (aFinalize) { @@ -746,35 +744,33 @@ imgFrame::GetPaletteData() const return data; } -nsresult -imgFrame::LockImageData() +uint8_t* +imgFrame::LockImageData(bool aOnlyFinished) { MonitorAutoLock lock(mMonitor); MOZ_ASSERT(mLockCount >= 0, "Unbalanced locks and unlocks"); - if (mLockCount < 0) { - return NS_ERROR_FAILURE; + if (mLockCount < 0 || (aOnlyFinished && !mFinished)) { + return nullptr; } - mLockCount++; - - // If we are not the first lock, there's nothing to do. - if (mLockCount != 1) { - return NS_OK; - } - - // If we're the first lock, but have the locked surface, we're OK. - if (mLockedSurface) { - return NS_OK; - } - - // Paletted images don't have surfaces, so there's nothing to do. + uint8_t* data; if (mPalettedImageData) { - return NS_OK; + data = mPalettedImageData; + } else if (mLockedSurface) { + data = mLockedSurface->GetData(); + } else { + data = nullptr; } - MOZ_ASSERT_UNREACHABLE("It's illegal to re-lock an optimized imgFrame"); - return NS_ERROR_FAILURE; + // If the raw data is still available, we should get a valid pointer for it. + if (!data) { + MOZ_ASSERT_UNREACHABLE("It's illegal to re-lock an optimized imgFrame"); + return nullptr; + } + + ++mLockCount; + return data; } void @@ -866,26 +862,6 @@ imgFrame::GetSourceSurfaceInternal() return CreateLockedSurface(mRawSurface, mFrameRect.Size(), mFormat); } -AnimationData -imgFrame::GetAnimationData() const -{ - MonitorAutoLock lock(mMonitor); - MOZ_ASSERT(mLockCount > 0, "Image data should be locked"); - - uint8_t* data; - if (mPalettedImageData) { - data = mPalettedImageData; - } else { - uint32_t length; - GetImageDataInternal(&data, &length); - } - - bool hasAlpha = mFormat == SurfaceFormat::B8G8R8A8; - - return AnimationData(data, PaletteDataLength(), mTimeout, GetRect(), - mBlendMethod, mBlendRect, mDisposalMethod, hasAlpha); -} - void imgFrame::Abort() { diff --git a/image/imgFrame.h b/image/imgFrame.h index b50451912e6a..72c9e4fd24c4 100644 --- a/image/imgFrame.h +++ b/image/imgFrame.h @@ -11,11 +11,10 @@ #include "mozilla/MemoryReporting.h" #include "mozilla/Monitor.h" #include "mozilla/Move.h" -#include "FrameTimeout.h" +#include "AnimationParams.h" #include "gfxDrawable.h" #include "imgIContainer.h" #include "MainThreadUtils.h" -#include "nsAutoPtr.h" namespace mozilla { namespace image { @@ -24,63 +23,11 @@ class ImageRegion; class DrawableFrameRef; class RawAccessFrameRef; -enum class BlendMethod : int8_t { - // All color components of the frame, including alpha, overwrite the current - // contents of the frame's output buffer region. - SOURCE, - - // The frame should be composited onto the output buffer based on its alpha, - // using a simple OVER operation. - OVER -}; - -enum class DisposalMethod : int8_t { - CLEAR_ALL = -1, // Clear the whole image, revealing what's underneath. - NOT_SPECIFIED, // Leave the frame and let the new frame draw on top. - KEEP, // Leave the frame and let the new frame draw on top. - CLEAR, // Clear the frame's area, revealing what's underneath. - RESTORE_PREVIOUS // Restore the previous (composited) frame. -}; - enum class Opacity : uint8_t { FULLY_OPAQUE, SOME_TRANSPARENCY }; -/** - * AnimationData contains all of the information necessary for using an imgFrame - * as part of an animation. - * - * It includes pointers to the raw image data of the underlying imgFrame, but - * does not own that data. A RawAccessFrameRef for the underlying imgFrame must - * outlive the AnimationData for it to remain valid. - */ -struct AnimationData -{ - AnimationData(uint8_t* aRawData, uint32_t aPaletteDataLength, - FrameTimeout aTimeout, const nsIntRect& aRect, - BlendMethod aBlendMethod, const Maybe& aBlendRect, - DisposalMethod aDisposalMethod, bool aHasAlpha) - : mRawData(aRawData) - , mPaletteDataLength(aPaletteDataLength) - , mTimeout(aTimeout) - , mRect(aRect) - , mBlendMethod(aBlendMethod) - , mBlendRect(aBlendRect) - , mDisposalMethod(aDisposalMethod) - , mHasAlpha(aHasAlpha) - { } - - uint8_t* mRawData; - uint32_t mPaletteDataLength; - FrameTimeout mTimeout; - nsIntRect mRect; - BlendMethod mBlendMethod; - Maybe mBlendRect; - DisposalMethod mDisposalMethod; - bool mHasAlpha; -}; - class imgFrame { typedef gfx::Color Color; @@ -112,13 +59,17 @@ public: SurfaceFormat aFormat, uint8_t aPaletteDepth = 0, bool aNonPremult = false, - bool aIsAnimated = false); + const Maybe& aAnimParams = Nothing()); nsresult InitForAnimator(const nsIntSize& aSize, SurfaceFormat aFormat) { - return InitForDecoder(aSize, nsIntRect(0, 0, aSize.width, aSize.height), - aFormat, 0, false, true); + nsIntRect frameRect(0, 0, aSize.width, aSize.height); + AnimationParams animParams { frameRect, FrameTimeout::Forever(), + /* aFrameNum */ 1, BlendMethod::OVER, + DisposalMethod::NOT_SPECIFIED }; + return InitForDecoder(aSize, frameRect, + aFormat, 0, false, Some(animParams)); } @@ -143,19 +94,14 @@ public: gfx::BackendType aBackend); DrawableFrameRef DrawableRef(); - RawAccessFrameRef RawAccessRef(); /** - * Make this imgFrame permanently available for raw access. + * Create a RawAccessFrameRef for the frame. * - * This is irrevocable, and should be avoided whenever possible, since it - * prevents this imgFrame from being optimized and makes it impossible for its - * volatile buffer to be freed. - * - * It is an error to call this without already holding a RawAccessFrameRef to - * this imgFrame. + * @param aOnlyFinished If true, only return a valid RawAccessFrameRef if + * imgFrame::Finish has been called. */ - void SetRawAccessOnly(); + RawAccessFrameRef RawAccessRef(bool aOnlyFinished = false); bool Draw(gfxContext* aContext, const ImageRegion& aRegion, SamplingFilter aSamplingFilter, uint32_t aImageFlags, @@ -170,24 +116,10 @@ public: * RawAccessFrameRef pointing to an imgFrame. * * @param aFrameOpacity Whether this imgFrame is opaque. - * @param aDisposalMethod For animation frames, how this imgFrame is cleared - * from the compositing frame before the next frame is - * displayed. - * @param aTimeout For animation frames, the timeout before the next - * frame is displayed. - * @param aBlendMethod For animation frames, a blending method to be used - * when compositing this frame. - * @param aBlendRect For animation frames, if present, the subrect in - * which @aBlendMethod applies. Outside of this - * subrect, BlendMethod::OVER is always used. * @param aFinalize Finalize the underlying surface (e.g. so that it * may be marked as read only if possible). */ void Finish(Opacity aFrameOpacity = Opacity::SOME_TRANSPARENCY, - DisposalMethod aDisposalMethod = DisposalMethod::KEEP, - FrameTimeout aTimeout = FrameTimeout::FromRawMilliseconds(0), - BlendMethod aBlendMethod = BlendMethod::OVER, - const Maybe& aBlendRect = Nothing(), bool aFinalize = true); /** @@ -227,9 +159,15 @@ public: */ uint32_t GetBytesPerPixel() const { return GetIsPaletted() ? 1 : 4; } - IntSize GetImageSize() const { return mImageSize; } - IntRect GetRect() const { return mFrameRect; } + const IntSize& GetImageSize() const { return mImageSize; } + const IntRect& GetRect() const { return mFrameRect; } IntSize GetSize() const { return mFrameRect.Size(); } + const IntRect& GetBlendRect() const { return mBlendRect; } + IntRect GetBoundedBlendRect() const { return mBlendRect.Intersect(mFrameRect); } + FrameTimeout GetTimeout() const { return mTimeout; } + BlendMethod GetBlendMethod() const { return mBlendMethod; } + DisposalMethod GetDisposalMethod() const { return mDisposalMethod; } + bool FormatHasAlpha() const { return mFormat == SurfaceFormat::B8G8R8A8; } void GetImageData(uint8_t** aData, uint32_t* length) const; uint8_t* GetImageData() const; @@ -238,8 +176,6 @@ public: uint32_t* GetPaletteData() const; uint8_t GetPaletteDepth() const { return mPaletteDepth; } - AnimationData GetAnimationData() const; - bool GetCompositingFailed() const; void SetCompositingFailed(bool val); @@ -256,7 +192,15 @@ private: // methods ~imgFrame(); - nsresult LockImageData(); + /** + * Used when the caller desires raw access to the underlying frame buffer. + * If the locking succeeds, the data pointer to the start of the buffer is + * returned, else it returns nullptr. + * + * @param aOnlyFinished If true, only attempt to lock if imgFrame::Finish has + * been called. + */ + uint8_t* LockImageData(bool aOnlyFinished); nsresult UnlockImageData(); nsresult Optimize(gfx::DrawTarget* aTarget); @@ -327,14 +271,6 @@ private: // data //! Number of RawAccessFrameRefs currently alive for this imgFrame. int32_t mLockCount; - //! The timeout for this frame. - FrameTimeout mTimeout; - - DisposalMethod mDisposalMethod; - BlendMethod mBlendMethod; - Maybe mBlendRect; - SurfaceFormat mFormat; - bool mAborted; bool mFinished; bool mOptimizable; @@ -346,6 +282,14 @@ private: // data IntSize mImageSize; IntRect mFrameRect; + IntRect mBlendRect; + + //! The timeout for this frame. + FrameTimeout mTimeout; + + DisposalMethod mDisposalMethod; + BlendMethod mBlendMethod; + SurfaceFormat mFormat; // The palette and image data for images that are paletted, since Cairo // doesn't support these images. @@ -381,20 +325,16 @@ public: { MOZ_ASSERT(aFrame); MonitorAutoLock lock(aFrame->mMonitor); + MOZ_ASSERT(!aFrame->GetIsPaletted(), "Paletted must use RawAccessFrameRef"); - // Paletted images won't have a surface so there is no strong reference - // to hold on to. Since Draw() and GetSourceSurface() calls will not work - // in that case, we should be using RawAccessFrameRef exclusively instead. - // See FrameAnimator::GetRawFrame for an example of this behaviour. if (aFrame->mRawSurface) { - mRef = new DataSourceSurface::ScopedMap(aFrame->mRawSurface, - DataSourceSurface::READ_WRITE); + mRef.emplace(aFrame->mRawSurface, DataSourceSurface::READ); if (!mRef->IsMapped()) { mFrame = nullptr; - mRef = nullptr; + mRef.reset(); } } else { - MOZ_ASSERT(aFrame->mOptSurface || aFrame->GetIsPaletted()); + MOZ_ASSERT(aFrame->mOptSurface); } } @@ -431,14 +371,15 @@ public: void reset() { mFrame = nullptr; - mRef = nullptr; + mRef.reset(); } private: DrawableFrameRef(const DrawableFrameRef& aOther) = delete; + DrawableFrameRef& operator=(const DrawableFrameRef& aOther) = delete; RefPtr mFrame; - nsAutoPtr mRef; + Maybe mRef; }; /** @@ -459,22 +400,27 @@ private: class RawAccessFrameRef final { public: - RawAccessFrameRef() { } + RawAccessFrameRef() : mData(nullptr) { } - explicit RawAccessFrameRef(imgFrame* aFrame) + explicit RawAccessFrameRef(imgFrame* aFrame, + bool aOnlyFinished) : mFrame(aFrame) + , mData(nullptr) { MOZ_ASSERT(mFrame, "Need a frame"); - if (NS_FAILED(mFrame->LockImageData())) { - mFrame->UnlockImageData(); + mData = mFrame->LockImageData(aOnlyFinished); + if (!mData) { mFrame = nullptr; } } RawAccessFrameRef(RawAccessFrameRef&& aOther) : mFrame(aOther.mFrame.forget()) - { } + , mData(aOther.mData) + { + aOther.mData = nullptr; + } ~RawAccessFrameRef() { @@ -492,6 +438,8 @@ public: } mFrame = aOther.mFrame.forget(); + mData = aOther.mData; + aOther.mData = nullptr; return *this; } @@ -519,12 +467,18 @@ public: mFrame->UnlockImageData(); } mFrame = nullptr; + mData = nullptr; } + uint8_t* Data() const { return mData; } + uint32_t PaletteDataLength() const { return mFrame->PaletteDataLength(); } + private: RawAccessFrameRef(const RawAccessFrameRef& aOther) = delete; + RawAccessFrameRef& operator=(const RawAccessFrameRef& aOther) = delete; RefPtr mFrame; + uint8_t* mData; }; } // namespace image diff --git a/image/test/gtest/Common.h b/image/test/gtest/Common.h index e256f5259dc2..542629cc1718 100644 --- a/image/test/gtest/Common.h +++ b/image/test/gtest/Common.h @@ -241,7 +241,7 @@ already_AddRefed CreateTrivialDecoder(); * @param aConfigs The configuration for the pipeline. */ template -void WithFilterPipeline(Decoder* aDecoder, Func aFunc, Configs... aConfigs) +void WithFilterPipeline(Decoder* aDecoder, Func aFunc, const Configs&... aConfigs) { auto pipe = MakeUnique::Type>(); nsresult rv = pipe->Configure(aConfigs...); @@ -264,7 +264,7 @@ void WithFilterPipeline(Decoder* aDecoder, Func aFunc, Configs... aConfigs) * @param aConfigs The configuration for the pipeline. */ template -void AssertConfiguringPipelineFails(Decoder* aDecoder, Configs... aConfigs) +void AssertConfiguringPipelineFails(Decoder* aDecoder, const Configs&... aConfigs) { auto pipe = MakeUnique::Type>(); nsresult rv = pipe->Configure(aConfigs...); diff --git a/image/test/gtest/TestADAM7InterpolatingFilter.cpp b/image/test/gtest/TestADAM7InterpolatingFilter.cpp index d9dab43465da..d11224251e54 100644 --- a/image/test/gtest/TestADAM7InterpolatingFilter.cpp +++ b/image/test/gtest/TestADAM7InterpolatingFilter.cpp @@ -33,7 +33,7 @@ WithADAM7InterpolatingFilter(const IntSize& aSize, Func aFunc) WithFilterPipeline(decoder, Forward(aFunc), ADAM7InterpolatingConfig { }, - SurfaceConfig { decoder, 0, aSize, + SurfaceConfig { decoder, aSize, SurfaceFormat::B8G8R8A8, false }); } @@ -45,7 +45,7 @@ AssertConfiguringADAM7InterpolatingFilterFails(const IntSize& aSize) AssertConfiguringPipelineFails(decoder, ADAM7InterpolatingConfig { }, - SurfaceConfig { decoder, 0, aSize, + SurfaceConfig { decoder, aSize, SurfaceFormat::B8G8R8A8, false }); } @@ -664,7 +664,7 @@ TEST(ImageADAM7InterpolatingFilter, ConfiguringPalettedADAM7InterpolatingFilterF // should fail. AssertConfiguringPipelineFails(decoder, ADAM7InterpolatingConfig { }, - PalettedSurfaceConfig { decoder, 0, IntSize(100, 100), + PalettedSurfaceConfig { decoder, IntSize(100, 100), IntRect(0, 0, 50, 50), SurfaceFormat::B8G8R8A8, 8, false }); diff --git a/image/test/gtest/TestAnimationFrameBuffer.cpp b/image/test/gtest/TestAnimationFrameBuffer.cpp index e8fc495cc6da..5a3f80f7bfc1 100644 --- a/image/test/gtest/TestAnimationFrameBuffer.cpp +++ b/image/test/gtest/TestAnimationFrameBuffer.cpp @@ -148,8 +148,8 @@ TEST_F(ImageAnimationFrameBuffer, FinishUnderBatchAndThreshold) EXPECT_FALSE(buffer.MayDiscard()); - DrawableFrameRef gotFrame = buffer.Get(i); - EXPECT_EQ(frame.get(), gotFrame.get()); + imgFrame* gotFrame = buffer.Get(i); + EXPECT_EQ(frame.get(), gotFrame); ASSERT_EQ(i + 1, frames.Length()); EXPECT_EQ(frame.get(), frames[i].get()); @@ -164,13 +164,12 @@ TEST_F(ImageAnimationFrameBuffer, FinishUnderBatchAndThreshold) } gotFrame = buffer.Get(0); - EXPECT_EQ(firstFrame.get(), gotFrame.get()); + EXPECT_EQ(firstFrame.get(), gotFrame); } // Loop again over the animation and make sure it is still all there. for (size_t i = 0; i < frames.Length(); ++i) { - DrawableFrameRef gotFrame = buffer.Get(i); - EXPECT_TRUE(gotFrame); + EXPECT_TRUE(buffer.Get(i) != nullptr); bool restartDecoder = buffer.AdvanceTo(i); EXPECT_FALSE(restartDecoder); @@ -202,8 +201,7 @@ TEST_F(ImageAnimationFrameBuffer, FinishMultipleBatchesUnderThreshold) bool restartDecoder = false; size_t i = 0; do { - DrawableFrameRef gotFrame = buffer.Get(i); - EXPECT_TRUE(gotFrame); + EXPECT_TRUE(buffer.Get(i) != nullptr); if (i > 0) { restartDecoder = buffer.AdvanceTo(i); } @@ -225,24 +223,21 @@ TEST_F(ImageAnimationFrameBuffer, FinishMultipleBatchesUnderThreshold) // Finish progressing through the animation. for ( ; i < frames.Length(); ++i) { - DrawableFrameRef gotFrame = buffer.Get(i); - EXPECT_TRUE(gotFrame); + EXPECT_TRUE(buffer.Get(i) != nullptr); restartDecoder = buffer.AdvanceTo(i); EXPECT_FALSE(restartDecoder); } // Loop again over the animation and make sure it is still all there. for (i = 0; i < frames.Length(); ++i) { - DrawableFrameRef gotFrame = buffer.Get(i); - EXPECT_TRUE(gotFrame); + EXPECT_TRUE(buffer.Get(i) != nullptr); restartDecoder = buffer.AdvanceTo(i); EXPECT_FALSE(restartDecoder); } // Loop to the third frame and then reset the animation. for (i = 0; i < 3; ++i) { - DrawableFrameRef gotFrame = buffer.Get(i); - EXPECT_TRUE(gotFrame); + EXPECT_TRUE(buffer.Get(i) != nullptr); restartDecoder = buffer.AdvanceTo(i); EXPECT_FALSE(restartDecoder); } @@ -282,8 +277,7 @@ TEST_F(ImageAnimationFrameBuffer, MayDiscard) bool restartDecoder = false; size_t i = 0; do { - DrawableFrameRef gotFrame = buffer.Get(i); - EXPECT_TRUE(gotFrame); + EXPECT_TRUE(buffer.Get(i) != nullptr); if (i > 0) { restartDecoder = buffer.AdvanceTo(i); } @@ -312,8 +306,7 @@ TEST_F(ImageAnimationFrameBuffer, MayDiscard) // Progress through the animation so more. Make sure it removes frames as we // go along. do { - DrawableFrameRef gotFrame = buffer.Get(i); - EXPECT_TRUE(gotFrame); + EXPECT_TRUE(buffer.Get(i) != nullptr); restartDecoder = buffer.AdvanceTo(i); EXPECT_FALSE(frames[i - 1]); EXPECT_TRUE(frames[i]); @@ -349,8 +342,7 @@ TEST_F(ImageAnimationFrameBuffer, MayDiscard) i = 0; } - DrawableFrameRef gotFrame = buffer.Get(i); - if (!gotFrame) { + if (!buffer.Get(i)) { break; } @@ -368,8 +360,7 @@ TEST_F(ImageAnimationFrameBuffer, MayDiscard) EXPECT_EQ(size_t(0), buffer.PendingDecode()); // Can we retry advancing again? - DrawableFrameRef gotFrame = buffer.Get(i); - EXPECT_TRUE(gotFrame); + EXPECT_TRUE(buffer.Get(i) != nullptr); restartDecoder = buffer.AdvanceTo(i); EXPECT_EQ(size_t(2), buffer.Displayed()); EXPECT_FALSE(frames[i - 1]); diff --git a/image/test/gtest/TestDecoders.cpp b/image/test/gtest/TestDecoders.cpp index e054770bc5c4..f47553baecdf 100644 --- a/image/test/gtest/TestDecoders.cpp +++ b/image/test/gtest/TestDecoders.cpp @@ -467,8 +467,8 @@ TEST_F(ImageDecoders, AnimatedGIFWithFRAME_FIRST) EXPECT_TRUE(NS_SUCCEEDED(result.Surface().Seek(0))); EXPECT_TRUE(bool(result.Surface())); - EXPECT_TRUE(NS_SUCCEEDED(result.Surface().Seek(1))); - EXPECT_TRUE(bool(result.Surface())); + RawAccessFrameRef partialFrame = result.Surface().RawAccessRef(1); + EXPECT_TRUE(bool(partialFrame)); } // Ensure that the static version is still around. @@ -553,8 +553,8 @@ TEST_F(ImageDecoders, AnimatedGIFWithFRAME_CURRENT) EXPECT_TRUE(NS_SUCCEEDED(result.Surface().Seek(0))); EXPECT_TRUE(bool(result.Surface())); - EXPECT_TRUE(NS_SUCCEEDED(result.Surface().Seek(1))); - EXPECT_TRUE(bool(result.Surface())); + RawAccessFrameRef partialFrame = result.Surface().RawAccessRef(1); + EXPECT_TRUE(bool(partialFrame)); } // Ensure that we didn't decode the static version of the image. @@ -596,8 +596,8 @@ TEST_F(ImageDecoders, AnimatedGIFWithFRAME_CURRENT) EXPECT_TRUE(NS_SUCCEEDED(result.Surface().Seek(0))); EXPECT_TRUE(bool(result.Surface())); - EXPECT_TRUE(NS_SUCCEEDED(result.Surface().Seek(1))); - EXPECT_TRUE(bool(result.Surface())); + RawAccessFrameRef partialFrame = result.Surface().RawAccessRef(1); + EXPECT_TRUE(bool(partialFrame)); } } @@ -665,8 +665,8 @@ TEST_F(ImageDecoders, AnimatedGIFWithExtraImageSubBlocks) EXPECT_TRUE(NS_SUCCEEDED(result.Surface().Seek(0))); EXPECT_TRUE(bool(result.Surface())); - EXPECT_TRUE(NS_SUCCEEDED(result.Surface().Seek(1))); - EXPECT_TRUE(bool(result.Surface())); + RawAccessFrameRef partialFrame = result.Surface().RawAccessRef(1); + EXPECT_TRUE(bool(partialFrame)); } TEST_F(ImageDecoders, TruncatedSmallGIFSingleChunk) diff --git a/image/test/gtest/TestDeinterlacingFilter.cpp b/image/test/gtest/TestDeinterlacingFilter.cpp index 30cad7993516..82637bbf7149 100644 --- a/image/test/gtest/TestDeinterlacingFilter.cpp +++ b/image/test/gtest/TestDeinterlacingFilter.cpp @@ -28,7 +28,7 @@ WithDeinterlacingFilter(const IntSize& aSize, WithFilterPipeline(decoder, Forward(aFunc), DeinterlacingConfig { aProgressiveDisplay }, - SurfaceConfig { decoder, 0, aSize, + SurfaceConfig { decoder, aSize, SurfaceFormat::B8G8R8A8, false }); } @@ -41,7 +41,7 @@ WithPalettedDeinterlacingFilter(const IntSize& aSize, WithFilterPipeline(decoder, Forward(aFunc), DeinterlacingConfig { /* mProgressiveDisplay = */ true }, - PalettedSurfaceConfig { decoder, 0, aSize, + PalettedSurfaceConfig { decoder, aSize, IntRect(0, 0, 100, 100), SurfaceFormat::B8G8R8A8, 8, false }); @@ -55,7 +55,7 @@ AssertConfiguringDeinterlacingFilterFails(const IntSize& aSize) AssertConfiguringPipelineFails(decoder, DeinterlacingConfig { /* mProgressiveDisplay = */ true}, - SurfaceConfig { decoder, 0, aSize, + SurfaceConfig { decoder, aSize, SurfaceFormat::B8G8R8A8, false }); } diff --git a/image/test/gtest/TestDownscalingFilter.cpp b/image/test/gtest/TestDownscalingFilter.cpp index 596becab0be5..d7aa0ead2a30 100644 --- a/image/test/gtest/TestDownscalingFilter.cpp +++ b/image/test/gtest/TestDownscalingFilter.cpp @@ -29,7 +29,7 @@ WithDownscalingFilter(const IntSize& aInputSize, WithFilterPipeline(decoder, Forward(aFunc), DownscalingConfig { aInputSize, SurfaceFormat::B8G8R8A8 }, - SurfaceConfig { decoder, 0, aOutputSize, + SurfaceConfig { decoder, aOutputSize, SurfaceFormat::B8G8R8A8, false }); } @@ -43,7 +43,7 @@ AssertConfiguringDownscalingFilterFails(const IntSize& aInputSize, AssertConfiguringPipelineFails(decoder, DownscalingConfig { aInputSize, SurfaceFormat::B8G8R8A8 }, - SurfaceConfig { decoder, 0, aOutputSize, + SurfaceConfig { decoder, aOutputSize, SurfaceFormat::B8G8R8A8, false }); } @@ -224,7 +224,7 @@ TEST(ImageDownscalingFilter, ConfiguringPalettedDownscaleFails) AssertConfiguringPipelineFails(decoder, DownscalingConfig { IntSize(100, 100), SurfaceFormat::B8G8R8A8 }, - PalettedSurfaceConfig { decoder, 0, IntSize(20, 20), + PalettedSurfaceConfig { decoder, IntSize(20, 20), IntRect(0, 0, 20, 20), SurfaceFormat::B8G8R8A8, 8, false }); diff --git a/image/test/gtest/TestDownscalingFilterNoSkia.cpp b/image/test/gtest/TestDownscalingFilterNoSkia.cpp index c62ca018da1f..80928a880985 100644 --- a/image/test/gtest/TestDownscalingFilterNoSkia.cpp +++ b/image/test/gtest/TestDownscalingFilterNoSkia.cpp @@ -52,6 +52,6 @@ TEST(ImageDownscalingFilter, NoSkia) AssertConfiguringPipelineFails(decoder, DownscalingConfig { IntSize(100, 100), SurfaceFormat::B8G8R8A8 }, - SurfaceConfig { decoder, 0, IntSize(50, 50), + SurfaceConfig { decoder, IntSize(50, 50), SurfaceFormat::B8G8R8A8, false }); } diff --git a/image/test/gtest/TestMetadata.cpp b/image/test/gtest/TestMetadata.cpp index 088a7df709d7..be36fe0a5637 100644 --- a/image/test/gtest/TestMetadata.cpp +++ b/image/test/gtest/TestMetadata.cpp @@ -255,6 +255,6 @@ TEST_F(ImageDecoderMetadata, NoFrameDelayGIFFullDecode) EXPECT_TRUE(NS_SUCCEEDED(result.Surface().Seek(0))); EXPECT_TRUE(bool(result.Surface())); - EXPECT_TRUE(NS_SUCCEEDED(result.Surface().Seek(1))); - EXPECT_TRUE(bool(result.Surface())); + RawAccessFrameRef partialFrame = result.Surface().RawAccessRef(1); + EXPECT_TRUE(bool(partialFrame)); } diff --git a/image/test/gtest/TestRemoveFrameRectFilter.cpp b/image/test/gtest/TestRemoveFrameRectFilter.cpp index e1def590e5d4..ad1f944fc4a0 100644 --- a/image/test/gtest/TestRemoveFrameRectFilter.cpp +++ b/image/test/gtest/TestRemoveFrameRectFilter.cpp @@ -28,7 +28,7 @@ WithRemoveFrameRectFilter(const IntSize& aSize, WithFilterPipeline(decoder, Forward(aFunc), RemoveFrameRectConfig { aFrameRect }, - SurfaceConfig { decoder, 0, aSize, + SurfaceConfig { decoder, aSize, SurfaceFormat::B8G8R8A8, false }); } @@ -41,7 +41,7 @@ AssertConfiguringRemoveFrameRectFilterFails(const IntSize& aSize, AssertConfiguringPipelineFails(decoder, RemoveFrameRectConfig { aFrameRect }, - SurfaceConfig { decoder, 0, aSize, + SurfaceConfig { decoder, aSize, SurfaceFormat::B8G8R8A8, false }); } @@ -320,7 +320,7 @@ TEST(ImageRemoveFrameRectFilter, ConfiguringPalettedRemoveFrameRectFails) // should fail. AssertConfiguringPipelineFails(decoder, RemoveFrameRectConfig { IntRect(0, 0, 50, 50) }, - PalettedSurfaceConfig { decoder, 0, IntSize(100, 100), + PalettedSurfaceConfig { decoder, IntSize(100, 100), IntRect(0, 0, 50, 50), SurfaceFormat::B8G8R8A8, 8, false }); diff --git a/image/test/gtest/TestSurfacePipeIntegration.cpp b/image/test/gtest/TestSurfacePipeIntegration.cpp index ac8ba8600cb0..1996a30f6884 100644 --- a/image/test/gtest/TestSurfacePipeIntegration.cpp +++ b/image/test/gtest/TestSurfacePipeIntegration.cpp @@ -149,7 +149,7 @@ TEST_F(ImageSurfacePipeIntegration, SurfacePipe) auto sink = MakeUnique(); nsresult rv = - sink->Configure(SurfaceConfig { decoder, 0, IntSize(100, 100), + sink->Configure(SurfaceConfig { decoder, IntSize(100, 100), SurfaceFormat::B8G8R8A8, false }); ASSERT_TRUE(NS_SUCCEEDED(rv)); @@ -243,7 +243,7 @@ TEST_F(ImageSurfacePipeIntegration, PalettedSurfacePipe) auto sink = MakeUnique(); nsresult rv = - sink->Configure(PalettedSurfaceConfig { decoder, 0, IntSize(100, 100), + sink->Configure(PalettedSurfaceConfig { decoder, IntSize(100, 100), IntRect(0, 0, 100, 100), SurfaceFormat::B8G8R8A8, 8, false }); @@ -345,7 +345,7 @@ TEST_F(ImageSurfacePipeIntegration, DeinterlaceDownscaleWritePixels) DeinterlacingConfig { /* mProgressiveDisplay = */ true }, DownscalingConfig { IntSize(100, 100), SurfaceFormat::B8G8R8A8 }, - SurfaceConfig { decoder, 0, IntSize(25, 25), + SurfaceConfig { decoder, IntSize(25, 25), SurfaceFormat::B8G8R8A8, false }); } @@ -401,7 +401,7 @@ TEST_F(ImageSurfacePipeIntegration, RemoveFrameRectBottomRightDownscaleWritePixe RemoveFrameRectConfig { IntRect(50, 50, 100, 100) }, DownscalingConfig { IntSize(100, 100), SurfaceFormat::B8G8R8A8 }, - SurfaceConfig { decoder, 0, IntSize(20, 20), + SurfaceConfig { decoder, IntSize(20, 20), SurfaceFormat::B8G8R8A8, false }); } @@ -435,7 +435,7 @@ TEST_F(ImageSurfacePipeIntegration, RemoveFrameRectTopLeftDownscaleWritePixels) RemoveFrameRectConfig { IntRect(-50, -50, 100, 100) }, DownscalingConfig { IntSize(100, 100), SurfaceFormat::B8G8R8A8 }, - SurfaceConfig { decoder, 0, IntSize(20, 20), + SurfaceConfig { decoder, IntSize(20, 20), SurfaceFormat::B8G8R8A8, false }); } @@ -459,7 +459,7 @@ TEST_F(ImageSurfacePipeIntegration, DeinterlaceRemoveFrameRectWritePixels) WithFilterPipeline(decoder, test, DeinterlacingConfig { /* mProgressiveDisplay = */ true }, RemoveFrameRectConfig { IntRect(50, 50, 100, 100) }, - SurfaceConfig { decoder, 0, IntSize(100, 100), + SurfaceConfig { decoder, IntSize(100, 100), SurfaceFormat::B8G8R8A8, false }); } @@ -482,7 +482,7 @@ TEST_F(ImageSurfacePipeIntegration, DeinterlaceRemoveFrameRectDownscaleWritePixe RemoveFrameRectConfig { IntRect(50, 50, 100, 100) }, DownscalingConfig { IntSize(100, 100), SurfaceFormat::B8G8R8A8 }, - SurfaceConfig { decoder, 0, IntSize(20, 20), + SurfaceConfig { decoder, IntSize(20, 20), SurfaceFormat::B8G8R8A8, false }); } @@ -497,7 +497,7 @@ TEST_F(ImageSurfacePipeIntegration, ConfiguringPalettedRemoveFrameRectDownscaleF RemoveFrameRectConfig { IntRect(0, 0, 50, 50) }, DownscalingConfig { IntSize(100, 100), SurfaceFormat::B8G8R8A8 }, - PalettedSurfaceConfig { decoder, 0, IntSize(100, 100), + PalettedSurfaceConfig { decoder, IntSize(100, 100), IntRect(0, 0, 50, 50), SurfaceFormat::B8G8R8A8, 8, false }); @@ -514,7 +514,7 @@ TEST_F(ImageSurfacePipeIntegration, ConfiguringPalettedDeinterlaceDownscaleFails DeinterlacingConfig { /* mProgressiveDisplay = */ true}, DownscalingConfig { IntSize(100, 100), SurfaceFormat::B8G8R8A8 }, - PalettedSurfaceConfig { decoder, 0, IntSize(100, 100), + PalettedSurfaceConfig { decoder, IntSize(100, 100), IntRect(0, 0, 20, 20), SurfaceFormat::B8G8R8A8, 8, false }); @@ -535,6 +535,6 @@ TEST_F(ImageSurfacePipeIntegration, ConfiguringHugeDeinterlacingBufferFails) DeinterlacingConfig { /* mProgressiveDisplay = */ true}, DownscalingConfig { IntSize(60000, 60000), SurfaceFormat::B8G8R8A8 }, - SurfaceConfig { decoder, 0, IntSize(600, 600), + SurfaceConfig { decoder, IntSize(600, 600), SurfaceFormat::B8G8R8A8, false }); } diff --git a/image/test/gtest/TestSurfaceSink.cpp b/image/test/gtest/TestSurfaceSink.cpp index 2b7cf61bad15..0000d7e50d51 100644 --- a/image/test/gtest/TestSurfaceSink.cpp +++ b/image/test/gtest/TestSurfaceSink.cpp @@ -32,7 +32,7 @@ WithSurfaceSink(Func aFunc) const bool flipVertically = Orientation == Orient::FLIP_VERTICALLY; WithFilterPipeline(decoder, Forward(aFunc), - SurfaceConfig { decoder, 0, IntSize(100, 100), + SurfaceConfig { decoder, IntSize(100, 100), SurfaceFormat::B8G8R8A8, flipVertically }); } @@ -43,7 +43,7 @@ WithPalettedSurfaceSink(const IntRect& aFrameRect, Func aFunc) ASSERT_TRUE(decoder != nullptr); WithFilterPipeline(decoder, Forward(aFunc), - PalettedSurfaceConfig { decoder, 0, IntSize(100, 100), + PalettedSurfaceConfig { decoder, IntSize(100, 100), aFrameRect, SurfaceFormat::B8G8R8A8, 8, false }); } diff --git a/js/public/RootingAPI.h b/js/public/RootingAPI.h index 7f51225aa7ba..c0b035951ae9 100644 --- a/js/public/RootingAPI.h +++ b/js/public/RootingAPI.h @@ -719,6 +719,10 @@ struct BarrierMethods static void postBarrier(JSString** vp, JSString* prev, JSString* next) { JS::HeapStringPostBarrier(vp, prev, next); } + static void exposeToJS(JSString* v) { + if (v) + js::gc::ExposeGCThingToActiveJS(JS::GCCellPtr(v)); + } }; // Provide hash codes for Cell kinds that may be relocated and, thus, not have diff --git a/js/src/builtin/Array.cpp b/js/src/builtin/Array.cpp index aeb2919a2ee0..2163d5218042 100644 --- a/js/src/builtin/Array.cpp +++ b/js/src/builtin/Array.cpp @@ -3555,7 +3555,7 @@ static const JSFunctionSpec array_methods[] = { #ifdef NIGHTLY_BUILD JS_SELF_HOSTED_FN("flatMap", "ArrayFlatMap", 1,0), - JS_SELF_HOSTED_FN("flatten", "ArrayFlatten", 0,0), + JS_SELF_HOSTED_FN("flat", "ArrayFlat", 0,0), #endif JS_FS_END diff --git a/js/src/builtin/Array.js b/js/src/builtin/Array.js index 6a34ca455ec5..9ffcdc404538 100644 --- a/js/src/builtin/Array.js +++ b/js/src/builtin/Array.js @@ -1133,8 +1133,8 @@ function ArrayFlatMap(mapperFunction/*, thisArg*/) { } // https://tc39.github.io/proposal-flatMap/ -// January 16, 2018 -function ArrayFlatten(/* depth */) { +// May 23, 2018 +function ArrayFlat(/* depth */) { // Step 1. var O = ToObject(this); diff --git a/js/src/builtin/Eval.cpp b/js/src/builtin/Eval.cpp index db173426ef62..16e84fb7fa9b 100644 --- a/js/src/builtin/Eval.cpp +++ b/js/src/builtin/Eval.cpp @@ -137,35 +137,29 @@ template static bool EvalStringMightBeJSON(const mozilla::Range chars) { - // If the eval string starts with '(' or '[' and ends with ')' or ']', it may be JSON. - // Try the JSON parser first because it's much faster. If the eval string - // isn't JSON, JSON parsing will probably fail quickly, so little time - // will be lost. + // If the eval string starts with '(' or '[' and ends with ')' or ']', it + // may be JSON. Try the JSON parser first because it's much faster. If + // the eval string isn't JSON, JSON parsing will probably fail quickly, so + // little time will be lost. size_t length = chars.length(); - if (length > 2 && - ((chars[0] == '[' && chars[length - 1] == ']') || - (chars[0] == '(' && chars[length - 1] == ')'))) - { - // Remarkably, JavaScript syntax is not a superset of JSON syntax: - // strings in JavaScript cannot contain the Unicode line and paragraph - // terminator characters U+2028 and U+2029, but strings in JSON can. - // Rather than force the JSON parser to handle this quirk when used by - // eval, we simply don't use the JSON parser when either character - // appears in the provided string. See bug 657367. - if (sizeof(CharT) > 1) { - for (RangedPtr cp = chars.begin() + 1, end = chars.end() - 1; - cp < end; - cp++) - { - char16_t c = *cp; - if (c == 0x2028 || c == 0x2029) - return false; - } - } + if (length < 2) + return false; - return true; - } - return false; + // It used to be that strings in JavaScript forbid U+2028 LINE SEPARATOR + // and U+2029 PARAGRAPH SEPARATOR, so something like + // + // eval("['" + "\u2028" + "']"); + // + // i.e. an array containing a string with a line separator in it, *would* + // be JSON but *would not* be valid JavaScript. Handing such a string to + // the JSON parser would then fail to recognize a syntax error. As of + // JavaScript strings may + // contain these two code points, so it's safe to JSON-parse eval strings + // that contain them. + + CharT first = chars[0], last = chars[length - 1]; + return (first == '[' && last == ']') || + (first == '(' && last == ')'); } template diff --git a/js/src/frontend/BinSource.cpp b/js/src/frontend/BinSource.cpp index 0429667a8572..745fb2e1541d 100644 --- a/js/src/frontend/BinSource.cpp +++ b/js/src/frontend/BinSource.cpp @@ -19,6 +19,7 @@ #include "frontend/Parser.h" #include "frontend/SharedContext.h" +#include "js/Result.h" #include "vm/RegExpObject.h" #include "frontend/ParseContext-inl.h" @@ -69,8 +70,6 @@ // // They should be treated lazily (whenever we open a subscope), like bindings. -using namespace mozilla; - namespace js { namespace frontend { @@ -114,7 +113,8 @@ BinASTParser::parseAux(const uint8_t* start, const size_t length) ParseNode* result(nullptr); MOZ_TRY_VAR(result, parseProgram()); - Maybe bindings = NewGlobalScopeData(cx_, varScope, alloc_, parseContext_); + mozilla::Maybe bindings = NewGlobalScopeData(cx_, varScope, alloc_, + parseContext_); if (!bindings) return cx_->alreadyReportedError(); globalsc.bindings = *bindings; @@ -500,7 +500,7 @@ BinASTParserBase::hasUsedName(HandlePropertyName name) } void -TraceBinParser(JSTracer* trc, AutoGCRooter* parser) +TraceBinParser(JSTracer* trc, JS::AutoGCRooter* parser) { static_cast(parser)->trace(trc); } diff --git a/js/src/frontend/BinSource.h b/js/src/frontend/BinSource.h index 5ed6807c8183..1461b8ec1df9 100644 --- a/js/src/frontend/BinSource.h +++ b/js/src/frontend/BinSource.h @@ -84,7 +84,7 @@ class BinASTParserBase: private JS::AutoGCRooter JS_DECLARE_NEW_METHODS(new_, allocParseNode, inline) // Needs access to AutoGCRooter. - friend void TraceBinParser(JSTracer* trc, AutoGCRooter* parser); + friend void TraceBinParser(JSTracer* trc, JS::AutoGCRooter* parser); protected: JSContext* cx_; @@ -290,7 +290,7 @@ class BinASTParser : public BinASTParserBase, public ErrorReporter, public BCEPa } private: // Implement ErrorReporter - Maybe tokenizer_; + mozilla::Maybe tokenizer_; VariableDeclarationKind variableDeclarationKind_; friend class BinParseContext; diff --git a/js/src/frontend/BinToken.cpp b/js/src/frontend/BinToken.cpp index 22af0da5e01c..42091c9ac689 100644 --- a/js/src/frontend/BinToken.cpp +++ b/js/src/frontend/BinToken.cpp @@ -15,7 +15,7 @@ #include "frontend/BinSourceRuntimeSupport.h" #include "frontend/TokenStream.h" #include "gc/Zone.h" - +#include "js/Result.h" namespace js { namespace frontend { diff --git a/js/src/frontend/BinTokenReaderBase.cpp b/js/src/frontend/BinTokenReaderBase.cpp index becc5621abe4..aa5df8cf5489 100644 --- a/js/src/frontend/BinTokenReaderBase.cpp +++ b/js/src/frontend/BinTokenReaderBase.cpp @@ -8,6 +8,7 @@ #include "frontend/BinSource-macros.h" #include "gc/Zone.h" +#include "js/Result.h" namespace js { namespace frontend { diff --git a/js/src/frontend/BinTokenReaderBase.h b/js/src/frontend/BinTokenReaderBase.h index c6be8e3e845f..4d62fd24f057 100644 --- a/js/src/frontend/BinTokenReaderBase.h +++ b/js/src/frontend/BinTokenReaderBase.h @@ -7,20 +7,15 @@ #ifndef frontend_BinTokenReaderBase_h #define frontend_BinTokenReaderBase_h -#include "mozilla/Maybe.h" - #include "frontend/BinToken.h" #include "frontend/TokenStream.h" +#include "js/Result.h" #include "js/TypeDecls.h" - namespace js { namespace frontend { -using namespace mozilla; -using namespace JS; - // A constant used by tokenizers to represent a null float. extern const uint64_t NULL_FLOAT_REPRESENTATION; @@ -172,4 +167,4 @@ class MOZ_STACK_CLASS BinTokenReaderBase } // namespace frontend } // namespace js -#endif // frontend_BinTokenReaderBase_h \ No newline at end of file +#endif // frontend_BinTokenReaderBase_h diff --git a/js/src/frontend/BinTokenReaderMultipart.cpp b/js/src/frontend/BinTokenReaderMultipart.cpp index cd668e3c56e2..7c06912657a1 100644 --- a/js/src/frontend/BinTokenReaderMultipart.cpp +++ b/js/src/frontend/BinTokenReaderMultipart.cpp @@ -6,6 +6,8 @@ #include "frontend/BinTokenReaderMultipart.h" +#include "mozilla/ArrayUtils.h" +#include "mozilla/Casting.h" #include "mozilla/EndianUtils.h" #include "mozilla/Maybe.h" @@ -13,6 +15,7 @@ #include "frontend/BinSourceRuntimeSupport.h" #include "gc/Zone.h" +#include "js/Result.h" namespace js { namespace frontend { @@ -192,18 +195,17 @@ BinTokenReaderMultipart::readDouble() uint8_t bytes[8]; MOZ_ASSERT(sizeof(bytes) == sizeof(double)); - MOZ_TRY(readBuf(reinterpret_cast(bytes), ArrayLength(bytes))); + MOZ_TRY(readBuf(reinterpret_cast(bytes), mozilla::ArrayLength(bytes))); // Decode little-endian. - const uint64_t asInt = LittleEndian::readUint64(bytes); + const uint64_t asInt = mozilla::LittleEndian::readUint64(bytes); if (asInt == NULL_FLOAT_REPRESENTATION) return raiseError("Not implemented: null double value"); // Canonicalize NaN, just to make sure another form of signalling NaN // doesn't slip past us. - const double asDouble = CanonicalizeNaN(BitwiseCast(asInt)); - return asDouble; + return JS::CanonicalizeNaN(mozilla::BitwiseCast(asInt)); } diff --git a/js/src/frontend/BinTokenReaderMultipart.h b/js/src/frontend/BinTokenReaderMultipart.h index 648482270660..bbcd78f2d458 100644 --- a/js/src/frontend/BinTokenReaderMultipart.h +++ b/js/src/frontend/BinTokenReaderMultipart.h @@ -12,12 +12,11 @@ #include "frontend/BinToken.h" #include "frontend/BinTokenReaderBase.h" +#include "js/Result.h" + namespace js { namespace frontend { -using namespace mozilla; -using namespace JS; - /** * A token reader implementing the "multipart" serialization format for BinAST. * @@ -114,7 +113,7 @@ class MOZ_STACK_CLASS BinTokenReaderMultipart: public BinTokenReaderBase /** * Read a single `BinVariant | null` value. */ - MOZ_MUST_USE JS::Result> readMaybeVariant(); + MOZ_MUST_USE JS::Result> readMaybeVariant(); MOZ_MUST_USE JS::Result readVariant(); /** diff --git a/js/src/frontend/BinTokenReaderTester.cpp b/js/src/frontend/BinTokenReaderTester.cpp index 1a3940ca998d..19d706c1b913 100644 --- a/js/src/frontend/BinTokenReaderTester.cpp +++ b/js/src/frontend/BinTokenReaderTester.cpp @@ -7,10 +7,14 @@ #include "frontend/BinTokenReaderTester.h" +#include "mozilla/ArrayUtils.h" +#include "mozilla/Casting.h" #include "mozilla/EndianUtils.h" +#include "mozilla/PodOperations.h" #include "frontend/BinSource-macros.h" #include "gc/Zone.h" +#include "js/Result.h" namespace js { namespace frontend { @@ -65,18 +69,17 @@ BinTokenReaderTester::readDouble() uint8_t bytes[8]; MOZ_ASSERT(sizeof(bytes) == sizeof(double)); - MOZ_TRY(readBuf(reinterpret_cast(bytes), ArrayLength(bytes))); + MOZ_TRY(readBuf(reinterpret_cast(bytes), mozilla::ArrayLength(bytes))); // Decode little-endian. - const uint64_t asInt = LittleEndian::readUint64(bytes); + const uint64_t asInt = mozilla::LittleEndian::readUint64(bytes); if (asInt == NULL_FLOAT_REPRESENTATION) return raiseError("Not implemented: null double value"); // Canonicalize NaN, just to make sure another form of signalling NaN // doesn't slip past us. - const double asDouble = CanonicalizeNaN(BitwiseCast(asInt)); - return asDouble; + return JS::CanonicalizeNaN(mozilla::BitwiseCast(asInt)); } // Internal uint32_t @@ -90,7 +93,7 @@ BinTokenReaderTester::readInternalUint32() MOZ_TRY(readBuf(bytes, 4)); // Decode little-endian. - return LittleEndian::readUint32(bytes); + return mozilla::LittleEndian::readUint32(bytes); } @@ -170,7 +173,7 @@ BinTokenReaderTester::readChars(Chars& out) if (!out.resize(byteLen)) return raiseOOM(); - PodCopy(out.begin(), current_, byteLen); + mozilla::PodCopy(out.begin(), current_, byteLen); current_ += byteLen; diff --git a/js/src/frontend/BinTokenReaderTester.h b/js/src/frontend/BinTokenReaderTester.h index a3c74b0abb1b..d63b2c3b33e4 100644 --- a/js/src/frontend/BinTokenReaderTester.h +++ b/js/src/frontend/BinTokenReaderTester.h @@ -12,6 +12,7 @@ #include "frontend/BinToken.h" #include "frontend/BinTokenReaderBase.h" +#include "js/Result.h" #include "js/TypeDecls.h" #if !defined(NIGHTLY_BUILD) @@ -21,9 +22,6 @@ namespace js { namespace frontend { -using namespace mozilla; -using namespace JS; - /** * A token reader for a simple, alternative serialization format for BinAST. * @@ -135,7 +133,7 @@ class MOZ_STACK_CLASS BinTokenReaderTester: public BinTokenReaderBase /** * Read a single `BinVariant | null` value. */ - MOZ_MUST_USE JS::Result> readMaybeVariant(); + MOZ_MUST_USE JS::Result> readMaybeVariant(); MOZ_MUST_USE JS::Result readVariant(); /** diff --git a/js/src/frontend/BytecodeEmitter.cpp b/js/src/frontend/BytecodeEmitter.cpp index 85aceaf4c961..a6d0606d7298 100644 --- a/js/src/frontend/BytecodeEmitter.cpp +++ b/js/src/frontend/BytecodeEmitter.cpp @@ -536,10 +536,6 @@ class BytecodeEmitter::EmitterScope : public Nestable::enclosing(); } @@ -2402,13 +2398,6 @@ BytecodeEmitter::init() return atomIndices.acquire(cx); } -template bool */> -BytecodeEmitter::NestableControl* -BytecodeEmitter::findInnermostNestableControl(Predicate predicate) const -{ - return NestableControl::findNearest(innermostNestableControl, predicate); -} - template T* BytecodeEmitter::findInnermostNestableControl() const @@ -5159,54 +5148,6 @@ BytecodeEmitter::emitFunctionScript(ParseNode* body) return true; } -template -bool -BytecodeEmitter::emitDestructuringDeclsWithEmitter(ParseNode* pattern, NameEmitter emitName) -{ - if (pattern->isKind(ParseNodeKind::Array)) { - for (ParseNode* element = pattern->pn_head; element; element = element->pn_next) { - if (element->isKind(ParseNodeKind::Elision)) - continue; - ParseNode* target = element; - if (element->isKind(ParseNodeKind::Spread)) { - target = element->pn_kid; - } - if (target->isKind(ParseNodeKind::Assign)) - target = target->pn_left; - if (target->isKind(ParseNodeKind::Name)) { - if (!emitName(this, target)) - return false; - } else { - if (!emitDestructuringDeclsWithEmitter(target, emitName)) - return false; - } - } - return true; - } - - MOZ_ASSERT(pattern->isKind(ParseNodeKind::Object)); - for (ParseNode* member = pattern->pn_head; member; member = member->pn_next) { - MOZ_ASSERT(member->isKind(ParseNodeKind::MutateProto) || - member->isKind(ParseNodeKind::Colon) || - member->isKind(ParseNodeKind::Shorthand)); - - ParseNode* target = member->isKind(ParseNodeKind::MutateProto) - ? member->pn_kid - : member->pn_right; - - if (target->isKind(ParseNodeKind::Assign)) - target = target->pn_left; - if (target->isKind(ParseNodeKind::Name)) { - if (!emitName(this, target)) - return false; - } else { - if (!emitDestructuringDeclsWithEmitter(target, emitName)) - return false; - } - } - return true; -} - bool BytecodeEmitter::emitDestructuringLHSRef(ParseNode* target, size_t* emitted) { @@ -11420,16 +11361,6 @@ CGObjectList::add(ObjectBox* objbox) return length++; } -unsigned -CGObjectList::indexOf(JSObject* obj) -{ - MOZ_ASSERT(length > 0); - unsigned index = length - 1; - for (ObjectBox* box = lastbox; box->object != obj; box = box->emitLink) - index--; - return index; -} - void CGObjectList::finish(ObjectArray* array) { @@ -11447,16 +11378,6 @@ CGObjectList::finish(ObjectArray* array) MOZ_ASSERT(cursor == array->vector); } -ObjectBox* -CGObjectList::find(uint32_t index) -{ - MOZ_ASSERT(index < length); - ObjectBox* box = lastbox; - for (unsigned n = length - 1; n > index; n--) - box = box->emitLink; - return box; -} - void CGScopeList::finish(ScopeArray* array) { diff --git a/js/src/frontend/BytecodeEmitter.h b/js/src/frontend/BytecodeEmitter.h index 140f958a2902..d0a779204168 100644 --- a/js/src/frontend/BytecodeEmitter.h +++ b/js/src/frontend/BytecodeEmitter.h @@ -44,9 +44,7 @@ struct CGObjectList { CGObjectList() : length(0), lastbox(nullptr) {} unsigned add(ObjectBox* objbox); - unsigned indexOf(JSObject* obj); void finish(ObjectArray* array); - ObjectBox* find(uint32_t index); }; struct MOZ_STACK_CLASS CGScopeList { @@ -370,9 +368,6 @@ struct MOZ_STACK_CLASS BytecodeEmitter MOZ_MUST_USE bool init(); - template bool */> - NestableControl* findInnermostNestableControl(Predicate predicate) const; - template T* findInnermostNestableControl() const; @@ -776,12 +771,6 @@ struct MOZ_STACK_CLASS BytecodeEmitter MOZ_MUST_USE bool emitDestructuringOpsArray(ParseNode* pattern, DestructuringFlavor flav); MOZ_MUST_USE bool emitDestructuringOpsObject(ParseNode* pattern, DestructuringFlavor flav); - typedef bool - (*DestructuringDeclEmitter)(BytecodeEmitter* bce, ParseNode* pn); - - template - MOZ_MUST_USE bool emitDestructuringDeclsWithEmitter(ParseNode* pattern, NameEmitter emitName); - enum class CopyOption { Filtered, Unfiltered }; diff --git a/js/src/frontend/FullParseHandler.h b/js/src/frontend/FullParseHandler.h index 48ee87009a02..ea09cd684112 100644 --- a/js/src/frontend/FullParseHandler.h +++ b/js/src/frontend/FullParseHandler.h @@ -311,9 +311,6 @@ class FullParseHandler ParseNode* newSuperBase(ParseNode* thisName, const TokenPos& pos) { return new_(ParseNodeKind::SuperBase, pos, thisName); } - ParseNode* newCatchBlock(ParseNode* catchName, ParseNode* catchGuard, ParseNode* catchBody) { - return new_(ParseNodeKind::Catch, catchName, catchGuard, catchBody); - } MOZ_MUST_USE bool addPrototypeMutation(ParseNode* literal, uint32_t begin, ParseNode* expr) { MOZ_ASSERT(literal->isKind(ParseNodeKind::Object)); MOZ_ASSERT(literal->isArity(PN_LIST)); @@ -473,10 +470,6 @@ class FullParseHandler list->pn_xflags |= PNX_FUNCDEFS; } - MOZ_MUST_USE inline bool addCatchBlock(ParseNode* catchList, ParseNode* lexicalScope, - ParseNode* catchName, ParseNode* catchGuard, - ParseNode* catchBody); - MOZ_MUST_USE bool prependInitialYield(ParseNode* stmtList, ParseNode* genName) { MOZ_ASSERT(stmtList->isKind(ParseNodeKind::StatementList)); MOZ_ASSERT(stmtList->isArity(PN_LIST)); @@ -947,19 +940,6 @@ class FullParseHandler } }; -inline bool -FullParseHandler::addCatchBlock(ParseNode* catchList, ParseNode* lexicalScope, - ParseNode* catchName, ParseNode* catchGuard, - ParseNode* catchBody) -{ - ParseNode* catchpn = newCatchBlock(catchName, catchGuard, catchBody); - if (!catchpn) - return false; - addList(/* list = */ catchList, /* child = */ lexicalScope); - lexicalScope->setScopeBody(catchpn); - return true; -} - inline bool FullParseHandler::setLastFunctionFormalParameterDefault(ParseNode* funcpn, ParseNode* defaultValue) diff --git a/js/src/frontend/ParseNode-inl.h b/js/src/frontend/ParseNode-inl.h index 2402f3b0698c..eaed735a37ea 100644 --- a/js/src/frontend/ParseNode-inl.h +++ b/js/src/frontend/ParseNode-inl.h @@ -22,13 +22,6 @@ ParseNode::name() const return atom->asPropertyName(); } -inline JSAtom* -ParseNode::atom() const -{ - MOZ_ASSERT(isKind(ParseNodeKind::String)); - return pn_atom; -} - } /* namespace frontend */ } /* namespace js */ diff --git a/js/src/frontend/ParseNode.h b/js/src/frontend/ParseNode.h index 98c02a178a87..e371c32fe735 100644 --- a/js/src/frontend/ParseNode.h +++ b/js/src/frontend/ParseNode.h @@ -623,7 +623,6 @@ class ParseNode // include "ParseNode-inl.h" for these methods. inline PropertyName* name() const; - inline JSAtom* atom() const; ParseNode* expr() const { MOZ_ASSERT(pn_arity == PN_NAME || pn_arity == PN_CODE); diff --git a/js/src/frontend/SharedContext.h b/js/src/frontend/SharedContext.h index 28ccfec02951..180d1c9b39f2 100644 --- a/js/src/frontend/SharedContext.h +++ b/js/src/frontend/SharedContext.h @@ -235,10 +235,6 @@ class SharedContext bool needStrictChecks() const { return strict() || extraWarnings; } - - bool isDotVariable(JSAtom* atom) const { - return atom == context->names().dotGenerator || atom == context->names().dotThis; - } }; class MOZ_STACK_CLASS GlobalSharedContext : public SharedContext diff --git a/js/src/frontend/TokenStream.cpp b/js/src/frontend/TokenStream.cpp index f1d580b1688d..ade848e8d35e 100644 --- a/js/src/frontend/TokenStream.cpp +++ b/js/src/frontend/TokenStream.cpp @@ -637,6 +637,10 @@ SourceUnits::findEOLMax(size_t start, size_t max) if (n >= max) break; n++; + + // This stops at U+2028 LINE SEPARATOR or U+2029 PARAGRAPH SEPARATOR in + // string and template literals. These code points do affect line and + // column coordinates, even as they encode their literal values. if (isRawEOLChar(*p++)) break; } @@ -2409,13 +2413,15 @@ TokenStreamSpecific::getStringOrTemplateToken(char untilC } break; } - } else if (SourceUnits::isRawEOLChar(c)) { + } else if (c == '\r' || c == '\n') { if (!parsingTemplate) { + // String literals don't allow ASCII line breaks. ungetCharIgnoreEOL(c); const char delimiters[] = { untilChar, untilChar, '\0' }; error(JSMSG_EOL_BEFORE_END_OF_STRING, delimiters); return false; } + if (c == '\r') { c = '\n'; @@ -2424,6 +2430,15 @@ TokenStreamSpecific::getStringOrTemplateToken(char untilC sourceUnits.matchCodeUnit('\n'); } + if (!updateLineInfoForEOL()) + return false; + + anyCharsAccess().updateFlagsForEOL(); + } else if (c == unicode::LINE_SEPARATOR || c == unicode::PARA_SEPARATOR) { + // U+2028 LINE SEPARATOR and U+2029 PARAGRAPH SEPARATOR encode + // their literal values in template literals and (as of fairly + // recently) string literals, but they still count as line + // terminators when computing line/column coordinates. if (!updateLineInfoForEOL()) return false; diff --git a/js/src/frontend/TokenStream.h b/js/src/frontend/TokenStream.h index 607eae589b74..5bbbdca813f4 100644 --- a/js/src/frontend/TokenStream.h +++ b/js/src/frontend/TokenStream.h @@ -561,8 +561,6 @@ class TokenStreamAnyChars return currentToken().type == type; } - bool getMutedErrors() const { return mutedErrors; } - MOZ_MUST_USE bool checkOptions(); private: @@ -587,14 +585,6 @@ class TokenStreamAnyChars return false; } - PropertyName* nextName() const { - if (nextToken().type != TokenKind::Name) - return nextToken().name(); - - MOZ_ASSERT(TokenKindIsPossibleIdentifierName(nextToken().type)); - return reservedWordToPropertyName(nextToken().type); - } - bool isCurrentTokenAssignment() const { return TokenKindIsAssignment(currentToken().type); } @@ -775,10 +765,6 @@ class TokenStreamAnyChars SourceCoords srcCoords; - JSAtomState& names() const { - return cx->names(); - } - JSContext* context() const { return cx; } @@ -1740,13 +1726,6 @@ class MOZ_STACK_CLASS TokenStreamSpecific MOZ_ASSERT(!SourceUnits::isRawEOLChar(c)); } } - - void skipCharsIgnoreEOL(uint8_t n) { - while (n-- > 0) { - MOZ_ASSERT(sourceUnits.hasRawChars()); - getCharIgnoreEOL(); - } - } }; // It's preferable to define this in TokenStream.cpp, but its template-ness diff --git a/js/src/gc/Marking.cpp b/js/src/gc/Marking.cpp index 520dbc2b2a81..5676747147ee 100644 --- a/js/src/gc/Marking.cpp +++ b/js/src/gc/Marking.cpp @@ -82,9 +82,9 @@ using mozilla::PodCopy; // |TraceEdge| |TraceRoot| |TraceManuallyBarrieredEdge| ... |TraceRange| ... etc. // // '---------' '---------' '--------------------------' '----------' // // \ \ / / // -// \ \ .----------------. / / // -// o------------->o-|DispatchToTracer|-o<-----------------------o // -// '----------------' // +// \ \ .-----------------. / / // +// o------------->o-|TraceEdgeInternal|-o<----------------------o // +// '-----------------' // // / \ // // / \ // // .---------. .----------. .-----------------. // @@ -372,162 +372,38 @@ AssertShouldMarkInZone(JS::Symbol* sym) #endif } -static void -AssertRootMarkingPhase(JSTracer* trc) +#ifdef DEBUG +void +js::gc::AssertRootMarkingPhase(JSTracer* trc) { MOZ_ASSERT_IF(trc->isMarkingTracer(), trc->runtime()->gc.state() == State::NotActive || trc->runtime()->gc.state() == State::MarkRoots); } +#endif /*** Tracing Interface ***************************************************************************/ -// The second parameter to BaseGCType is derived automatically based on T. The -// relation here is that for any T, the TraceKind will automatically, -// statically select the correct Cell layout for marking. Below, we instantiate -// each override with a declaration of the most derived layout type. -// -// The use of TraceKind::Null for the case where the type is not matched -// generates a compile error as no template instantiated for that kind. -// -// Usage: -// BaseGCType::type -// -// Examples: -// BaseGCType::type => JSObject -// BaseGCType::type => BaseShape -// etc. -template ::value ? JS::TraceKind::name : -JS_FOR_EACH_TRACEKIND(EXPAND_MATCH_TYPE) -#undef EXPAND_MATCH_TYPE - JS::TraceKind::Null> - -struct BaseGCType; -#define IMPL_BASE_GC_TYPE(name, type_, _) \ - template struct BaseGCType { typedef type_ type; }; -JS_FOR_EACH_TRACEKIND(IMPL_BASE_GC_TYPE); -#undef IMPL_BASE_GC_TYPE - -// Our barrier templates are parameterized on the pointer types so that we can -// share the definitions with Value and jsid. Thus, we need to strip the -// pointer before sending the type to BaseGCType and re-add it on the other -// side. As such: -template struct PtrBaseGCType { typedef T type; }; -template struct PtrBaseGCType { typedef typename BaseGCType::type* type; }; - -template -typename PtrBaseGCType::type* -ConvertToBase(T* thingp) -{ - return reinterpret_cast::type*>(thingp); -} - -template void DispatchToTracer(JSTracer* trc, T* thingp, const char* name); template T DoCallback(JS::CallbackTracer* trc, T* thingp, const char* name); template void DoMarking(GCMarker* gcmarker, T* thing); template void DoMarking(GCMarker* gcmarker, const T& thing); template void NoteWeakEdge(GCMarker* gcmarker, T** thingp); template void NoteWeakEdge(GCMarker* gcmarker, T* thingp); -template -void -js::TraceEdge(JSTracer* trc, WriteBarrieredBase* thingp, const char* name) -{ - DispatchToTracer(trc, ConvertToBase(thingp->unsafeUnbarrieredForTracing()), name); -} - -template -void -js::TraceEdge(JSTracer* trc, ReadBarriered* thingp, const char* name) -{ - DispatchToTracer(trc, ConvertToBase(thingp->unsafeGet()), name); -} - -template -void -js::TraceNullableEdge(JSTracer* trc, WriteBarrieredBase* thingp, const char* name) -{ - if (InternalBarrierMethods::isMarkable(thingp->get())) - DispatchToTracer(trc, ConvertToBase(thingp->unsafeUnbarrieredForTracing()), name); -} - -template -void -js::TraceNullableEdge(JSTracer* trc, ReadBarriered* thingp, const char* name) -{ - if (InternalBarrierMethods::isMarkable(thingp->unbarrieredGet())) - DispatchToTracer(trc, ConvertToBase(thingp->unsafeGet()), name); -} - template JS_PUBLIC_API(void) js::gc::TraceExternalEdge(JSTracer* trc, T* thingp, const char* name) { MOZ_ASSERT(InternalBarrierMethods::isMarkable(*thingp)); - DispatchToTracer(trc, ConvertToBase(thingp), name); -} - -template -void -js::TraceManuallyBarrieredEdge(JSTracer* trc, T* thingp, const char* name) -{ - DispatchToTracer(trc, ConvertToBase(thingp), name); + TraceEdgeInternal(trc, ConvertToBase(thingp), name); } template JS_PUBLIC_API(void) js::UnsafeTraceManuallyBarrieredEdge(JSTracer* trc, T* thingp, const char* name) { - DispatchToTracer(trc, ConvertToBase(thingp), name); -} - -template -void -js::TraceWeakEdge(JSTracer* trc, WeakRef* thingp, const char* name) -{ - if (!trc->isMarkingTracer()) { - // Non-marking tracers can select whether or not they see weak edges. - if (trc->traceWeakEdges()) - DispatchToTracer(trc, ConvertToBase(thingp->unsafeUnbarrieredForTracing()), name); - return; - } - - NoteWeakEdge(GCMarker::fromTracer(trc), - ConvertToBase(thingp->unsafeUnbarrieredForTracing())); -} - -template -void -js::TraceRoot(JSTracer* trc, T* thingp, const char* name) -{ - AssertRootMarkingPhase(trc); - DispatchToTracer(trc, ConvertToBase(thingp), name); -} - -template -void -js::TraceRoot(JSTracer* trc, ReadBarriered* thingp, const char* name) -{ - TraceRoot(trc, thingp->unsafeGet(), name); -} - -template -void -js::TraceNullableRoot(JSTracer* trc, T* thingp, const char* name) -{ - AssertRootMarkingPhase(trc); - if (InternalBarrierMethods::isMarkable(*thingp)) - DispatchToTracer(trc, ConvertToBase(thingp), name); -} - -template -void -js::TraceNullableRoot(JSTracer* trc, ReadBarriered* thingp, const char* name) -{ - TraceNullableRoot(trc, thingp->unsafeGet(), name); + TraceEdgeInternal(trc, ConvertToBase(thingp), name); } template @@ -538,48 +414,7 @@ JS::UnsafeTraceRoot(JSTracer* trc, T* thingp, const char* name) js::TraceNullableRoot(trc, thingp, name); } -template -void -js::TraceRange(JSTracer* trc, size_t len, WriteBarrieredBase* vec, const char* name) -{ - JS::AutoTracingIndex index(trc); - for (auto i : IntegerRange(len)) { - if (InternalBarrierMethods::isMarkable(vec[i].get())) - DispatchToTracer(trc, ConvertToBase(vec[i].unsafeUnbarrieredForTracing()), name); - ++index; - } -} - -template -void -js::TraceRootRange(JSTracer* trc, size_t len, T* vec, const char* name) -{ - AssertRootMarkingPhase(trc); - JS::AutoTracingIndex index(trc); - for (auto i : IntegerRange(len)) { - if (InternalBarrierMethods::isMarkable(vec[i])) - DispatchToTracer(trc, ConvertToBase(&vec[i]), name); - ++index; - } -} - -// Instantiate a copy of the Tracing templates for each derived type. -#define INSTANTIATE_ALL_VALID_TRACE_FUNCTIONS(type) \ - template void js::TraceEdge(JSTracer*, WriteBarrieredBase*, const char*); \ - template void js::TraceEdge(JSTracer*, ReadBarriered*, const char*); \ - template void js::TraceNullableEdge(JSTracer*, WriteBarrieredBase*, const char*); \ - template void js::TraceNullableEdge(JSTracer*, ReadBarriered*, const char*); \ - template void js::TraceManuallyBarrieredEdge(JSTracer*, type*, const char*); \ - template void js::TraceWeakEdge(JSTracer*, WeakRef*, const char*); \ - template void js::TraceRoot(JSTracer*, type*, const char*); \ - template void js::TraceRoot(JSTracer*, ReadBarriered*, const char*); \ - template void js::TraceNullableRoot(JSTracer*, type*, const char*); \ - template void js::TraceNullableRoot(JSTracer*, ReadBarriered*, const char*); \ - template void js::TraceRange(JSTracer*, size_t, WriteBarrieredBase*, const char*); \ - template void js::TraceRootRange(JSTracer*, size_t, type*, const char*); -FOR_EACH_GC_POINTER_TYPE(INSTANTIATE_ALL_VALID_TRACE_FUNCTIONS) -#undef INSTANTIATE_ALL_VALID_TRACE_FUNCTIONS - +// Instantiate a copy of the Tracing templates for each public GC pointer type. #define INSTANTIATE_PUBLIC_TRACE_FUNCTIONS(type) \ template JS_PUBLIC_API(void) JS::UnsafeTraceRoot(JSTracer*, type*, const char*); \ template JS_PUBLIC_API(void) js::UnsafeTraceManuallyBarrieredEdge(JSTracer*, type*, \ @@ -589,29 +424,46 @@ FOR_EACH_PUBLIC_GC_POINTER_TYPE(INSTANTIATE_PUBLIC_TRACE_FUNCTIONS) FOR_EACH_PUBLIC_TAGGED_GC_POINTER_TYPE(INSTANTIATE_PUBLIC_TRACE_FUNCTIONS) #undef INSTANTIATE_PUBLIC_TRACE_FUNCTIONS +namespace js { +namespace gc { + +#define INSTANTIATE_INTERNAL_TRACE_FUNCTIONS(type) \ + template void TraceEdgeInternal(JSTracer*, type*, const char*); \ + template void TraceWeakEdgeInternal(JSTracer*, type*, const char*); \ + template void TraceRangeInternal(JSTracer*, size_t len, type*, const char*); + +#define INSTANTIATE_INTERNAL_TRACE_FUNCTIONS_FROM_TRACEKIND(_1, type, _2) \ + INSTANTIATE_INTERNAL_TRACE_FUNCTIONS(type*) + +JS_FOR_EACH_TRACEKIND(INSTANTIATE_INTERNAL_TRACE_FUNCTIONS_FROM_TRACEKIND) +FOR_EACH_PUBLIC_TAGGED_GC_POINTER_TYPE(INSTANTIATE_INTERNAL_TRACE_FUNCTIONS) + +#undef INSTANTIATE_INTERNAL_TRACE_FUNCTIONS_FROM_TRACEKIND +#undef INSTANTIATE_INTERNAL_TRACE_FUNCTIONS + +} // namespace gc +} // namespace js + template void js::TraceManuallyBarrieredCrossCompartmentEdge(JSTracer* trc, JSObject* src, T* dst, const char* name) { if (ShouldTraceCrossCompartment(trc, src, *dst)) - DispatchToTracer(trc, dst, name); + TraceEdgeInternal(trc, dst, name); } template void js::TraceManuallyBarrieredCrossCompartmentEdge(JSTracer*, JSObject*, JSObject**, const char*); template void js::TraceManuallyBarrieredCrossCompartmentEdge(JSTracer*, JSObject*, JSScript**, const char*); -template void -js::TraceCrossCompartmentEdge(JSTracer* trc, JSObject* src, WriteBarrieredBase* dst, +js::TraceCrossCompartmentEdge(JSTracer* trc, JSObject* src, WriteBarrieredBase* dst, const char* name) { if (ShouldTraceCrossCompartment(trc, src, dst->get())) - DispatchToTracer(trc, dst->unsafeUnbarrieredForTracing(), name); + TraceEdgeInternal(trc, dst->unsafeUnbarrieredForTracing(), name); } -template void js::TraceCrossCompartmentEdge(JSTracer*, JSObject*, - WriteBarrieredBase*, const char*); template void @@ -676,7 +528,7 @@ js::TraceManuallyBarrieredGenericPointerEdge(JSTracer* trc, Cell** thingp, const // a sufficiently smart C++ compiler may be able to devirtualize some paths. template void -DispatchToTracer(JSTracer* trc, T* thingp, const char* name) +js::gc::TraceEdgeInternal(JSTracer* trc, T* thingp, const char* name) { #define IS_SAME_TYPE_OR(name, type, _) mozilla::IsSame::value || static_assert( @@ -694,6 +546,32 @@ DispatchToTracer(JSTracer* trc, T* thingp, const char* name) DoCallback(trc->asCallbackTracer(), thingp, name); } +template +void +js::gc::TraceWeakEdgeInternal(JSTracer* trc, T* thingp, const char* name) +{ + if (!trc->isMarkingTracer()) { + // Non-marking tracers can select whether or not they see weak edges. + if (trc->traceWeakEdges()) + TraceEdgeInternal(trc, thingp, name); + return; + } + + NoteWeakEdge(GCMarker::fromTracer(trc), thingp); +} + +template +void +js::gc::TraceRangeInternal(JSTracer* trc, size_t len, T* vec, const char* name) +{ + JS::AutoTracingIndex index(trc); + for (auto i : IntegerRange(len)) { + if (InternalBarrierMethods::isMarkable(vec[i])) + TraceEdgeInternal(trc, &vec[i], name); + ++index; + } +} + /*** GC Marking Interface *************************************************************************/ @@ -3361,27 +3239,25 @@ IsMarkedInternalCommon(T* thingp) } template -static bool -IsMarkedInternal(JSRuntime* rt, T** thingp) +struct MightBeNurseryAllocated +{ + static const bool value = mozilla::IsBaseOf::value || + mozilla::IsBaseOf::value; +}; + +template +bool +js::gc::IsMarkedInternal(JSRuntime* rt, T** thingp) { if (IsOwnedByOtherRuntime(rt, *thingp)) return true; - return IsMarkedInternalCommon(thingp); -} - -template <> -/* static */ bool -IsMarkedInternal(JSRuntime* rt, JSObject** thingp) -{ - if (IsOwnedByOtherRuntime(rt, *thingp)) - return true; - - if (IsInsideNursery(*thingp)) { + if (MightBeNurseryAllocated::value && IsInsideNursery(*thingp)) { MOZ_ASSERT(CurrentThreadCanAccessRuntime(rt)); Cell** cellp = reinterpret_cast(thingp); return Nursery::getForwardedPointer(cellp); } + return IsMarkedInternalCommon(thingp); } @@ -3394,8 +3270,8 @@ struct IsMarkedFunctor : public IdentityDefaultAdaptor { }; template -static bool -IsMarkedInternal(JSRuntime* rt, T* thingp) +bool +js::gc::IsMarkedInternal(JSRuntime* rt, T* thingp) { bool rv = true; *thingp = DispatchTyped(IsMarkedFunctor(), *thingp, rt, &rv); @@ -3411,8 +3287,8 @@ js::gc::IsAboutToBeFinalizedDuringSweep(TenuredCell& tenured) } template -static bool -IsAboutToBeFinalizedInternal(T** thingp) +bool +js::gc::IsAboutToBeFinalizedInternal(T** thingp) { CheckIsMarkedThing(thingp); T* thing = *thingp; @@ -3447,8 +3323,8 @@ struct IsAboutToBeFinalizedInternalFunctor : public IdentityDefaultAdaptor { }; template -static bool -IsAboutToBeFinalizedInternal(T* thingp) +bool +js::gc::IsAboutToBeFinalizedInternal(T* thingp) { bool rv = false; *thingp = DispatchTyped(IsAboutToBeFinalizedInternalFunctor(), *thingp, &rv); @@ -3458,41 +3334,6 @@ IsAboutToBeFinalizedInternal(T* thingp) namespace js { namespace gc { -template -bool -IsMarkedUnbarriered(JSRuntime* rt, T* thingp) -{ - return IsMarkedInternal(rt, ConvertToBase(thingp)); -} - -template -bool -IsMarked(JSRuntime* rt, WriteBarrieredBase* thingp) -{ - return IsMarkedInternal(rt, ConvertToBase(thingp->unsafeUnbarrieredForTracing())); -} - -template -bool -IsAboutToBeFinalizedUnbarriered(T* thingp) -{ - return IsAboutToBeFinalizedInternal(ConvertToBase(thingp)); -} - -template -bool -IsAboutToBeFinalized(WriteBarrieredBase* thingp) -{ - return IsAboutToBeFinalizedInternal(ConvertToBase(thingp->unsafeUnbarrieredForTracing())); -} - -template -bool -IsAboutToBeFinalized(ReadBarrieredBase* thingp) -{ - return IsAboutToBeFinalizedInternal(ConvertToBase(thingp->unsafeUnbarrieredForTracing())); -} - template JS_PUBLIC_API(bool) EdgeNeedsSweep(JS::Heap* thingp) @@ -3507,20 +3348,25 @@ EdgeNeedsSweepUnbarrieredSlow(T* thingp) return IsAboutToBeFinalizedInternal(ConvertToBase(thingp)); } -// Instantiate a copy of the Tracing templates for each derived type. -#define INSTANTIATE_ALL_VALID_TRACE_FUNCTIONS(type) \ - template bool IsMarkedUnbarriered(JSRuntime*, type*); \ - template bool IsMarked(JSRuntime*, WriteBarrieredBase*); \ - template bool IsAboutToBeFinalizedUnbarriered(type*); \ - template bool IsAboutToBeFinalized(WriteBarrieredBase*); \ - template bool IsAboutToBeFinalized(ReadBarrieredBase*); +// Instantiate a copy of the Tracing templates for each public GC type. #define INSTANTIATE_ALL_VALID_HEAP_TRACE_FUNCTIONS(type) \ template JS_PUBLIC_API(bool) EdgeNeedsSweep(JS::Heap*); \ template JS_PUBLIC_API(bool) EdgeNeedsSweepUnbarrieredSlow(type*); -FOR_EACH_GC_POINTER_TYPE(INSTANTIATE_ALL_VALID_TRACE_FUNCTIONS) FOR_EACH_PUBLIC_GC_POINTER_TYPE(INSTANTIATE_ALL_VALID_HEAP_TRACE_FUNCTIONS) FOR_EACH_PUBLIC_TAGGED_GC_POINTER_TYPE(INSTANTIATE_ALL_VALID_HEAP_TRACE_FUNCTIONS) -#undef INSTANTIATE_ALL_VALID_TRACE_FUNCTIONS + +#define INSTANTIATE_INTERNAL_MARKING_FUNCTIONS(type) \ + template bool IsMarkedInternal(JSRuntime* rt, type* thing); \ + template bool IsAboutToBeFinalizedInternal(type* thingp); + +#define INSTANTIATE_INTERNAL_MARKING_FUNCTIONS_FROM_TRACEKIND(_1, type, _2) \ + INSTANTIATE_INTERNAL_MARKING_FUNCTIONS(type*) + +JS_FOR_EACH_TRACEKIND(INSTANTIATE_INTERNAL_MARKING_FUNCTIONS_FROM_TRACEKIND) +FOR_EACH_PUBLIC_TAGGED_GC_POINTER_TYPE(INSTANTIATE_INTERNAL_MARKING_FUNCTIONS) + +#undef INSTANTIATE_INTERNAL_MARKING_FUNCTIONS_FROM_TRACEKIND +#undef INSTANTIATE_INTERNAL_MARKING_FUNCTIONS } /* namespace gc */ } /* namespace js */ diff --git a/js/src/gc/Marking.h b/js/src/gc/Marking.h index 0d11a07db9df..62ba44cba62e 100644 --- a/js/src/gc/Marking.h +++ b/js/src/gc/Marking.h @@ -55,31 +55,66 @@ PushArena(GCMarker* gcmarker, Arena* arena); /*** Liveness ***/ -// Report whether a thing has been marked. Things which are in zones that are -// not currently being collected or are owned by another runtime are always -// reported as being marked. +// The IsMarkedInternal and IsAboutToBeFinalizedInternal function templates are +// used to implement the IsMarked and IsAboutToBeFinalized set of functions. +// These internal functions are instantiated for the base GC types and should +// not be called directly. +// +// Note that there are two function templates declared for each, not one +// template and a specialization. This is necessary so that pointer arguments +// (e.g. JSObject**) and tagged value arguments (e.g. JS::Value*) are routed to +// separate implementations. + template -bool -IsMarkedUnbarriered(JSRuntime* rt, T* thingp); +bool IsMarkedInternal(JSRuntime* rt, T* thing); +template +bool IsMarkedInternal(JSRuntime* rt, T** thing); + +template +bool IsAboutToBeFinalizedInternal(T* thingp); +template +bool IsAboutToBeFinalizedInternal(T** thingp); // Report whether a thing has been marked. Things which are in zones that are // not currently being collected or are owned by another runtime are always // reported as being marked. template -bool -IsMarked(JSRuntime* rt, WriteBarrieredBase* thingp); +inline bool +IsMarkedUnbarriered(JSRuntime* rt, T* thingp) +{ + return IsMarkedInternal(rt, ConvertToBase(thingp)); +} + +// Report whether a thing has been marked. Things which are in zones that are +// not currently being collected or are owned by another runtime are always +// reported as being marked. +template +inline bool +IsMarked(JSRuntime* rt, WriteBarrieredBase* thingp) +{ + return IsMarkedInternal(rt, ConvertToBase(thingp->unsafeUnbarrieredForTracing())); +} template -bool -IsAboutToBeFinalizedUnbarriered(T* thingp); +inline bool +IsAboutToBeFinalizedUnbarriered(T* thingp) +{ + return IsAboutToBeFinalizedInternal(ConvertToBase(thingp)); +} template -bool -IsAboutToBeFinalized(WriteBarrieredBase* thingp); +inline bool +IsAboutToBeFinalized(WriteBarrieredBase* thingp) +{ + return IsAboutToBeFinalizedInternal(ConvertToBase(thingp->unsafeUnbarrieredForTracing())); +} template -bool -IsAboutToBeFinalized(ReadBarrieredBase* thingp); +inline bool +IsAboutToBeFinalized(ReadBarrieredBase* thingp) +{ + return IsAboutToBeFinalizedInternal(ConvertToBase(thingp->unsafeUnbarrieredForTracing())); +} bool IsAboutToBeFinalizedDuringSweep(TenuredCell& tenured); diff --git a/js/src/gc/Policy.h b/js/src/gc/Policy.h index dc2aa5d1fac3..d97ad7318f1f 100644 --- a/js/src/gc/Policy.h +++ b/js/src/gc/Policy.h @@ -14,107 +14,6 @@ #include "gc/Marking.h" #include "js/GCPolicyAPI.h" -// Forward declare the types we're defining policies for. This file is -// included in all places that define GC things, so the real definitions -// will be available when we do template expansion, allowing for use of -// static members in the underlying types. We cannot, however, use -// static_assert to verify relations between types. -class JSLinearString; -namespace js { -class AccessorShape; -class ArgumentsObject; -class ArrayBufferObject; -class ArrayBufferObjectMaybeShared; -class ArrayBufferViewObject; -class ArrayObject; -class BaseShape; -class DebugEnvironmentProxy; -class DebuggerFrame; -class ExportEntryObject; -class EnvironmentObject; -class GlobalObject; -class ImportEntryObject; -class LazyScript; -class LexicalEnvironmentObject; -class ModuleEnvironmentObject; -class ModuleNamespaceObject; -class ModuleObject; -class NativeObject; -class ObjectGroup; -class PlainObject; -class PropertyName; -class RegExpObject; -class SavedFrame; -class Scope; -class EnvironmentObject; -class RequestedModuleObject; -class ScriptSourceObject; -class Shape; -class SharedArrayBufferObject; -class StructTypeDescr; -class UnownedBaseShape; -class WasmGlobalObject; -class WasmFunctionScope; -class WasmMemoryObject; -namespace jit { -class JitCode; -} // namespace jit -} // namespace js - -// Expand the given macro D for each valid GC reference type. -#define FOR_EACH_INTERNAL_GC_POINTER_TYPE(D) \ - D(JSFlatString*) \ - D(JSLinearString*) \ - D(js::AccessorShape*) \ - D(js::ArgumentsObject*) \ - D(js::ArrayBufferObject*) \ - D(js::ArrayBufferObjectMaybeShared*) \ - D(js::ArrayBufferViewObject*) \ - D(js::ArrayObject*) \ - D(js::BaseShape*) \ - D(js::DebugEnvironmentProxy*) \ - D(js::DebuggerFrame*) \ - D(js::ExportEntryObject*) \ - D(js::EnvironmentObject*) \ - D(js::GlobalObject*) \ - D(js::ImportEntryObject*) \ - D(js::LazyScript*) \ - D(js::LexicalEnvironmentObject*) \ - D(js::ModuleEnvironmentObject*) \ - D(js::ModuleNamespaceObject*) \ - D(js::ModuleObject*) \ - D(js::NativeObject*) \ - D(js::ObjectGroup*) \ - D(js::PlainObject*) \ - D(js::PropertyName*) \ - D(js::RegExpObject*) \ - D(js::RegExpShared*) \ - D(js::RequestedModuleObject*) \ - D(js::SavedFrame*) \ - D(js::Scope*) \ - D(js::ScriptSourceObject*) \ - D(js::Shape*) \ - D(js::SharedArrayBufferObject*) \ - D(js::StructTypeDescr*) \ - D(js::UnownedBaseShape*) \ - D(js::WasmFunctionScope*) \ - D(js::WasmInstanceObject*) \ - D(js::WasmMemoryObject*) \ - D(js::WasmTableObject*) \ - D(js::WasmGlobalObject*) \ - D(js::jit::JitCode*) - -// Expand the given macro D for each internal tagged GC pointer type. -#define FOR_EACH_INTERNAL_TAGGED_GC_POINTER_TYPE(D) \ - D(js::TaggedProto) - -// Expand the macro D for every GC reference type that we know about. -#define FOR_EACH_GC_POINTER_TYPE(D) \ - FOR_EACH_PUBLIC_GC_POINTER_TYPE(D) \ - FOR_EACH_PUBLIC_TAGGED_GC_POINTER_TYPE(D) \ - FOR_EACH_INTERNAL_GC_POINTER_TYPE(D) \ - FOR_EACH_INTERNAL_TAGGED_GC_POINTER_TYPE(D) - namespace js { // Define the GCPolicy for all internal pointers. diff --git a/js/src/gc/RootMarking.cpp b/js/src/gc/RootMarking.cpp index e0a33713a0ca..e5f2edd24413 100644 --- a/js/src/gc/RootMarking.cpp +++ b/js/src/gc/RootMarking.cpp @@ -48,13 +48,27 @@ struct ConcreteTraceable { void trace(JSTracer*) {} }; -template TraceFn = TraceNullableRoot> +template +static inline void +TraceStackOrPersistentRoot(JSTracer* trc, T* thingp, const char* name) +{ + TraceNullableRoot(trc, thingp, name); +} + +template <> +inline void +TraceStackOrPersistentRoot(JSTracer* trc, ConcreteTraceable* thingp, const char* name) +{ + js::DispatchWrapper::TraceWrapped(trc, thingp, name); +} + +template static inline void TraceExactStackRootList(JSTracer* trc, JS::Rooted* rooter, const char* name) { while (rooter) { T* addr = reinterpret_cast*>(rooter)->address(); - TraceFn(trc, addr, name); + TraceStackOrPersistentRoot(trc, addr, name); rooter = rooter->previous(); } } @@ -68,8 +82,7 @@ JS_FOR_EACH_TRACEKIND(TRACE_ROOTS) #undef TRACE_ROOTS TraceExactStackRootList(trc, stackRoots[JS::RootKind::Id], "exact-id"); TraceExactStackRootList(trc, stackRoots[JS::RootKind::Value], "exact-value"); - TraceExactStackRootList::TraceWrapped>( + TraceExactStackRootList( trc, stackRoots[JS::RootKind::Traceable], "Traceable"); } @@ -85,13 +98,13 @@ TraceExactStackRoots(JSContext* cx, JSTracer* trc) cx->traceStackRoots(trc); } -template TraceFn = TraceNullableRoot> +template static inline void TracePersistentRootedList(JSTracer* trc, mozilla::LinkedList>& list, const char* name) { for (PersistentRooted* r : list) - TraceFn(trc, reinterpret_cast*>(r)->address(), name); + TraceStackOrPersistentRoot(trc, reinterpret_cast*>(r)->address(), name); } void @@ -103,9 +116,8 @@ JS_FOR_EACH_TRACEKIND(TRACE_ROOTS) #undef TRACE_ROOTS TracePersistentRootedList(trc, heapRoots.ref()[JS::RootKind::Id], "persistent-id"); TracePersistentRootedList(trc, heapRoots.ref()[JS::RootKind::Value], "persistent-value"); - TracePersistentRootedList::TraceWrapped>(trc, - heapRoots.ref()[JS::RootKind::Traceable], "persistent-traceable"); + TracePersistentRootedList( + trc, heapRoots.ref()[JS::RootKind::Traceable], "persistent-traceable"); } static void @@ -477,9 +489,6 @@ js::IsBufferGrayRootsTracer(JSTracer* trc) } #endif -// A canary value used to check the gray buffer contents are valid. -static Cell* const GrayBufferCanary = reinterpret_cast(0x47726179); // "Gray" - void js::gc::GCRuntime::bufferGrayRoots() { @@ -493,12 +502,6 @@ js::gc::GCRuntime::bufferGrayRoots() if (JSTraceDataOp op = grayRootTracer.op) (*op)(&grayBufferer, grayRootTracer.data); - // Push a canary value onto the end of the list. - for (GCZonesIter zone(rt); !zone.done(); zone.next()) { - if (!zone->gcGrayRoots().empty() && !zone->gcGrayRoots().append(GrayBufferCanary)) - grayBufferer.setFailed(); - } - // Propagate the failure flag from the marker to the runtime. if (grayBufferer.failed()) { grayBufferState = GrayBufferState::Failed; @@ -544,13 +547,21 @@ GCRuntime::markBufferedGrayRoots(JS::Zone* zone) if (roots.empty()) return; - // Check for canary value but don't remove it. - MOZ_RELEASE_ASSERT(roots.length() > 1); - MOZ_RELEASE_ASSERT(roots.back() == GrayBufferCanary); - - for (size_t i = 0; i < roots.length() - 1; i++) { + for (size_t i = 0; i < roots.length(); i++) { Cell* cell = roots[i]; + + // Bug 1203273: Check for bad pointers on OSX and output diagnostics. +#if defined(XP_DARWIN) && defined(MOZ_DIAGNOSTIC_ASSERT_ENABLED) + auto addr = uintptr_t(cell); + if (addr < ChunkSize || addr % CellAlignBytes != 0) { + MOZ_CRASH_UNSAFE_PRINTF( + "Bad GC thing pointer in gray root buffer: %p at index %zu of %zu, address %p", + cell, i, roots.length(), &roots[i]); + } +#else MOZ_ASSERT(IsCellPointerValid(cell)); +#endif + TraceManuallyBarrieredGenericPointerEdge(&marker, &cell, "buffered gray root"); } } diff --git a/js/src/gc/Tracer.h b/js/src/gc/Tracer.h index ca9d6b440640..eb6b362b771c 100644 --- a/js/src/gc/Tracer.h +++ b/js/src/gc/Tracer.h @@ -49,76 +49,175 @@ namespace js { // called "tracing" forever and changing it would be extremely difficult at // this point. +namespace gc { + +// Map from all trace kinds to the base GC type. +template +struct MapTraceKindToType {}; + +#define DEFINE_TRACE_KIND_MAP(name, type, _) \ + template <> struct MapTraceKindToType { \ + using Type = type; \ + }; +JS_FOR_EACH_TRACEKIND(DEFINE_TRACE_KIND_MAP); +#undef DEFINE_TRACE_KIND_MAP + +// Map from a possibly-derived type to the base GC type. +template +struct BaseGCType +{ + using type = typename MapTraceKindToType::kind>::Type; + static_assert(mozilla::IsBaseOf::value, "Failed to find base type"); +}; + +// Our barrier templates are parameterized on the pointer types so that we can +// share the definitions with Value and jsid. Thus, we need to strip the +// pointer before sending the type to BaseGCType and re-add it on the other +// side. As such: +template struct PtrBaseGCType { using type = T; }; +template struct PtrBaseGCType { using type = typename BaseGCType::type* ; }; + +// Cast a possibly-derived T** pointer to a base class pointer. +template +typename PtrBaseGCType::type* +ConvertToBase(T* thingp) +{ + return reinterpret_cast::type*>(thingp); +} + +// Internal methods to trace edges. +template void TraceEdgeInternal(JSTracer* trc, T* thingp, const char* name); +template void TraceWeakEdgeInternal(JSTracer* trc, T* thingp, const char* name); +template void TraceRangeInternal(JSTracer* trc, size_t len, T* vec, const char* name); + +#ifdef DEBUG +void AssertRootMarkingPhase(JSTracer* trc); +#else +inline void AssertRootMarkingPhase(JSTracer* trc) {} +#endif + +} // namespace gc + // Trace through an edge in the live object graph on behalf of tracing. The // effect of tracing the edge depends on the JSTracer being used. For pointer // types, |*thingp| must not be null. -template -void -TraceEdge(JSTracer* trc, WriteBarrieredBase* thingp, const char* name); template -void -TraceEdge(JSTracer* trc, ReadBarriered* thingp, const char* name); - -// Trace through an edge in the live object graph on behalf of tracing. -template -void -TraceNullableEdge(JSTracer* trc, WriteBarrieredBase* thingp, const char* name); +inline void +TraceEdge(JSTracer* trc, WriteBarrieredBase* thingp, const char* name) +{ + gc::TraceEdgeInternal(trc, gc::ConvertToBase(thingp->unsafeUnbarrieredForTracing()), name); +} template -void -TraceNullableEdge(JSTracer* trc, ReadBarriered* thingp, const char* name); +inline void +TraceEdge(JSTracer* trc, ReadBarriered* thingp, const char* name) +{ + gc::TraceEdgeInternal(trc, gc::ConvertToBase(thingp->unsafeGet()), name); +} + +// Trace through a possibly-null edge in the live object graph on behalf of +// tracing. + +template +inline void +TraceNullableEdge(JSTracer* trc, WriteBarrieredBase* thingp, const char* name) +{ + if (InternalBarrierMethods::isMarkable(thingp->get())) + TraceEdge(trc, thingp, name); +} + +template +inline void +TraceNullableEdge(JSTracer* trc, ReadBarriered* thingp, const char* name) +{ + if (InternalBarrierMethods::isMarkable(thingp->unbarrieredGet())) + TraceEdge(trc, thingp, name); +} // Trace through a "root" edge. These edges are the initial edges in the object // graph traversal. Root edges are asserted to only be traversed in the initial // phase of a GC. -template -void -TraceRoot(JSTracer* trc, T* thingp, const char* name); template -void -TraceRoot(JSTracer* trc, ReadBarriered* thingp, const char* name); +inline void +TraceRoot(JSTracer* trc, T* thingp, const char* name) +{ + gc::AssertRootMarkingPhase(trc); + gc::TraceEdgeInternal(trc, gc::ConvertToBase(thingp), name); +} + +template +inline void +TraceRoot(JSTracer* trc, ReadBarriered* thingp, const char* name) +{ + TraceRoot(trc, thingp->unsafeGet(), name); +} // Idential to TraceRoot, except that this variant will not crash if |*thingp| // is null. -template -void -TraceNullableRoot(JSTracer* trc, T* thingp, const char* name); template -void -TraceNullableRoot(JSTracer* trc, ReadBarriered* thingp, const char* name); +inline void +TraceNullableRoot(JSTracer* trc, T* thingp, const char* name) +{ + gc::AssertRootMarkingPhase(trc); + if (InternalBarrierMethods::isMarkable(*thingp)) + gc::TraceEdgeInternal(trc, gc::ConvertToBase(thingp), name); +} + +template +inline void +TraceNullableRoot(JSTracer* trc, ReadBarriered* thingp, const char* name) +{ + TraceNullableRoot(trc, thingp->unsafeGet(), name); +} // Like TraceEdge, but for edges that do not use one of the automatic barrier // classes and, thus, must be treated specially for moving GC. This method is // separate from TraceEdge to make accidental use of such edges more obvious. + template -void -TraceManuallyBarrieredEdge(JSTracer* trc, T* thingp, const char* name); +inline void +TraceManuallyBarrieredEdge(JSTracer* trc, T* thingp, const char* name) +{ + gc::TraceEdgeInternal(trc, gc::ConvertToBase(thingp), name); +} // Visits a WeakRef, but does not trace its referents. If *thingp is not marked // at the end of marking, it is replaced by nullptr. This method records // thingp, so the edge location must not change after this function is called. + template -void -TraceWeakEdge(JSTracer* trc, WeakRef* thingp, const char* name); +inline void +TraceWeakEdge(JSTracer* trc, WeakRef* thingp, const char* name) +{ + gc::TraceWeakEdgeInternal(trc, gc::ConvertToBase(thingp->unsafeUnbarrieredForTracing()), name); +} // Trace all edges contained in the given array. + template void -TraceRange(JSTracer* trc, size_t len, WriteBarrieredBase* vec, const char* name); +TraceRange(JSTracer* trc, size_t len, WriteBarrieredBase* vec, const char* name) +{ + gc::TraceRangeInternal(trc, len, gc::ConvertToBase(vec[0].unsafeUnbarrieredForTracing()), name); +} // Trace all root edges in the given array. + template void -TraceRootRange(JSTracer* trc, size_t len, T* vec, const char* name); +TraceRootRange(JSTracer* trc, size_t len, T* vec, const char* name) +{ + gc::AssertRootMarkingPhase(trc); + gc::TraceRangeInternal(trc, len, gc::ConvertToBase(vec), name); +} // Trace an edge that crosses compartment boundaries. If the compartment of the // destination thing is not being GC'd, then the edge will not be traced. -template void -TraceCrossCompartmentEdge(JSTracer* trc, JSObject* src, WriteBarrieredBase* dst, +TraceCrossCompartmentEdge(JSTracer* trc, JSObject* src, WriteBarrieredBase* dst, const char* name); // As above but with manual barriers. diff --git a/js/src/jit-test/tests/latin1/json.js b/js/src/jit-test/tests/latin1/json.js index 16559890d7ef..88a4f1471edf 100644 --- a/js/src/jit-test/tests/latin1/json.js +++ b/js/src/jit-test/tests/latin1/json.js @@ -55,13 +55,9 @@ function testEvalHackNotJSON() { arr = eval("[]; var z; [1, 2, 3, \"abc\u1200\"]"); assertEq(JSON.stringify(arr), '[1,2,3,"abc\u1200"]'); - try { - eval("[1, 2, 3, \"abc\u2028\"]"); - throw new Error("U+2028 shouldn't eval"); - } catch (e) { - assertEq(e instanceof SyntaxError, true, - "should have thrown a SyntaxError, instead got " + e); - } + var arr = eval("[1, 2, 3, \"abc\u2028\"]"); + assertEq(arr.length, 4); + assertEq(arr[3], "abc\u2028"); } testEvalHackNotJSON(); diff --git a/js/src/jit/BaselineCacheIRCompiler.cpp b/js/src/jit/BaselineCacheIRCompiler.cpp index 89ec7e5e1506..abcfd8a2b68b 100644 --- a/js/src/jit/BaselineCacheIRCompiler.cpp +++ b/js/src/jit/BaselineCacheIRCompiler.cpp @@ -1979,10 +1979,8 @@ BaselineCacheIRCompiler::emitGuardAndGetIterator() masm.loadPtr(iterAddr, output); masm.loadObjPrivate(output, JSObject::ITER_CLASS_NFIXED_SLOTS, niScratch); - // Ensure the |active| and |unreusable| bits are not set. - masm.branchTest32(Assembler::NonZero, - Address(niScratch, NativeIterator::offsetOfFlags()), - Imm32(NativeIterator::Flags::All), failure->label()); + // Ensure the iterator is reusable: see NativeIterator::isReusable. + masm.branchIfNativeIteratorNotReusable(niScratch, failure->label()); // Pre-write barrier for store to 'objectBeingIterated_'. Address iterObjAddr(niScratch, NativeIterator::offsetOfObjectBeingIterated()); diff --git a/js/src/jit/IonCacheIRCompiler.cpp b/js/src/jit/IonCacheIRCompiler.cpp index 919b4985a782..75248e450f97 100644 --- a/js/src/jit/IonCacheIRCompiler.cpp +++ b/js/src/jit/IonCacheIRCompiler.cpp @@ -2308,10 +2308,8 @@ IonCacheIRCompiler::emitGuardAndGetIterator() masm.movePtr(ImmGCPtr(iterobj), output); masm.loadObjPrivate(output, JSObject::ITER_CLASS_NFIXED_SLOTS, niScratch); - // Ensure the |active| and |unreusable| bits are not set. - masm.branchTest32(Assembler::NonZero, - Address(niScratch, NativeIterator::offsetOfFlags()), - Imm32(NativeIterator::Flags::All), failure->label()); + // Ensure the iterator is reusable: see NativeIterator::isReusable. + masm.branchIfNativeIteratorNotReusable(niScratch, failure->label()); // Pre-write barrier for store to 'objectBeingIterated_'. Address iterObjAddr(niScratch, NativeIterator::offsetOfObjectBeingIterated()); diff --git a/js/src/jit/MacroAssembler.cpp b/js/src/jit/MacroAssembler.cpp index c660d68890db..40e86325788c 100644 --- a/js/src/jit/MacroAssembler.cpp +++ b/js/src/jit/MacroAssembler.cpp @@ -3785,6 +3785,29 @@ MacroAssembler::debugAssertObjHasFixedSlots(Register obj, Register scratch) #endif } +void +MacroAssembler::branchIfNativeIteratorNotReusable(Register ni, Label* notReusable) +{ + // See NativeIterator::isReusable. + Address flagsAddr(ni, NativeIterator::offsetOfFlags()); + +#ifdef DEBUG + Label niIsInitialized; + branchTest32(Assembler::NonZero, + flagsAddr, + Imm32(NativeIterator::Flags::Initialized), + &niIsInitialized); + assumeUnreachable("Expected a NativeIterator that's been completely " + "initialized"); + bind(&niIsInitialized); +#endif + + branchTest32(Assembler::NonZero, + flagsAddr, + Imm32(NativeIterator::Flags::NotReusable), + notReusable); +} + template static bool AddPendingReadBarrier(Vector& list, T* value) diff --git a/js/src/jit/MacroAssembler.h b/js/src/jit/MacroAssembler.h index f3dc38de5c73..812c08c2d8ba 100644 --- a/js/src/jit/MacroAssembler.h +++ b/js/src/jit/MacroAssembler.h @@ -2192,6 +2192,8 @@ class MacroAssembler : public MacroAssemblerSpecific void debugAssertIsObject(const ValueOperand& val); void debugAssertObjHasFixedSlots(Register obj, Register scratch); + void branchIfNativeIteratorNotReusable(Register ni, Label* notReusable); + using MacroAssemblerSpecific::extractTag; Register extractTag(const TypedOrValueRegister& reg, Register scratch) { if (reg.hasValue()) diff --git a/js/src/jit/WasmBCE.cpp b/js/src/jit/WasmBCE.cpp index e517c3583e79..7ee72cb435d7 100644 --- a/js/src/jit/WasmBCE.cpp +++ b/js/src/jit/WasmBCE.cpp @@ -10,7 +10,6 @@ using namespace js; using namespace js::jit; -using namespace mozilla; typedef js::HashMap, SystemAllocPolicy> LastSeenMap; diff --git a/js/src/tests/non262/eval/line-terminator-paragraph-terminator.js b/js/src/tests/non262/eval/line-terminator-paragraph-terminator.js index 61047fb1095d..9a904073ab63 100644 --- a/js/src/tests/non262/eval/line-terminator-paragraph-terminator.js +++ b/js/src/tests/non262/eval/line-terminator-paragraph-terminator.js @@ -3,7 +3,9 @@ //----------------------------------------------------------------------------- var BUGNUMBER = 657367; -var summary = "eval must not parse strings containing U+2028 or U+2029"; +var summary = + "eval via the JSON parser should parse strings containing U+2028/U+2029 " + + "(as of , that is)"; print(BUGNUMBER + ": " + summary); @@ -11,59 +13,8 @@ print(BUGNUMBER + ": " + summary); * BEGIN TEST * **************/ -function esc(s) -{ - return s.split("").map(function(v) - { - var code = - ("000" + v.charCodeAt(0).toString(16)).slice(-4); - return "\\u" + code; - }).join(""); -} - -try -{ - var r = eval('"\u2028"'); - throw new Error("\"\\u2028\" didn't throw, returned " + esc(r)); -} -catch (e) -{ - assertEq(e instanceof SyntaxError, true, - "U+2028 is not a valid string character"); -} - -try -{ - var r = eval('("\u2028")'); - throw new Error("(\"\\u2028\") didn't throw, returned " + esc(r)); -} -catch (e) -{ - assertEq(e instanceof SyntaxError, true, - "U+2028 is not a valid string character"); -} - -try -{ - var r = eval('"\u2029"'); - throw new Error("\"\\u2029\" didn't throw, returned " + esc(r)); -} -catch (e) -{ - assertEq(e instanceof SyntaxError, true, - "U+2029 is not a valid string character"); -} - -try -{ - var r = eval('("\u2029")'); - throw new Error("(\"\\u2029\") didn't throw, returned " + esc(r)); -} -catch (e) -{ - assertEq(e instanceof SyntaxError, true, - "U+2029 is not a valid string character"); -} +assertEq(eval('("\u2028")'), "\u2028"); +assertEq(eval('("\u2029")'), "\u2029"); /******************************************************************************/ diff --git a/js/src/tests/test262-update.py b/js/src/tests/test262-update.py index 0077cdb2fb3a..724e3b5143ac 100755 --- a/js/src/tests/test262-update.py +++ b/js/src/tests/test262-update.py @@ -27,7 +27,6 @@ UNSUPPORTED_FEATURES = set([ "regexp-named-groups", "regexp-unicode-property-escapes", "numeric-separator-literal", - "json-superset", "Intl.Locale", "String.prototype.matchAll", "Symbol.matchAll", diff --git a/js/src/tests/test262/GIT-INFO b/js/src/tests/test262/GIT-INFO index ddbf5f541e99..a9d4174961e4 100644 --- a/js/src/tests/test262/GIT-INFO +++ b/js/src/tests/test262/GIT-INFO @@ -1,7 +1,5 @@ -commit fbccd8eeffd21cfb6fee97493d347ae078f59d5c +commit a8f7012587250b32ffb43a3cbd8da8a9f9d1565e Author: Rick Waldron -Date: Fri May 18 12:35:06 2018 -0400 +Date: Tue May 22 15:47:50 2018 -0400 - Intl: PluralRules, NumberFormat, Number & getCanonicalLocales to use verifyProperty - - There's a lot of work like this to do, but not enough time in the day to reach it all. + Array.prototype.flatten => Array.prototype.flat (#1569) diff --git a/js/src/tests/test262/built-ins/Array/prototype/flatten/array-like-objects.js b/js/src/tests/test262/built-ins/Array/prototype/flat/array-like-objects.js similarity index 78% rename from js/src/tests/test262/built-ins/Array/prototype/flatten/array-like-objects.js rename to js/src/tests/test262/built-ins/Array/prototype/flat/array-like-objects.js index 2d0aa4efba4c..34cfe64fe139 100644 --- a/js/src/tests/test262/built-ins/Array/prototype/flatten/array-like-objects.js +++ b/js/src/tests/test262/built-ins/Array/prototype/flat/array-like-objects.js @@ -1,11 +1,11 @@ // Copyright (C) 2018 Shilpi Jain and Michael Ficarra. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- -esid: sec-array.prototype.flatten +esid: sec-array.prototype.flat description: > array-like objects can be flattened includes: [compareArray.js] -features: [Array.prototype.flatten] +features: [Array.prototype.flat] ---*/ function getArgumentsObject() { @@ -13,21 +13,21 @@ function getArgumentsObject() { } var a = getArgumentsObject([1], [2]); -var actual = [].flatten.call(a); +var actual = [].flat.call(a); assert.compareArray(actual, [1, 2], 'arguments objects'); var a = { length: 1, 0: [1], }; -var actual = [].flatten.call(a); +var actual = [].flat.call(a); assert.compareArray(actual, [1], 'array-like objects'); var a = { length: undefined, 0: [1], }; -var actual = [].flatten.call(a); +var actual = [].flat.call(a); assert.compareArray(actual, [], 'array-like objects; undefined length'); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Array/prototype/flatten/bound-function-call.js b/js/src/tests/test262/built-ins/Array/prototype/flat/bound-function-call.js similarity index 63% rename from js/src/tests/test262/built-ins/Array/prototype/flatten/bound-function-call.js rename to js/src/tests/test262/built-ins/Array/prototype/flat/bound-function-call.js index 9ea1ecbf11f4..4684bde4973d 100644 --- a/js/src/tests/test262/built-ins/Array/prototype/flatten/bound-function-call.js +++ b/js/src/tests/test262/built-ins/Array/prototype/flat/bound-function-call.js @@ -1,19 +1,19 @@ // Copyright (C) 2018 Shilpi Jain and Michael Ficarra. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- -esid: sec-array.prototype.flatten +esid: sec-array.prototype.flat description: > using bound functions includes: [compareArray.js] -features: [Array.prototype.flatten] +features: [Array.prototype.flat] ---*/ var a = [ [0], [1] ]; -var actual = [].flatten.bind(a)(); +var actual = [].flat.bind(a)(); -assert.compareArray(actual, [0, 1], 'bound flatten'); +assert.compareArray(actual, [0, 1], 'bound flat'); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Array/prototype/flatten/browser.js b/js/src/tests/test262/built-ins/Array/prototype/flat/browser.js similarity index 100% rename from js/src/tests/test262/built-ins/Array/prototype/flatten/browser.js rename to js/src/tests/test262/built-ins/Array/prototype/flat/browser.js diff --git a/js/src/tests/test262/built-ins/Array/prototype/flatten/empty-array-elements.js b/js/src/tests/test262/built-ins/Array/prototype/flat/empty-array-elements.js similarity index 69% rename from js/src/tests/test262/built-ins/Array/prototype/flatten/empty-array-elements.js rename to js/src/tests/test262/built-ins/Array/prototype/flat/empty-array-elements.js index aa32dff0c6ac..c184b02b343c 100644 --- a/js/src/tests/test262/built-ins/Array/prototype/flatten/empty-array-elements.js +++ b/js/src/tests/test262/built-ins/Array/prototype/flat/empty-array-elements.js @@ -1,26 +1,26 @@ // Copyright (C) 2018 Shilpi Jain and Michael Ficarra. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- -esid: sec-array.prototype.flatten +esid: sec-array.prototype.flat description: > arrays with empty arrays elements includes: [compareArray.js] -features: [Array.prototype.flatten] +features: [Array.prototype.flat] ---*/ var a = {}; -assert.compareArray([].flatten(), []); +assert.compareArray([].flat(), []); assert.compareArray([ [], [] -].flatten(), []); +].flat(), []); assert.compareArray([ [], [1] -].flatten(), [1]); +].flat(), [1]); assert.compareArray([ [], [1, a] -].flatten(), [1, a]); +].flat(), [1, a]); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Array/prototype/flatten/empty-object-elements.js b/js/src/tests/test262/built-ins/Array/prototype/flat/empty-object-elements.js similarity index 63% rename from js/src/tests/test262/built-ins/Array/prototype/flatten/empty-object-elements.js rename to js/src/tests/test262/built-ins/Array/prototype/flat/empty-object-elements.js index 7ffc60fe7748..e69f78ea97e7 100644 --- a/js/src/tests/test262/built-ins/Array/prototype/flatten/empty-object-elements.js +++ b/js/src/tests/test262/built-ins/Array/prototype/flat/empty-object-elements.js @@ -1,24 +1,24 @@ // Copyright (C) 2018 Shilpi Jain and Michael Ficarra. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- -esid: sec-array.prototype.flatten +esid: sec-array.prototype.flat description: > arrays with empty object elements includes: [compareArray.js] -features: [Array.prototype.flatten] +features: [Array.prototype.flat] ---*/ var a = {}, b = {}; -assert.compareArray([a].flatten(), [a]); -assert.compareArray([a, [b]].flatten(), [a, b]); +assert.compareArray([a].flat(), [a]); +assert.compareArray([a, [b]].flat(), [a, b]); assert.compareArray([ [a], b -].flatten(), [a, b]); +].flat(), [a, b]); assert.compareArray([ [a], [b] -].flatten(), [a, b]); +].flat(), [a, b]); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Array/prototype/flat/length.js b/js/src/tests/test262/built-ins/Array/prototype/flat/length.js new file mode 100644 index 000000000000..9e7d156ca589 --- /dev/null +++ b/js/src/tests/test262/built-ins/Array/prototype/flat/length.js @@ -0,0 +1,21 @@ +// Copyright (C) 2018 Shilpi Jain and Michael Ficarra. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-array.prototype.flat +description: Array.prototype.flat.length value and descriptor. +info: > + 17 ECMAScript Standard Built-in Objects +includes: [propertyHelper.js] +features: [Array.prototype.flat] +---*/ + +assert.sameValue( + Array.prototype.flat.length, 0, + 'The value of `Array.prototype.flat.length` is `0`' +); + +verifyNotEnumerable(Array.prototype.flat, 'length'); +verifyNotWritable(Array.prototype.flat, 'length'); +verifyConfigurable(Array.prototype.flat, 'length'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Array/prototype/flat/name.js b/js/src/tests/test262/built-ins/Array/prototype/flat/name.js new file mode 100644 index 000000000000..47df34d6e7f4 --- /dev/null +++ b/js/src/tests/test262/built-ins/Array/prototype/flat/name.js @@ -0,0 +1,22 @@ +// Copyright (C) 2018 Shilpi Jain and Michael Ficarra. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-array.prototype.flat +description: > + Array.prototype.flat.name value and descriptor. +info: > + 17 ECMAScript Standard Built-in Objects +includes: [propertyHelper.js] +features: [Array.prototype.flat] +---*/ + +assert.sameValue( + Array.prototype.flat.name, 'flat', + 'The value of `Array.prototype.flat.name` is `"flat"`' +); + +verifyNotEnumerable(Array.prototype.flat, 'name'); +verifyNotWritable(Array.prototype.flat, 'name'); +verifyConfigurable(Array.prototype.flat, 'name'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Array/prototype/flatten/non-numeric-depth-should-not-throw.js b/js/src/tests/test262/built-ins/Array/prototype/flat/non-numeric-depth-should-not-throw.js similarity index 81% rename from js/src/tests/test262/built-ins/Array/prototype/flatten/non-numeric-depth-should-not-throw.js rename to js/src/tests/test262/built-ins/Array/prototype/flat/non-numeric-depth-should-not-throw.js index 505d5f98f64d..3a167a197952 100644 --- a/js/src/tests/test262/built-ins/Array/prototype/flatten/non-numeric-depth-should-not-throw.js +++ b/js/src/tests/test262/built-ins/Array/prototype/flat/non-numeric-depth-should-not-throw.js @@ -1,11 +1,11 @@ // Copyright (C) 2018 Shilpi Jain and Michael Ficarra. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- -esid: sec-array.prototype.flatten +esid: sec-array.prototype.flat description: > if the argument is a string or object, the depthNum is 0 includes: [compareArray.js] -features: [Array.prototype.flatten] +features: [Array.prototype.flat] ---*/ var a = [1, [2]]; @@ -13,32 +13,32 @@ var expected = a; // non integral string depthNum is converted to 0 var depthNum = 'TestString'; -var actual = a.flatten(depthNum); +var actual = a.flat(depthNum); assert(compareArray(actual, expected), 'non integral string depthNum'); // object type depthNum is converted to 0 var depthNum = {}; -var actual = a.flatten(depthNum); +var actual = a.flat(depthNum); assert(compareArray(actual, expected), 'object type depthNum'); // negative infinity depthNum is converted to 0 var depthNum = Number.NEGATIVE_INFINITY; -var actual = a.flatten(depthNum); +var actual = a.flat(depthNum); assert(compareArray(actual, expected), 'negative infinity depthNum'); // positive zero depthNum is converted to 0 var depthNum = +0; -var actual = a.flatten(depthNum); +var actual = a.flat(depthNum); assert(compareArray(actual, expected), 'positive zero depthNum'); // negative zero depthNum is converted to 0 var depthNum = -0; -var actual = a.flatten(depthNum); +var actual = a.flat(depthNum); assert(compareArray(actual, expected), 'negative zero depthNum'); // integral string depthNum is converted to an integer var depthNum = '1'; -var actual = a.flatten(depthNum); +var actual = a.flat(depthNum); var expected = [1, 2] assert(compareArray(actual, expected), 'integral string depthNum'); diff --git a/js/src/tests/test262/built-ins/Array/prototype/flatten/non-object-ctor-throws.js b/js/src/tests/test262/built-ins/Array/prototype/flat/non-object-ctor-throws.js similarity index 84% rename from js/src/tests/test262/built-ins/Array/prototype/flatten/non-object-ctor-throws.js rename to js/src/tests/test262/built-ins/Array/prototype/flat/non-object-ctor-throws.js index 05a44774a26e..08617b169897 100644 --- a/js/src/tests/test262/built-ins/Array/prototype/flatten/non-object-ctor-throws.js +++ b/js/src/tests/test262/built-ins/Array/prototype/flat/non-object-ctor-throws.js @@ -1,35 +1,35 @@ // Copyright (C) 2018 Shilpi Jain and Michael Ficarra. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- -esid: sec-array.prototype.flatten +esid: sec-array.prototype.flat description: > Behavior when `constructor` property is neither an Object nor undefined - if IsConstructor(C) is false, throw a TypeError exception. -features: [Array.prototype.flatten] +features: [Array.prototype.flat] ---*/ var a = []; a.constructor = null; assert.throws(TypeError, function() { - a.flatten(); + a.flat(); }, 'null value'); var a = []; a.constructor = 1; assert.throws(TypeError, function() { - a.flatten(); + a.flat(); }, 'number value'); var a = []; a.constructor = 'string'; assert.throws(TypeError, function() { - a.flatten(); + a.flat(); }, 'string value'); var a = []; a.constructor = true; assert.throws(TypeError, function() { - a.flatten(); + a.flat(); }, 'boolean value'); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Array/prototype/flat/null-undefined-elements.js b/js/src/tests/test262/built-ins/Array/prototype/flat/null-undefined-elements.js new file mode 100644 index 000000000000..ecc412365960 --- /dev/null +++ b/js/src/tests/test262/built-ins/Array/prototype/flat/null-undefined-elements.js @@ -0,0 +1,22 @@ +// Copyright (C) 2018 Shilpi Jain and Michael Ficarra. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-array.prototype.flat +description: > + arrays with null, and undefined +includes: [compareArray.js] +features: [Array.prototype.flat] +---*/ + +var a = [void 0]; + +assert(compareArray([1, null, void 0].flat(), [1, null, undefined])); +assert(compareArray([1, [null, void 0]].flat(), [1, null, undefined])); +assert(compareArray([ + [null, void 0], + [null, void 0] +].flat(), [null, undefined, null, undefined])); +assert(compareArray([1, [null, a]].flat(1), [1, null, a])); +assert(compareArray([1, [null, a]].flat(2), [1, null, undefined])); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Array/prototype/flatten/null-undefined-input-throws.js b/js/src/tests/test262/built-ins/Array/prototype/flat/null-undefined-input-throws.js similarity index 74% rename from js/src/tests/test262/built-ins/Array/prototype/flatten/null-undefined-input-throws.js rename to js/src/tests/test262/built-ins/Array/prototype/flat/null-undefined-input-throws.js index 93081ec5c925..6c6ddae7c50b 100644 --- a/js/src/tests/test262/built-ins/Array/prototype/flatten/null-undefined-input-throws.js +++ b/js/src/tests/test262/built-ins/Array/prototype/flat/null-undefined-input-throws.js @@ -1,22 +1,22 @@ // Copyright (C) 2018 Shilpi Jain and Michael Ficarra. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- -esid: sec-array.prototype.flatten +esid: sec-array.prototype.flat description: > null or undefined should throw TypeError Exception -features: [Array.prototype.flatten] +features: [Array.prototype.flat] ---*/ assert.throws(TypeError, function() { - [].flatten.call(null); + [].flat.call(null); }, 'null value'); assert.throws(TypeError, function() { - [].flatten.call(); + [].flat.call(); }, 'missing'); assert.throws(TypeError, function() { - [].flatten.call(void 0); + [].flat.call(void 0); }, 'undefined'); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Array/prototype/flatten/positive-infinity.js b/js/src/tests/test262/built-ins/Array/prototype/flat/positive-infinity.js similarity index 65% rename from js/src/tests/test262/built-ins/Array/prototype/flatten/positive-infinity.js rename to js/src/tests/test262/built-ins/Array/prototype/flat/positive-infinity.js index 5b350370e84f..8fc7a98c011c 100644 --- a/js/src/tests/test262/built-ins/Array/prototype/flatten/positive-infinity.js +++ b/js/src/tests/test262/built-ins/Array/prototype/flat/positive-infinity.js @@ -1,14 +1,14 @@ // Copyright (C) 2018 Shilpi Jain and Michael Ficarra. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- -esid: sec-array.prototype.flatten +esid: sec-array.prototype.flat description: > if the argument is a positive infinity, the depthNum is max depth of the array includes: [compareArray.js] -features: [Array.prototype.flatten] +features: [Array.prototype.flat] ---*/ var a = [1, [2, [3, [4]]]] -assert(compareArray(a.flatten(Number.POSITIVE_INFINITY), [1, 2, 3, 4]), 'positive infinity depthNum'); +assert(compareArray(a.flat(Number.POSITIVE_INFINITY), [1, 2, 3, 4]), 'positive infinity depthNum'); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Array/prototype/flatten/prop-desc.js b/js/src/tests/test262/built-ins/Array/prototype/flat/prop-desc.js similarity index 54% rename from js/src/tests/test262/built-ins/Array/prototype/flatten/prop-desc.js rename to js/src/tests/test262/built-ins/Array/prototype/flat/prop-desc.js index b4e87e55a361..bf03432e87b3 100644 --- a/js/src/tests/test262/built-ins/Array/prototype/flatten/prop-desc.js +++ b/js/src/tests/test262/built-ins/Array/prototype/flat/prop-desc.js @@ -1,23 +1,23 @@ // Copyright (C) 2018 Shilpi Jain and Michael Ficarra. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- -esid: sec-array.prototype.flatten +esid: sec-array.prototype.flat es6id: 22.1.3 description: Property type and descriptor. info: > 17 ECMAScript Standard Built-in Objects includes: [propertyHelper.js] -features: [Array.prototype.flatten] +features: [Array.prototype.flat] ---*/ assert.sameValue( - typeof Array.prototype.flatten, + typeof Array.prototype.flat, 'function', - '`typeof Array.prototype.flatten` is `function`' + '`typeof Array.prototype.flat` is `function`' ); -verifyNotEnumerable(Array.prototype, 'flatten'); -verifyWritable(Array.prototype, 'flatten'); -verifyConfigurable(Array.prototype, 'flatten'); +verifyNotEnumerable(Array.prototype, 'flat'); +verifyWritable(Array.prototype, 'flat'); +verifyConfigurable(Array.prototype, 'flat'); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Array/prototype/flatten/shell.js b/js/src/tests/test262/built-ins/Array/prototype/flat/shell.js similarity index 100% rename from js/src/tests/test262/built-ins/Array/prototype/flatten/shell.js rename to js/src/tests/test262/built-ins/Array/prototype/flat/shell.js diff --git a/js/src/tests/test262/built-ins/Array/prototype/flatten/symbol-object-create-null-depth-throws.js b/js/src/tests/test262/built-ins/Array/prototype/flat/symbol-object-create-null-depth-throws.js similarity index 75% rename from js/src/tests/test262/built-ins/Array/prototype/flatten/symbol-object-create-null-depth-throws.js rename to js/src/tests/test262/built-ins/Array/prototype/flat/symbol-object-create-null-depth-throws.js index 8487135a46cd..57de25004200 100644 --- a/js/src/tests/test262/built-ins/Array/prototype/flatten/symbol-object-create-null-depth-throws.js +++ b/js/src/tests/test262/built-ins/Array/prototype/flat/symbol-object-create-null-depth-throws.js @@ -1,18 +1,18 @@ // Copyright (C) 2018 Shilpi Jain and Michael Ficarra. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- -esid: sec-array.prototype.flatten +esid: sec-array.prototype.flat description: > if the argument is a Symbol or Object null, it throws exception -features: [Array.prototype.flatten] +features: [Array.prototype.flat] ---*/ assert.throws(TypeError, function() { - [].flatten(Symbol()); + [].flat(Symbol()); }, 'symbol value'); assert.throws(TypeError, function() { - [].flatten(Object.create(null)); + [].flat(Object.create(null)); }, 'object create null'); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Array/prototype/flatten/length.js b/js/src/tests/test262/built-ins/Array/prototype/flatten/length.js deleted file mode 100644 index e3a5b87cf7d7..000000000000 --- a/js/src/tests/test262/built-ins/Array/prototype/flatten/length.js +++ /dev/null @@ -1,21 +0,0 @@ -// Copyright (C) 2018 Shilpi Jain and Michael Ficarra. All rights reserved. -// This code is governed by the BSD license found in the LICENSE file. -/*--- -esid: sec-array.prototype.flatten -description: Array.prototype.flatten.length value and descriptor. -info: > - 17 ECMAScript Standard Built-in Objects -includes: [propertyHelper.js] -features: [Array.prototype.flatten] ----*/ - -assert.sameValue( - Array.prototype.flatten.length, 0, - 'The value of `Array.prototype.flatten.length` is `0`' -); - -verifyNotEnumerable(Array.prototype.flatten, 'length'); -verifyNotWritable(Array.prototype.flatten, 'length'); -verifyConfigurable(Array.prototype.flatten, 'length'); - -reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Array/prototype/flatten/name.js b/js/src/tests/test262/built-ins/Array/prototype/flatten/name.js deleted file mode 100644 index f1f93548d3c3..000000000000 --- a/js/src/tests/test262/built-ins/Array/prototype/flatten/name.js +++ /dev/null @@ -1,22 +0,0 @@ -// Copyright (C) 2018 Shilpi Jain and Michael Ficarra. All rights reserved. -// This code is governed by the BSD license found in the LICENSE file. -/*--- -esid: sec-array.prototype.flatten -description: > - Array.prototype.flatten.name value and descriptor. -info: > - 17 ECMAScript Standard Built-in Objects -includes: [propertyHelper.js] -features: [Array.prototype.flatten] ----*/ - -assert.sameValue( - Array.prototype.flatten.name, 'flatten', - 'The value of `Array.prototype.flatten.name` is `"flatten"`' -); - -verifyNotEnumerable(Array.prototype.flatten, 'name'); -verifyNotWritable(Array.prototype.flatten, 'name'); -verifyConfigurable(Array.prototype.flatten, 'name'); - -reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Array/prototype/flatten/null-undefined-elements.js b/js/src/tests/test262/built-ins/Array/prototype/flatten/null-undefined-elements.js deleted file mode 100644 index ca7c5bb6d9e5..000000000000 --- a/js/src/tests/test262/built-ins/Array/prototype/flatten/null-undefined-elements.js +++ /dev/null @@ -1,22 +0,0 @@ -// Copyright (C) 2018 Shilpi Jain and Michael Ficarra. All rights reserved. -// This code is governed by the BSD license found in the LICENSE file. -/*--- -esid: sec-array.prototype.flatten -description: > - arrays with null, and undefined -includes: [compareArray.js] -features: [Array.prototype.flatten] ----*/ - -var a = [void 0]; - -assert(compareArray([1, null, void 0].flatten(), [1, null, undefined])); -assert(compareArray([1, [null, void 0]].flatten(), [1, null, undefined])); -assert(compareArray([ - [null, void 0], - [null, void 0] -].flatten(), [null, undefined, null, undefined])); -assert(compareArray([1, [null, a]].flatten(1), [1, null, a])); -assert(compareArray([1, [null, a]].flatten(2), [1, null, undefined])); - -reportCompare(0, 0); diff --git a/js/src/tests/test262/language/expressions/greater-than/bigint-and-string.js b/js/src/tests/test262/language/expressions/greater-than/bigint-and-string.js index 1349802b4637..6935e082c652 100644 --- a/js/src/tests/test262/language/expressions/greater-than/bigint-and-string.js +++ b/js/src/tests/test262/language/expressions/greater-than/bigint-and-string.js @@ -26,6 +26,15 @@ assert.sameValue(-1n > '1', false, 'The result of (-1n > "1") is false'); assert.sameValue('-1' > 1n, false, 'The result of ("-1" > 1n) is false'); assert.sameValue(-1n > '-1', false, 'The result of (-1n > "-1") is false'); assert.sameValue('-1' > -1n, false, 'The result of ("-1" > -1n) is false'); +assert.sameValue('0x10' > 15n, true, 'The result of ("0x10" > 15n) is true'); +assert.sameValue('0x10' > 16n, false, 'The result of ("0x10" > 16n) is false'); +assert.sameValue('0x10' > 17n, false, 'The result of ("0x10" > 17n) is false'); +assert.sameValue('0o10' > 7n, true, 'The result of ("0o10" > 7n) is true'); +assert.sameValue('0o10' > 8n, false, 'The result of ("0o10" > 8n) is false'); +assert.sameValue('0o10' > 9n, false, 'The result of ("0o10" > 9n) is false'); +assert.sameValue('0b10' > 1n, true, 'The result of ("0b10" > 1n) is true'); +assert.sameValue('0b10' > 2n, false, 'The result of ("0b10" > 2n) is false'); +assert.sameValue('0b10' > 3n, false, 'The result of ("0b10" > 3n) is false'); assert.sameValue( 9007199254740993n > '9007199254740992', @@ -50,4 +59,5 @@ assert.sameValue( true, 'The result of ("-9007199254740992" > -9007199254740993n) is true' ); + reportCompare(0, 0); diff --git a/js/src/tests/test262/language/expressions/less-than/bigint-and-string.js b/js/src/tests/test262/language/expressions/less-than/bigint-and-string.js index 9ec323a26563..75a2dfbef482 100644 --- a/js/src/tests/test262/language/expressions/less-than/bigint-and-string.js +++ b/js/src/tests/test262/language/expressions/less-than/bigint-and-string.js @@ -26,6 +26,15 @@ assert.sameValue(-1n < '1', true, 'The result of (-1n < "1") is true'); assert.sameValue('-1' < 1n, true, 'The result of ("-1" < 1n) is true'); assert.sameValue(-1n < '-1', false, 'The result of (-1n < "-1") is false'); assert.sameValue('-1' < -1n, false, 'The result of ("-1" < -1n) is false'); +assert.sameValue('0x10' < 15n, false, 'The result of ("0x10" < 15n) is false'); +assert.sameValue('0x10' < 16n, false, 'The result of ("0x10" < 16n) is false'); +assert.sameValue('0x10' < 17n, true, 'The result of ("0x10" < 17n) is true'); +assert.sameValue('0o10' < 7n, false, 'The result of ("0o10" < 7n) is false'); +assert.sameValue('0o10' < 8n, false, 'The result of ("0o10" < 8n) is false'); +assert.sameValue('0o10' < 9n, true, 'The result of ("0o10" < 9n) is true'); +assert.sameValue('0b10' < 1n, false, 'The result of ("0b10" < 1n) is false'); +assert.sameValue('0b10' < 2n, false, 'The result of ("0b10" < 2n) is false'); +assert.sameValue('0b10' < 3n, true, 'The result of ("0b10" < 3n) is true'); assert.sameValue( 9007199254740993n < '9007199254740992', @@ -50,4 +59,5 @@ assert.sameValue( false, 'The result of ("-9007199254740992" < -9007199254740993n) is false' ); + reportCompare(0, 0); diff --git a/js/src/tests/test262/language/literals/string/line-continuation-double.js b/js/src/tests/test262/language/literals/string/line-continuation-double.js new file mode 100644 index 000000000000..1ab165a4ddb1 --- /dev/null +++ b/js/src/tests/test262/language/literals/string/line-continuation-double.js @@ -0,0 +1,62 @@ +// Copyright (C) 2018 Richard Gibson. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-literals-string-literals +description: > + Line terminators may occur within string literals as part of a |LineContinuation| + to produce the empty code points sequence. +info: | + 11.8.4 String Literals + + StringLiteral :: + `"` DoubleStringCharacters? `"` + `'` SingleStringCharacters? `'` + + DoubleStringCharacters :: + DoubleStringCharacter DoubleStringCharacters? + + DoubleStringCharacter :: + SourceCharacter but not one of `"` or `\` or LineTerminator + + + `\` EscapeSequence + LineContinuation + + LineContinuation :: + `\` LineTerminatorSequence + + 11.3 Line Terminators + + LineTerminatorSequence :: + + [lookahead != ] + + + + + 11.8.4.2 Static Semantics: SV + + The SV of DoubleStringCharacter :: LineContinuation is the empty code unit sequence. +---*/ + +// LineTerminatorSequence :: +assert.sameValue("\ +", ""); + +// LineTerminatorSequence :: [lookahead ≠ ] +assert.sameValue("\ ", ""); + +// LineTerminatorSequence :: +// is U+2028 LINE SEPARATOR; UTF8(0x2028) = 0xE2 0x80 0xA8 +assert.sameValue("\
", ""); + +// LineTerminatorSequence :: +// is U+2029 PARAGRAPH SEPARATOR; UTF8(0x2029) = 0xE2 0x80 0xA9 +assert.sameValue("\
", ""); + +// LineTerminatorSequence :: +assert.sameValue("\ +", ""); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/language/literals/string/line-continuation-single.js b/js/src/tests/test262/language/literals/string/line-continuation-single.js new file mode 100644 index 000000000000..6c0a5184bfac --- /dev/null +++ b/js/src/tests/test262/language/literals/string/line-continuation-single.js @@ -0,0 +1,62 @@ +// Copyright (C) 2018 Richard Gibson. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-literals-string-literals +description: > + Line terminators may occur within string literals as part of a |LineContinuation| + to produce the empty code points sequence. +info: | + 11.8.4 String Literals + + StringLiteral :: + `"` DoubleStringCharacters? `"` + `'` SingleStringCharacters? `'` + + SingleStringCharacters :: + SingleStringCharacter SingleStringCharacters? + + SingleStringCharacter :: + SourceCharacter but not one of `'` or `\` or LineTerminator + + + `\` EscapeSequence + LineContinuation + + LineContinuation :: + `\` LineTerminatorSequence + + 11.3 Line Terminators + + LineTerminatorSequence :: + + [lookahead != ] + + + + + 11.8.4.2 Static Semantics: SV + + The SV of SingleStringCharacter :: LineContinuation is the empty code unit sequence. +---*/ + +// LineTerminatorSequence :: +assert.sameValue('\ +', ''); + +// LineTerminatorSequence :: [lookahead ≠ ] +assert.sameValue('\ ', ''); + +// LineTerminatorSequence :: +// is U+2028 LINE SEPARATOR; UTF8(0x2028) = 0xE2 0x80 0xA8 +assert.sameValue('\
', ''); + +// LineTerminatorSequence :: +// is U+2029 PARAGRAPH SEPARATOR; UTF8(0x2029) = 0xE2 0x80 0xA9 +assert.sameValue('\
', ''); + +// LineTerminatorSequence :: +assert.sameValue('\ +', ''); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/language/literals/string/line-separator-eval.js b/js/src/tests/test262/language/literals/string/line-separator-eval.js index ee20bb69e56e..4eb677af9902 100644 --- a/js/src/tests/test262/language/literals/string/line-separator-eval.js +++ b/js/src/tests/test262/language/literals/string/line-separator-eval.js @@ -1,4 +1,3 @@ -// |reftest| skip -- json-superset is not supported // Copyright (C) 2018 Richard Gibson. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. diff --git a/js/src/tests/test262/language/literals/string/line-separator.js b/js/src/tests/test262/language/literals/string/line-separator.js index 23248ec8bffd..86e9c507d7f8 100644 --- a/js/src/tests/test262/language/literals/string/line-separator.js +++ b/js/src/tests/test262/language/literals/string/line-separator.js @@ -1,4 +1,3 @@ -// |reftest| skip -- json-superset is not supported // Copyright (C) 2018 Richard Gibson. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. diff --git a/js/src/tests/test262/language/literals/string/paragraph-separator-eval.js b/js/src/tests/test262/language/literals/string/paragraph-separator-eval.js index d88aee74d178..88d7ae6ae90b 100644 --- a/js/src/tests/test262/language/literals/string/paragraph-separator-eval.js +++ b/js/src/tests/test262/language/literals/string/paragraph-separator-eval.js @@ -1,4 +1,3 @@ -// |reftest| skip -- json-superset is not supported // Copyright (C) 2018 Richard Gibson. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. diff --git a/js/src/tests/test262/language/literals/string/paragraph-separator.js b/js/src/tests/test262/language/literals/string/paragraph-separator.js index 433e7db1d926..339e97f89f61 100644 --- a/js/src/tests/test262/language/literals/string/paragraph-separator.js +++ b/js/src/tests/test262/language/literals/string/paragraph-separator.js @@ -1,4 +1,3 @@ -// |reftest| skip -- json-superset is not supported // Copyright (C) 2018 Richard Gibson. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. diff --git a/js/src/vm/Iteration.cpp b/js/src/vm/Iteration.cpp index 31f3fdd364d8..42663e1ad3c3 100644 --- a/js/src/vm/Iteration.cpp +++ b/js/src/vm/Iteration.cpp @@ -9,6 +9,7 @@ #include "vm/Iteration.h" #include "mozilla/DebugOnly.h" +#include "mozilla/Likely.h" #include "mozilla/Maybe.h" #include "mozilla/MemoryReporting.h" #include "mozilla/PodOperations.h" @@ -69,9 +70,14 @@ NativeIterator::trace(JSTracer* trc) guard.trace(trc); }); - std::for_each(propertiesBegin(), propertiesEnd(), + GCPtrFlatString* begin = MOZ_LIKELY(isInitialized()) ? propertiesBegin() : propertyCursor_; + std::for_each(begin, propertiesEnd(), [trc](GCPtrFlatString& prop) { - TraceNullableEdge(trc, &prop, "prop"); + // Properties begin life non-null and never *become* + // null. (Deletion-suppression will shift trailing + // properties over a deleted property in the properties + // array, but it doesn't null them out.) + TraceEdge(trc, &prop, "prop"); }); } @@ -734,6 +740,8 @@ NativeIterator::NativeIterator(JSContext* cx, Handle pr } MOZ_ASSERT(static_cast(guardsEnd_) == propertyCursor_); + markInitialized(); + MOZ_ASSERT(!*hadError); } @@ -1299,9 +1307,7 @@ SuppressDeletedProperty(JSContext* cx, NativeIterator* ni, HandleObject obj, ni->trimLastProperty(); } - // Modified NativeIterators omit properties that possibly shouldn't - // be omitted, so they can't be reused. - ni->markNotReusable(); + ni->markHasUnvisitedPropertyDeletion(); return true; } diff --git a/js/src/vm/Iteration.h b/js/src/vm/Iteration.h index 34e274e11dfb..71835982be71 100644 --- a/js/src/vm/Iteration.h +++ b/js/src/vm/Iteration.h @@ -58,9 +58,10 @@ struct NativeIterator // active. Not serialized by XDR. struct Flags { - static constexpr uint32_t Active = 0x1; - static constexpr uint32_t NotReusable = 0x2; - static constexpr uint32_t All = Active | NotReusable; + static constexpr uint32_t Initialized = 0x1; + static constexpr uint32_t Active = 0x2; + static constexpr uint32_t HasUnvisitedPropertyDeletion = 0x4; + static constexpr uint32_t NotReusable = Active | HasUnvisitedPropertyDeletion; }; private: @@ -131,6 +132,15 @@ struct NativeIterator "HeapReceiverGuards are present, with no padding space " "required for correct alignment"); + // We *could* just check the assertion below if we wanted, but the + // incompletely-initialized NativeIterator case matters for so little + // code that we prefer not imposing the condition-check on every single + // user. + MOZ_ASSERT(isInitialized(), + "NativeIterator must be initialized, or else |guardsEnd_| " + "isn't necessarily the start of properties and instead " + "|propertyCursor_| instead is"); + return reinterpret_cast(guardsEnd_); } @@ -154,12 +164,20 @@ struct NativeIterator } void resetPropertyCursorForReuse() { + MOZ_ASSERT(isInitialized()); + + // This function is called unconditionally on IteratorClose, so + // unvisited properties might have been deleted, so we can't assert + // this NativeIterator is reusable. (Should we not bother resetting + // the cursor in that case?) + // Note: JIT code inlines |propertyCursor_| resetting when an iterator // ends: see |CodeGenerator::visitIteratorEnd|. propertyCursor_ = propertiesBegin(); } bool previousPropertyWas(JS::Handle str) { + MOZ_ASSERT(isInitialized()); return propertyCursor_ > propertiesBegin() && propertyCursor_[-1] == str; } @@ -168,6 +186,8 @@ struct NativeIterator } void trimLastProperty() { + MOZ_ASSERT(isInitialized()); + propertiesEnd_--; // This invokes the pre barrier on this property, since it's no longer @@ -189,6 +209,7 @@ struct NativeIterator } void incCursor() { + MOZ_ASSERT(isInitialized()); propertyCursor_++; } @@ -196,29 +217,52 @@ struct NativeIterator return guardKey_; } + bool isInitialized() const { + return flags_ & Flags::Initialized; + } + + private: + void markInitialized() { + MOZ_ASSERT(flags_ == 0); + flags_ = Flags::Initialized; + } + + public: bool isActive() const { + MOZ_ASSERT(isInitialized()); + return flags_ & Flags::Active; } void markActive() { + MOZ_ASSERT(isInitialized()); + flags_ |= Flags::Active; } void markInactive() { + MOZ_ASSERT(isInitialized()); + flags_ &= ~Flags::Active; } bool isReusable() const { - // Cached NativeIterators are reusable if they're not active and - // aren't marked as not reusable, i.e. if no flags are set. - return flags_ == 0; + MOZ_ASSERT(isInitialized()); + return flags_ == Flags::Initialized; } - void markNotReusable() { - flags_ |= Flags::NotReusable; + void markHasUnvisitedPropertyDeletion() { + MOZ_ASSERT(isInitialized()); + + flags_ |= Flags::HasUnvisitedPropertyDeletion; } void link(NativeIterator* other) { + // The NativeIterator sentinel doesn't have to be linked, because it's + // the start of the list. Anything else added should have been + // initialized. + MOZ_ASSERT(isInitialized()); + /* A NativeIterator cannot appear in the enumerator list twice. */ MOZ_ASSERT(!next_ && !prev_); @@ -228,6 +272,8 @@ struct NativeIterator other->prev_ = this; } void unlink() { + MOZ_ASSERT(isInitialized()); + next_->prev_ = prev_; prev_->next_ = next_; next_ = nullptr; diff --git a/js/xpconnect/tests/chrome/test_xrayToJS.xul b/js/xpconnect/tests/chrome/test_xrayToJS.xul index abe817a55eec..3526ecc9acce 100644 --- a/js/xpconnect/tests/chrome/test_xrayToJS.xul +++ b/js/xpconnect/tests/chrome/test_xrayToJS.xul @@ -203,7 +203,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=933681 "findIndex", "copyWithin", "fill", Symbol.iterator, Symbol.unscopables, "entries", "keys", "values", "constructor"]; if (isNightlyBuild) { - gPrototypeProperties['Array'].push("flatten", "flatMap"); + gPrototypeProperties['Array'].push("flat", "flatMap"); } gConstructorProperties['Array'] = constructorProps(["join", "reverse", "sort", "push", "pop", "shift", diff --git a/js/xpconnect/tests/mochitest/mochitest.ini b/js/xpconnect/tests/mochitest/mochitest.ini index deea5d604eea..ebcbda71b500 100644 --- a/js/xpconnect/tests/mochitest/mochitest.ini +++ b/js/xpconnect/tests/mochitest/mochitest.ini @@ -100,7 +100,7 @@ support-files = [test_frameWrapping.html] # The JS test component we use below is only available in debug builds. [test_getWebIDLCaller.html] -skip-if = (debug == false || os == "android") +skip-if = (debug == false) [test_nac.xhtml] [test_nukeContentWindow.html] [test_sameOriginPolicy.html] diff --git a/layout/reftests/bidi/dirAuto/reftest.list b/layout/reftests/bidi/dirAuto/reftest.list index 0ae405bc8697..5e234b7e60a4 100644 --- a/layout/reftests/bidi/dirAuto/reftest.list +++ b/layout/reftests/bidi/dirAuto/reftest.list @@ -1,9 +1,9 @@ == bdi-auto-dir-default.html bdi-auto-dir-default-ref.html -random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) == dir_auto-set-contained-dir-L.html dir_auto-contained-dir-L-ref.html +random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) == dir_auto-set-contained-dir-L.html dir_auto-contained-dir-L-ref.html # Bug 1392106 == dir_auto-set-contained-dir-R.html dir_auto-contained-dir-R-ref.html -random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) == dir_auto-set-contained-invalid-dir-L.html dir_auto-contained-dir-L-ref.html +random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) == dir_auto-set-contained-invalid-dir-L.html dir_auto-contained-dir-L-ref.html # Bug 1392106 == dir_auto-set-contained-invalid-dir-R.html dir_auto-contained-dir-R-ref.html -== dir_auto-unset-contained-dir-L.html dir_auto-unset-contained-dir-L-ref.html +random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) == dir_auto-unset-contained-dir-L.html dir_auto-unset-contained-dir-L-ref.html # Bug 1392106 == dir_auto-unset-contained-dir-R.html dir_auto-unset-contained-dir-R-ref.html == dynamicDirAuto-setLTR-Auto1.html dynamicDirAuto-refLTR-LTR.html == dynamicDirAuto-setLTR-Auto2.html dynamicDirAuto-refLTR-LTR.html @@ -109,10 +109,10 @@ fuzzy-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)&&!layersGPUAccelerated&&!azur == dynamicDirAuto-DeleteText-RTL1.html dynamicDirAuto-refRTL-RTL.html == dynamicDirAuto-DeleteText-RTL2.html dynamicDirAuto-refRTL-RTL.html == dynamicDirAuto-DeleteText-RTL3.html dynamicDirAuto-refRTL-RTL.html -== 839886-1.html 839886-1-ref.html +random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) == 839886-1.html 839886-1-ref.html # Bug 1392106 == 859093-1.html 859093-1-ref.html == 889742-1.html 889742-1-ref.html -== 1103348-1.html 1103348-1-ref.html +random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) == 1103348-1.html 1103348-1-ref.html # Bug 1392106 == 1169267-delete-add-1a.html 1169267-delete-add-1-ref.html == 1169267-delete-add-1b.html 1169267-delete-add-1-ref.html == 1169267-delete-add-2a.html 1169267-delete-add-2-ref.html diff --git a/layout/reftests/bidi/reftest.list b/layout/reftests/bidi/reftest.list index ac6fcbe57d79..edda2678e20e 100644 --- a/layout/reftests/bidi/reftest.list +++ b/layout/reftests/bidi/reftest.list @@ -109,8 +109,8 @@ fuzzy-if(webrender,122,1) == 562169-1a.html 562169-1-ref.html == 588739-2.html 588739-ref.html == 588739-3.html 588739-ref.html == 612843-1.html 612843-1-ref.html -== 613149-1a.html 613149-1-ref.html -== 613149-1b.html 613149-1-ref.html +random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) == 613149-1a.html 613149-1-ref.html # Bug 1392106 +random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) == 613149-1b.html 613149-1-ref.html # Bug 1392106 fuzzy-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)&&!layersGPUAccelerated&&!azureSkia,36,2) == 613149-2a.html 613149-2-ref.html fuzzy-if(Android,24,1) fuzzy-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)&&!layersGPUAccelerated&&!azureSkia,36,2) == 613149-2b.html 613149-2-ref.html == 613157-1.html 613157-1-ref.html diff --git a/layout/reftests/bugs/reftest.list b/layout/reftests/bugs/reftest.list index 3bcf3ed804da..a86e1171ea08 100644 --- a/layout/reftests/bugs/reftest.list +++ b/layout/reftests/bugs/reftest.list @@ -518,11 +518,11 @@ random-if(cocoaWidget) == 350506-1.html 350506-1-ref.html == 352980-3d.html 352980-3-ref.html == 352980-3e.html 352980-3-ref.html == 352980-3f.html 352980-3-ref.html -== 355548-1.xml 355548-1-ref.xml -== 355548-2.xml 355548-2-ref.xml -== 355548-3.xml 355548-3-ref.xml -== 355548-4.xml 355548-4-ref.xml -== 355548-5.xml 355548-5-ref.xml +random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) == 355548-1.xml 355548-1-ref.xml # Bug 1392106 +random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) == 355548-2.xml 355548-2-ref.xml # Bug 1392106 +random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) == 355548-3.xml 355548-3-ref.xml # Bug 1392106 +random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) == 355548-4.xml 355548-4-ref.xml # Bug 1392106 +random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) == 355548-5.xml 355548-5-ref.xml # Bug 1392106 == 356774-1.html 356774-1-ref.html == 356775-1.html 356775-1-ref.html == 359869-1.html 359869-1-ref.html @@ -656,7 +656,7 @@ fails-if(Android&&!asyncPan) == 371561-1.html 371561-1-ref.html == 372768-1.html 372768-1-ref.html fuzzy-if(webrender&&winWidget,83-83,2-2) == 373295-1.html 373295-1-ref.html == 373298-1.html 373298-1-ref.html -random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) == 373381-1.html 373381-1-ref.html +random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) == 373381-1.html 373381-1-ref.html # Bug 1392106 fuzzy-if(skiaContent&&!Android,2,40) == 373381-2.html 373381-2-ref.html random-if(d2d) == 373381-3.html 373381-3-ref.html == 373381-4.html 373381-4-ref.html @@ -687,7 +687,7 @@ fails-if(Android) != 376532-3.html 376532-3-ref.html == 379178-html.html 379178-html-ref.html == 379178-svg.svg 379178-svg-ref.svg fuzzy-if(skiaContent,1,500) == 379316-1.html 379316-1-ref.html -fails-if(Android) random-if(cocoaWidget) random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) fuzzy-if(winWidget,1,180) fuzzy-if(gtkWidget,1,191) fuzzy-if(skiaContent,8,500) == 379316-2.html 379316-2-ref.html # bug 379786 +fails-if(Android) random-if(cocoaWidget) fuzzy-if(winWidget,1,180) fuzzy-if(gtkWidget,1,191) fuzzy-if(skiaContent,8,500) random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) == 379316-2.html 379316-2-ref.html # bug 379786, Bug 1392106 == 379328-1.html 379328-1-ref.html == 379349-1a.xhtml 379349-1-ref.xhtml # fuzzy because of different border rendering approach in bug 1185636 @@ -715,7 +715,7 @@ fuzzy-if(skiaContent,2,5) == 381507-1.html 381507-1-ref.html == 382916-1.html 382916-1-ref.html == 383035-1.html about:blank == 383035-2.html about:blank -random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) == 383488-1.html 383488-1-ref.html +random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) == 383488-1.html 383488-1-ref.html # Bug 1392106 == 383551-1.html 383551-1-ref.html == 383883-1.html 383883-1-ref.html == 383883-2.html 383883-2-ref.html @@ -754,7 +754,7 @@ test-pref(layout.float-fragments-inside-column.enabled,true) == 386147-1.html 38 == 386470-1a.html 386470-1-ref.html == 386470-1b.html 386470-1-ref.html == 386470-1c.html 386470-1-ref.html -random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) == 386920-1.html 386920-1-ref.html +random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) == 386920-1.html 386920-1-ref.html # Bug 1392106 == 387201-1.html 387201-1-ref.html == 387201-2.html about:blank # Really an assertion test rather than a rendering test == 387201-3.html about:blank # Really an assertion test rather than a rendering test @@ -769,7 +769,7 @@ fails == 387344-1.html 387344-1-ref.html # scrolling rowgroups were removed in b == 389074-1.html 389074-1-ref.html == 389224-1.html 389224-1-ref.html == 389224-2.html about:blank -random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) == 389468-1.html 389468-1-ref.html +random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) == 389468-1.html 389468-1-ref.html # Bug 1392106 == 389623-1.html 389623-1-ref.html == 389636-1.html about:blank # assertion test == 389924-1a.html 389924-1-ref.html @@ -1366,24 +1366,23 @@ pref(browser.display.focus_ring_width,1) == 491180-2.html 491180-2-ref.html == 495274-1.html 495274-1-ref.html == 495354-1a.xhtml 495354-1-ref.xhtml == 495354-1b.xhtml 495354-1-ref.xhtml -== 495385-1a.html 495385-1-ref.html -== 495385-1b.html 495385-1-ref.html -== 495385-1c.html 495385-1-ref.html -== 495385-1d.html 495385-1-ref.html -== 495385-1e.html 495385-1-ref.html -== 495385-1f.html 495385-1-ref.html -== 495385-2a.html 495385-2-ref.html -== 495385-2b.html 495385-2-ref.html -== 495385-2c.html 495385-2-ref.html -== 495385-2d.html 495385-2-ref.html -== 495385-2e.html 495385-2-ref.html -pref(dom.use_xbl_scopes_for_remote_xul,true) == 495385-2f.xhtml 495385-2-ref.html -== 495385-2g.html 495385-2-ref.html -== 495385-2h.html 495385-2-ref.html -== 495385-2i.html 495385-2-ref.html -== 495385-3.html 495385-3-ref.html -== 495385-4.html 495385-4-ref.html -== 495385-5.html 495385-5-ref.html +random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) == 495385-1a.html 495385-1-ref.html # Bug 1392106 +random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) == 495385-1b.html 495385-1-ref.html # Bug 1392106 +random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) == 495385-1c.html 495385-1-ref.html # Bug 1392106 +random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) == 495385-1d.html 495385-1-ref.html # Bug 1392106 +random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) == 495385-1e.html 495385-1-ref.html # Bug 1392106 +random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) == 495385-1f.html 495385-1-ref.html # Bug 1392106 +random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) == 495385-2a.html 495385-2-ref.html # Bug 1392106 +random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) == 495385-2b.html 495385-2-ref.html # Bug 1392106 +random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) == 495385-2c.html 495385-2-ref.html # Bug 1392106 +random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) == 495385-2d.html 495385-2-ref.html # Bug 1392106 +random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) == 495385-2e.html 495385-2-ref.html # Bug 1392106 +pref(dom.use_xbl_scopes_for_remote_xul,true) random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) == 495385-2f.xhtml 495385-2-ref.html # Bug 1392106 +random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) == 495385-2g.html 495385-2-ref.html # Bug 1392106 +random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) == 495385-2h.html 495385-2-ref.html # Bug 1392106 +random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) == 495385-2i.html 495385-2-ref.html # Bug 1392106 +random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) == 495385-3.html 495385-3-ref.html # Bug 1392106 +random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) == 495385-4.html 495385-4-ref.html # Bug 1392106 == 496032-1.html 496032-1-ref.html == 496840-1.html 496840-1-ref.html fuzzy-if(skiaContent,1,17000) == 498228-1.xul 498228-1-ref.xul @@ -1475,7 +1474,7 @@ random == 536061.html 536061-ref.html # fixedpoint division in blur code makes t == 539880-1-dynamic.html 539880-1-ref.html fuzzy-if(Android,12,1000) == 539949-1.html#test2 539949-1-ref.html#test2 == 541382-1.html 541382-1-ref.html -random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)||!haveTestPlugin) HTTP == 541406-1.html 541406-1-ref.html +random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)||!haveTestPlugin) HTTP == 541406-1.html 541406-1-ref.html # Bug 1392106 needs-focus != 542116-1.html 542116-1-ref.html needs-focus != 542116-2.html 542116-2-ref.html needs-focus != 542116-3.html 542116-3-ref.html @@ -1606,9 +1605,9 @@ fails-if(!haveTestPlugin) HTTP == 599476.html 599476-ref.html == 599882-2.html 599882-2-ref.html == 600045-1.html 600045-1-ref.html == 600803-1.html 600803-1-ref.html -random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) == 600974-1.html 600974-1-ref.html -random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) == 600974-2.html 600974-1-ref.html -random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) == 600974-3.html 600974-1-ref.html +random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) == 600974-1.html 600974-1-ref.html # Bug 1392106 +random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) == 600974-2.html 600974-1-ref.html # Bug 1392106 +random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) == 600974-3.html 600974-1-ref.html # Bug 1392106 == 602200-1.html 602200-1-ref.html == 602200-2.html 602200-2-ref.html fuzzy-if(Android,8,20) == 602200-3.html 602200-3-ref.html @@ -1650,7 +1649,7 @@ fuzzy-if(Android,8,300) fuzzy-if(skiaContent,1,40000) == 625409-1.html 625409-1- == 627393-1.html about:blank fuzzy-if(skiaContent,1,500) == 630835-1.html about:blank == 631352-1.html 631352-1-ref.html -skip-if(!haveTestPlugin) fails-if(Android) fuzzy-if(winWidget&&!layersGPUAccelerated,102,535) fuzzy-if(skiaContent&&!Android,102,11000) HTTP == 632423-1.html 632423-1-ref.html +skip-if(!haveTestPlugin) fails-if(Android) fuzzy-if(winWidget&&!layersGPUAccelerated,102,535) fuzzy-if(skiaContent&&!Android,102,11000) random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) HTTP == 632423-1.html 632423-1-ref.html # Bug 1392106 skip-if(Android) random-if(winWidget||OSX==1010) == 632781-verybig.html 632781-ref.html == 632781-normalsize.html 632781-ref.html fuzzy-if(d2d&&/^Windows\x20NT\x206\.2/.test(http.oscpu),1,559) fuzzy-if(!isDebugBuild&>kWidget&&/^Linux\x20i686/.test(http.oscpu),102,140) == 633344-1.html 633344-1-ref.html # bug 1103623, Linux32 from GCC update @@ -1767,7 +1766,7 @@ fuzzy-if(Android,4,400) == 815593-1.html 815593-1-ref.html fuzzy-if(skiaContent,1,5) == 816948-1.html 816948-1-ref.html == 817019-1.html about:blank fuzzy-if(skiaContent,1,5) == 818276-1.html 818276-1-ref.html -fuzzy-if(asyncPan,190,510) fuzzy-if(asyncPan&&!layersGPUAccelerated,102,510) == 825999.html 825999-ref.html +fuzzy-if(asyncPan,190,510) fuzzy-if(asyncPan&&!layersGPUAccelerated,102,510) random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) == 825999.html 825999-ref.html # Bug 1392106 == 827577-1a.html 827577-1-ref.html == 827577-1b.html 827577-1-ref.html == 827799-1.html about:blank @@ -1817,7 +1816,7 @@ fuzzy-if(skiaContent,1,5) == 956513-1.svg 956513-1-ref.svg fuzzy-if(skiaContent,1,80) == 961887-1.html 961887-1-ref.html == 961887-2.html 961887-2-ref.html == 961887-3.html 961887-3-ref.html -pref(layout.css.overflow-clip-box.enabled,true) random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) fuzzy(50,145) fuzzy-if(asyncPan&&!layersGPUAccelerated,102,3712) fuzzy-if(webrender,255,51) == 966992-1.html 966992-1-ref.html +pref(layout.css.overflow-clip-box.enabled,true) fuzzy(50,145) fuzzy-if(asyncPan&&!layersGPUAccelerated,102,3712) fuzzy-if(webrender,255,51) random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) == 966992-1.html 966992-1-ref.html # Bug 1392106 skip-if(Android) == 966510-1.html 966510-1-ref.html # scrollable elements other than the root probably won't work well on android until bug 776030 is fixed skip-if(Android) == 966510-2.html 966510-2-ref.html # same as above fuzzy-if(skiaContent,1,123) == 978911-1.svg 978911-1-ref.svg diff --git a/layout/reftests/canvas/reftest.list b/layout/reftests/canvas/reftest.list index 8a308637eb99..e25ca34e98a0 100644 --- a/layout/reftests/canvas/reftest.list +++ b/layout/reftests/canvas/reftest.list @@ -48,7 +48,7 @@ fuzzy-if(azureSkiaGL,10,400) == text-not-in-doc-test.html text-not-in-doc-ref.ht != text-font-lang.html text-font-lang-notref.html == text-measure.html text-measure-ref.html -== text-small-caps-1.html text-small-caps-1-ref.html +random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) == text-small-caps-1.html text-small-caps-1-ref.html # Bug 1392106 random-if(!d2d) != text-subpixel-1.html text-subpixel-1-ref.html diff --git a/layout/reftests/counters/reftest.list b/layout/reftests/counters/reftest.list index f8f3c2b9d41c..cde7375178b3 100644 --- a/layout/reftests/counters/reftest.list +++ b/layout/reftests/counters/reftest.list @@ -8,7 +8,7 @@ == t1202-counter-06-b-test.html t1202-counter-06-b-reference.html == t1202-counter-07-b-test.html t1202-counter-07-b-reference.html == t1202-counter-08-b-test.html t1202-counter-08-b-reference.html -random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) == t1202-counter-09-b-test.html t1202-counter-09-b-reference.html +random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) == t1202-counter-09-b-test.html t1202-counter-09-b-reference.html # Bug 1392106 == t1202-counter-10-b-test.html t1202-counter-10-b-reference.html == t1202-counter-11-b-test.html t1202-counter-11-b-reference.html == t1202-counter-12-b-test.html t1202-counter-12-b-reference.html @@ -25,7 +25,7 @@ random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) == t1202-counter-09-b-test. == t1202-counters-06-b-test.html t1202-counters-06-b-reference.html == t1202-counters-07-b-test.html t1202-counters-07-b-reference.html == t1202-counters-08-b-test.html t1202-counters-08-b-reference.html -== t1202-counters-09-b-test.html t1202-counters-09-b-reference.html +random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) == t1202-counters-09-b-test.html t1202-counters-09-b-reference.html # Bug 1392106 == t1202-counters-10-b-test.html t1202-counters-10-b-reference.html == t1202-counters-11-b-test.html t1202-counters-11-b-reference.html == t1202-counters-12-b-test.html t1202-counters-12-b-reference.html @@ -68,15 +68,15 @@ random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) == t1202-counter-09-b-test. == counter-ua-limits-list-00.html counter-ua-limits-list-00-ref.html == counter-ua-limits-list-01.html counter-ua-limits-list-01-ref.html == multiple-thai-counters.html multiple-thai-counters-ref.html -fuzzy-if(webrender&&cocoaWidget,40-40,6-6) == counter-suffix.html counter-suffix-ref.html -random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) == counter-cjk-decimal.html counter-cjk-decimal-ref.html -random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) == counter-japanese-informal.html counter-japanese-informal-ref.html -random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) == counter-japanese-formal.html counter-japanese-formal-ref.html -random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) == counter-korean-hangul-formal.html counter-korean-hangul-formal-ref.html -random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) == counter-korean-hanja-informal.html counter-korean-hanja-informal-ref.html -random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) == counter-korean-hanja-formal.html counter-korean-hanja-formal-ref.html -random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) == counter-simp-chinese-informal.html counter-simp-chinese-informal-ref.html -random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) == counter-simp-chinese-formal.html counter-simp-chinese-formal-ref.html -random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) == counter-trad-chinese-informal.html counter-trad-chinese-informal-ref.html -random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) == counter-trad-chinese-formal.html counter-trad-chinese-formal-ref.html -random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) == counter-ethiopic-numeric.html counter-ethiopic-numeric-ref.html +fuzzy-if(webrender&&cocoaWidget,40-40,6-6) random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) == counter-suffix.html counter-suffix-ref.html # Bug 1392106 +random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) == counter-cjk-decimal.html counter-cjk-decimal-ref.html # Bug 1392106 +random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) == counter-japanese-informal.html counter-japanese-informal-ref.html # Bug 1392106 +random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) == counter-japanese-formal.html counter-japanese-formal-ref.html # Bug 1392106 +random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) == counter-korean-hangul-formal.html counter-korean-hangul-formal-ref.html # Bug 1392106 +random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) == counter-korean-hanja-informal.html counter-korean-hanja-informal-ref.html # Bug 1392106 +random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) == counter-korean-hanja-formal.html counter-korean-hanja-formal-ref.html # Bug 1392106 +random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) == counter-simp-chinese-informal.html counter-simp-chinese-informal-ref.html # Bug 1392106 +random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) == counter-simp-chinese-formal.html counter-simp-chinese-formal-ref.html # Bug 1392106 +random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) == counter-trad-chinese-informal.html counter-trad-chinese-informal-ref.html # Bug 1392106 +random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) == counter-trad-chinese-formal.html counter-trad-chinese-formal-ref.html # Bug 1392106 +random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) == counter-ethiopic-numeric.html counter-ethiopic-numeric-ref.html # Bug 1392106 diff --git a/layout/reftests/css-break/reftest.list b/layout/reftests/css-break/reftest.list index 315a2d9d62b9..8c8016a34ebc 100644 --- a/layout/reftests/css-break/reftest.list +++ b/layout/reftests/css-break/reftest.list @@ -8,7 +8,7 @@ random-if(!gtkWidget) == box-decoration-break-border-image.html box-decoration-b == box-decoration-break-block-margin.html box-decoration-break-block-margin-ref.html fuzzy-if(!Android,1,62) fuzzy-if(Android,8,6627) == box-decoration-break-first-letter.html box-decoration-break-first-letter-ref.html #Bug 1313773 == box-decoration-break-with-bidi.html box-decoration-break-with-bidi-ref.html -== box-decoration-break-bug-1235152.html box-decoration-break-bug-1235152-ref.html -== box-decoration-break-bug-1249913.html box-decoration-break-bug-1249913-ref.html +random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) == box-decoration-break-bug-1235152.html box-decoration-break-bug-1235152-ref.html # Bug 1392106 +random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) == box-decoration-break-bug-1249913.html box-decoration-break-bug-1249913-ref.html # Bug 1392106 == vertical-wm-001.html vertical-wm-001-ref.html random-if(Android) == 1405443.html 1405443-ref.html diff --git a/layout/reftests/css-grid/reftest.list b/layout/reftests/css-grid/reftest.list index 1b5c52da1a22..58d8f99cb9b7 100644 --- a/layout/reftests/css-grid/reftest.list +++ b/layout/reftests/css-grid/reftest.list @@ -52,11 +52,11 @@ fuzzy-if(winWidget,70,130) fuzzy-if(cocoaWidget,85,180) == grid-col-max-sizing-m fuzzy-if(winWidget,70,130) fuzzy-if(cocoaWidget,85,180) == grid-col-max-sizing-max-content-002.html grid-col-max-sizing-max-content-002-ref.html == grid-min-max-content-sizing-001.html grid-min-max-content-sizing-001-ref.html == grid-min-max-content-sizing-002.html grid-min-max-content-sizing-002-ref.html -fuzzy-if(winWidget,1,36) random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) == grid-auto-min-sizing-definite-001.html grid-auto-min-sizing-definite-001-ref.html -random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) == grid-auto-min-sizing-intrinsic-001.html grid-auto-min-sizing-intrinsic-001-ref.html -random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) == grid-auto-min-sizing-intrinsic-002.html grid-auto-min-sizing-intrinsic-002-ref.html -random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) == grid-auto-min-sizing-intrinsic-003.html grid-auto-min-sizing-intrinsic-003-ref.html -random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) == grid-auto-min-sizing-intrinsic-004.html grid-auto-min-sizing-intrinsic-004-ref.html +fuzzy-if(winWidget,1,36) random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) == grid-auto-min-sizing-definite-001.html grid-auto-min-sizing-definite-001-ref.html # Bug 1392106 +random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) == grid-auto-min-sizing-intrinsic-001.html grid-auto-min-sizing-intrinsic-001-ref.html # Bug 1392106 +random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) == grid-auto-min-sizing-intrinsic-002.html grid-auto-min-sizing-intrinsic-002-ref.html # Bug 1392106 +random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) == grid-auto-min-sizing-intrinsic-003.html grid-auto-min-sizing-intrinsic-003-ref.html # Bug 1392106 +random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) == grid-auto-min-sizing-intrinsic-004.html grid-auto-min-sizing-intrinsic-004-ref.html # Bug 1392106 == grid-auto-min-sizing-transferred-size-001.html grid-auto-min-sizing-transferred-size-001-ref.html == grid-auto-min-sizing-transferred-size-002.html grid-auto-min-sizing-transferred-size-002-ref.html == grid-auto-min-sizing-transferred-size-003.html grid-auto-min-sizing-transferred-size-003-ref.html @@ -92,7 +92,7 @@ skip-if(Android) == grid-auto-min-sizing-percent-001.html grid-auto-min-sizing-p == grid-item-align-003.html grid-item-align-003-ref.html == grid-item-justify-001.html grid-item-justify-001-ref.html == grid-item-justify-002.html grid-item-justify-002-ref.html -== grid-item-stretch-001.html grid-item-stretch-001-ref.html +random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) == grid-item-stretch-001.html grid-item-stretch-001-ref.html # Bug 1392106 == grid-item-intrinsic-ratio-stretch-001.html grid-item-intrinsic-ratio-stretch-001-ref.html == grid-item-intrinsic-ratio-stretch-002.html grid-item-intrinsic-ratio-stretch-002-ref.html == grid-item-intrinsic-ratio-stretch-003.html grid-item-intrinsic-ratio-stretch-003-ref.html @@ -108,7 +108,7 @@ skip-if(Android) == grid-auto-min-sizing-percent-001.html grid-auto-min-sizing-p == grid-item-intrinsic-size-normal-001.html grid-item-intrinsic-size-normal-001-ref.html == grid-item-intrinsic-size-normal-002.html grid-item-intrinsic-size-normal-002-ref.html == grid-item-auto-min-size-clamp-001.html grid-item-auto-min-size-clamp-001-ref.html -random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) == grid-item-auto-min-size-clamp-002.html grid-item-auto-min-size-clamp-002-ref.html +random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) == grid-item-auto-min-size-clamp-002.html grid-item-auto-min-size-clamp-002-ref.html # Bug 1392106 == grid-item-auto-min-size-clamp-003.html grid-item-auto-min-size-clamp-003-ref.html # == grid-item-auto-min-size-clamp-004.html grid-item-auto-min-size-clamp-004-ref.html # bug 1421976 == grid-item-auto-min-size-clamp-005.html grid-item-auto-min-size-clamp-005-ref.html diff --git a/layout/reftests/font-face/reftest.list b/layout/reftests/font-face/reftest.list index 20d4f7413383..4fb7c759c9cd 100644 --- a/layout/reftests/font-face/reftest.list +++ b/layout/reftests/font-face/reftest.list @@ -23,8 +23,8 @@ random-if(winWidget||gtkWidget) == src-list-2-big-otf.html src-list-2-big-ref.ht # assumes AAT fonts are only supported on MacOS random-if(cocoaWidget) == src-list-format-7.html src-list-format-2-ref.html random-if(!cocoaWidget) == src-list-format-7.html src-list-format-3-ref.html -random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) fails-if(Android) == src-list-local-full.html src-list-local-full-ref.html -random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) fails-if(Android) == src-list-local-full-quotes.html src-list-local-full-ref.html +random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) fails-if(Android) == src-list-local-full.html src-list-local-full-ref.html # Bug 1392106 +random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) fails-if(Android) == src-list-local-full-quotes.html src-list-local-full-ref.html # Bug 1392106 == src-list-local-fallback.html src-list-local-fallback-ref.html # data url tests (these don't need the HTTP server) @@ -94,7 +94,7 @@ random-if(cocoaWidget) == sheet-set-switch-1.html sheet-set-switch-1-ref.html # == local-styled-1.html local-styled-1-ref.html == synthetic-weight-style.html synthetic-weight-style-ref.html -== synthetic-variations.html synthetic-variations-ref.html +random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) == synthetic-variations.html synthetic-variations-ref.html # Bug 1392106 # Leak test load 486974-1.html @@ -182,16 +182,16 @@ skip-if(/^Linux\x20i686/.test(http.oscpu)) HTTP(..) == font-display-1.html font- fuzzy-if(OSX==1010,3,5) HTTP(..) == font-display-2.html font-display-2-ref.html # font load takes 4500ms # Testing hack for Meiryo -random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) == meiryo-en.html meiryo-ja.html -random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) == meiryo-en-bold.html meiryo-ja-bold.html -random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) == meiryo-en-italic.html meiryo-ja-italic.html -random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) == meiryo-en-oblique.html meiryo-ja-oblique.html -random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) == meiryo-en-bolditalic.html meiryo-ja-bolditalic.html -random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) != meiryo-en-bold.html meiryo-en.html -random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) != meiryo-en-italic.html meiryo-en.html -random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) != meiryo-en-oblique.html meiryo-en.html -random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) != meiryo-en-bolditalic.html meiryo-en.html -random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) != meiryo-en-bolditalic.html meiryo-en-bold.html +random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) == meiryo-en.html meiryo-ja.html # Bug 1392106 +random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) == meiryo-en-bold.html meiryo-ja-bold.html # Bug 1392106 +random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) == meiryo-en-italic.html meiryo-ja-italic.html # Bug 1392106 +random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) == meiryo-en-oblique.html meiryo-ja-oblique.html # Bug 1392106 +random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) == meiryo-en-bolditalic.html meiryo-ja-bolditalic.html # Bug 1392106 +random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) != meiryo-en-bold.html meiryo-en.html # Bug 1392106 +random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) != meiryo-en-italic.html meiryo-en.html # Bug 1392106 +random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) != meiryo-en-oblique.html meiryo-en.html # Bug 1392106 +random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) != meiryo-en-bolditalic.html meiryo-en.html # Bug 1392106 +random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) != meiryo-en-bolditalic.html meiryo-en-bold.html # Bug 1392106 # test support of variation-font format hints default-preferences pref(layout.css.font-variations.enabled,false) diff --git a/layout/reftests/mathml/reftest.list b/layout/reftests/mathml/reftest.list index 42ab8661b96b..a6cd9b5a2d46 100644 --- a/layout/reftests/mathml/reftest.list +++ b/layout/reftests/mathml/reftest.list @@ -13,10 +13,10 @@ fails == dir-9.html dir-9-ref.html # Bug 787215 == css-spacing-1.html css-spacing-1-ref.html pref(mathml.disabled,true) == disabled-scriptlevel-1.html disabled-scriptlevel-1-ref.html pref(mathml.disabled,true) == disabled-scriptlevel-1.xhtml disabled-scriptlevel-1-ref.xhtml -== displaystyle-1.html displaystyle-1-ref.html -== displaystyle-2.html displaystyle-2-ref.html -== displaystyle-3.html displaystyle-3-ref.html -== displaystyle-4.html displaystyle-4-ref.html +random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) == displaystyle-1.html displaystyle-1-ref.html # Bug 1392106 +random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) == displaystyle-2.html displaystyle-2-ref.html # Bug 1392106 +random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) == displaystyle-3.html displaystyle-3-ref.html # Bug 1392106 +random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) == displaystyle-4.html displaystyle-4-ref.html # Bug 1392106 random-if(smallScreen&&Android) fuzzy(255,200) fuzzy-if(webrender&&!gtkWidget,114-255,265-304) == mirror-op-1.html mirror-op-1-ref.html != mirror-op-2.html mirror-op-2-ref.html != mirror-op-3.html mirror-op-3-ref.html @@ -24,26 +24,26 @@ random-if(smallScreen&&Android) fuzzy(255,200) fuzzy-if(webrender&&!gtkWidget,11 == dynamic-mi.xhtml dynamic-mi-ref.xhtml == mphantom-1.html mphantom-1-ref.html == mphantom-2.html mphantom-2-ref.html -random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) == mfenced-1.xhtml mfenced-1-ref.xhtml -random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) == mfenced-2a.xhtml mfenced-2-ref.xhtml -random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) == mfenced-2b.xhtml mfenced-2-ref.xhtml -random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) == mfenced-3a.xhtml mfenced-3-ref.xhtml -random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) == mfenced-3b.xhtml mfenced-3-ref.xhtml -random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) == mfenced-3c.xhtml mfenced-3-ref.xhtml -random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) == mfenced-3d.xhtml mfenced-3-ref.xhtml -random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) == mfenced-4a.xhtml mfenced-4-ref.xhtml -random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) == mfenced-4b.xhtml mfenced-4-ref.xhtml -random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) == mfenced-5a.xhtml mfenced-5-ref.xhtml -random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) == mfenced-5b.xhtml mfenced-5-ref.xhtml -random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) == mfenced-5c.xhtml mfenced-5-ref.xhtml -random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) == mfenced-5d.xhtml mfenced-5-ref.xhtml -random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) == mfenced-6.html mfenced-6-ref.html -== mfenced-7.html mfenced-7-ref.html -!= mfenced-8.html mfenced-8-ref.html -== mfenced-9.html mfenced-9-ref.html -== mfenced-10.html mfenced-10-ref.html -fails-if(gtkWidget) == mfenced-11.html mfenced-11-ref.html # bug 670592, bug 1328771 -fails-if(gtkWidget) == mfenced-12.html mfenced-12-ref.html # bug 670592, bug 1328771 +random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) == mfenced-1.xhtml mfenced-1-ref.xhtml # Bug 1392106 +random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) == mfenced-2a.xhtml mfenced-2-ref.xhtml # Bug 1392106 +random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) == mfenced-2b.xhtml mfenced-2-ref.xhtml # Bug 1392106 +random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) == mfenced-3a.xhtml mfenced-3-ref.xhtml # Bug 1392106 +random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) == mfenced-3b.xhtml mfenced-3-ref.xhtml # Bug 1392106 +random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) == mfenced-3c.xhtml mfenced-3-ref.xhtml # Bug 1392106 +random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) == mfenced-3d.xhtml mfenced-3-ref.xhtml # Bug 1392106 +random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) == mfenced-4a.xhtml mfenced-4-ref.xhtml # Bug 1392106 +random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) == mfenced-4b.xhtml mfenced-4-ref.xhtml # Bug 1392106 +random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) == mfenced-5a.xhtml mfenced-5-ref.xhtml # Bug 1392106 +random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) == mfenced-5b.xhtml mfenced-5-ref.xhtml # Bug 1392106 +random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) == mfenced-5c.xhtml mfenced-5-ref.xhtml # Bug 1392106 +random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) == mfenced-5d.xhtml mfenced-5-ref.xhtml # Bug 1392106 +random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) == mfenced-6.html mfenced-6-ref.html # Bug 1392106 +random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) == mfenced-7.html mfenced-7-ref.html # Bug 1392106 +random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) != mfenced-8.html mfenced-8-ref.html # Bug 1392106 +random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) == mfenced-9.html mfenced-9-ref.html # Bug 1392106 +random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) == mfenced-10.html mfenced-10-ref.html # Bug 1392106 +fails-if(gtkWidget) random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) == mfenced-11.html mfenced-11-ref.html # bug 670592, bug 1328771, Bug 1392106 +fails-if(gtkWidget) random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) == mfenced-12.html mfenced-12-ref.html # bug 670592, bug 1328771, Bug 1392106 == mi-mathvariant-1.xhtml mi-mathvariant-1-ref.xhtml == mi-mathvariant-2.xhtml mi-mathvariant-2-ref.xhtml != mi-mathvariant-3.html mi-mathvariant-3-ref.html @@ -184,7 +184,7 @@ random-if(gtkWidget) == mpadded-9.html mpadded-9-ref.html # bug 1309430 == mtable-columnalign-multi-mtable.html mtable-columnalign-multi-ref.html == mtable-columnalign-multi-mtable-dynamic.html mtable-columnalign-multi-ref.html == maction-selection.html maction-selection-ref.html -== maction-dynamic-embellished-op.html maction-dynamic-embellished-op-ref.html +random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) == maction-dynamic-embellished-op.html maction-dynamic-embellished-op-ref.html # Bug 1392106 == maction-dynamic-1.html maction-dynamic-1-ref.html # bug 773482 == maction-dynamic-2.html maction-dynamic-2-ref.html == mo-lspace-rspace.html mo-lspace-rspace-ref.html diff --git a/layout/reftests/object/reftest.list b/layout/reftests/object/reftest.list index 1437c897c2e3..c3a2e9b0f81d 100644 --- a/layout/reftests/object/reftest.list +++ b/layout/reftests/object/reftest.list @@ -3,7 +3,7 @@ HTTP == 404-data.html 404-data-ref.html HTTP == 404-data-with-type.html 404-data-with-type-ref.html == page-as-data.html page-as-data-ref.html == page-as-data-with-type.html page-as-data-with-type-ref.html -== connection-refused.html connection-refused-ref.html +random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) == connection-refused.html connection-refused-ref.html # Bug 1392106 == image.html image-ref.html == image-with-type.html image-with-type-ref.html fails-if(Android) == image-no-useful-extension-typesniff.html image-no-useful-extension-typesniff-ref.html diff --git a/layout/reftests/svg/smil/reftest.list b/layout/reftests/svg/smil/reftest.list index f75e5bea5f88..cfaf9f912318 100644 --- a/layout/reftests/svg/smil/reftest.list +++ b/layout/reftests/svg/smil/reftest.list @@ -165,7 +165,7 @@ fuzzy-if(Android,4,1) == anim-svg-viewBox-01.svg lime.svg == anim-paintserver-1.svg anim-paintserver-1-ref.svg # animate attributes on text content children -random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) == anim-text-attr-01.svg anim-text-attr-01-ref.svg +random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) == anim-text-attr-01.svg anim-text-attr-01-ref.svg # Bug 1392106 # animate where the base value is non-interpolatable but will be replaced anyway == anim-fill-overpaintserver-1.svg lime.svg @@ -207,7 +207,7 @@ fails == anim-strokecolor-1.svg anim-standard-ref.svg # bug 436296 == anim-targethref-9.svg anim-standard-ref.svg == anim-targethref-10.svg anim-standard-ref.svg -random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) == anim-text-rotate-01.svg anim-text-rotate-01-ref.svg +random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) == anim-text-rotate-01.svg anim-text-rotate-01-ref.svg # Bug 1392106 == anim-feFuncR-tableValues-01.svg anim-feFuncR-tableValues-01-ref.svg skip == anim-text-x-y-dx-dy-01.svg anim-text-x-y-dx-dy-01-ref.svg # bug 579588 diff --git a/layout/reftests/svg/smil/style/reftest.list b/layout/reftests/svg/smil/style/reftest.list index 77c06bc42eb0..755f01e87f7b 100644 --- a/layout/reftests/svg/smil/style/reftest.list +++ b/layout/reftests/svg/smil/style/reftest.list @@ -71,12 +71,12 @@ fuzzy-if(skiaContent,1,365) == anim-css-fillopacity-3-clamp-small.svg anim-css # 'font-size' property, from/by/to with pixel values only == anim-css-fontsize-1-from-by-px-px.svg anim-css-fontsize-1-ref.svg -random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) == anim-css-fontsize-1-from-to-px-px.svg anim-css-fontsize-1-ref.svg +random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) == anim-css-fontsize-1-from-to-px-px.svg anim-css-fontsize-1-ref.svg # Bug 1392106 # 'font-size' property (accepts unitless values) -random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) == anim-css-fontsize-1-from-to-no-no.svg anim-css-fontsize-1-ref.svg -random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) == anim-css-fontsize-1-from-to-no-px.svg anim-css-fontsize-1-ref.svg -random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) == anim-css-fontsize-1-from-to-px-no.svg anim-css-fontsize-1-ref.svg +random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) == anim-css-fontsize-1-from-to-no-no.svg anim-css-fontsize-1-ref.svg # Bug 1392106 +random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) == anim-css-fontsize-1-from-to-no-px.svg anim-css-fontsize-1-ref.svg # Bug 1392106 +random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) == anim-css-fontsize-1-from-to-px-no.svg anim-css-fontsize-1-ref.svg # Bug 1392106 # 'font-size' mapped attribute (accepts unitless values) == anim-mapped-fontsize-1-from-to-no-no.svg anim-css-fontsize-1-ref.svg @@ -87,14 +87,14 @@ random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) == anim-css-fontsize-1-from == anim-css-fontsize-1-from-by-pct-pct.svg anim-css-fontsize-1-ref.svg == anim-css-fontsize-1-from-by-pct-px.svg anim-css-fontsize-1-ref.svg == anim-css-fontsize-1-from-by-px-pct.svg anim-css-fontsize-1-ref.svg -random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) == anim-css-fontsize-1-from-to-pct-pct.svg anim-css-fontsize-1-ref.svg -random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) == anim-css-fontsize-1-from-to-pct-px.svg anim-css-fontsize-1-ref.svg -random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) == anim-css-fontsize-1-from-to-px-pct.svg anim-css-fontsize-1-ref.svg +random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) == anim-css-fontsize-1-from-to-pct-pct.svg anim-css-fontsize-1-ref.svg # Bug 1392106 +random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) == anim-css-fontsize-1-from-to-pct-px.svg anim-css-fontsize-1-ref.svg # Bug 1392106 +random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) == anim-css-fontsize-1-from-to-px-pct.svg anim-css-fontsize-1-ref.svg # Bug 1392106 # 'font-size' property, with negative addition == anim-css-fontsize-2-from-by-px-px.svg anim-css-fontsize-2-ref.svg == anim-css-fontsize-2-from-by-px-em.svg anim-css-fontsize-2-ref.svg -== anim-css-fontsize-2-from-by-em-em.svg anim-css-fontsize-2-ref.svg +random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) == anim-css-fontsize-2-from-by-em-em.svg anim-css-fontsize-2-ref.svg # Bug 1392106 # 'stroke-dasharray' property, from/to with pixel values only fails == anim-css-strokedasharray-1.svg anim-css-strokedasharray-1-ref.svg # bug 474049 diff --git a/layout/reftests/svg/text/reftest.list b/layout/reftests/svg/text/reftest.list index cc3a3febacd7..89269a8d50d1 100644 --- a/layout/reftests/svg/text/reftest.list +++ b/layout/reftests/svg/text/reftest.list @@ -110,17 +110,17 @@ fuzzy-if(Android,242,81) == multiple-chunks-directions-and-anchor-multiple-dx.sv == simple-multiline-pc.svg simple-multiline-pc-ref.svg == simple-multiline-anchor-end.svg simple-multiline-anchor-end-ref.svg -random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) fuzzy-if(skiaContent,1,15) == textpath.svg textpath-ref.svg -random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) == textpath-a.svg textpath-a-ref.svg -random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) == textpath-anchor-middle.svg textpath-anchor-middle-ref.svg -random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) == textpath-anchor-end.svg textpath-anchor-end-ref.svg -random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) == textpath-invalid-parent.svg textpath-invalid-parent-ref.svg -random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) == textpath-multiline.svg textpath-multiline-ref.svg -random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) == textpath-multiline-2.svg textpath-multiline-2-ref.svg -random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) == textpath-after.svg textpath-after-ref.svg -random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) == textpath-after-anchor-end.svg textpath-after-anchor-end-ref.svg -random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) == textpath-reset-position.svg textpath-reset-position-ref.svg -random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) == textpath-inherit-position.svg textpath-inherit-position-ref.svg +random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) fuzzy-if(skiaContent,1,15) == textpath.svg textpath-ref.svg # Bug 1392106 +random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) == textpath-a.svg textpath-a-ref.svg # Bug 1392106 +random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) == textpath-anchor-middle.svg textpath-anchor-middle-ref.svg # Bug 1392106 +random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) == textpath-anchor-end.svg textpath-anchor-end-ref.svg # Bug 1392106 +random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) == textpath-invalid-parent.svg textpath-invalid-parent-ref.svg # Bug 1392106 +random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) == textpath-multiline.svg textpath-multiline-ref.svg # Bug 1392106 +random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) == textpath-multiline-2.svg textpath-multiline-2-ref.svg # Bug 1392106 +random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) == textpath-after.svg textpath-after-ref.svg # Bug 1392106 +random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) == textpath-after-anchor-end.svg textpath-after-anchor-end-ref.svg # Bug 1392106 +random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) == textpath-reset-position.svg textpath-reset-position-ref.svg # Bug 1392106 +random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) == textpath-inherit-position.svg textpath-inherit-position-ref.svg # Bug 1392106 == textLength.svg textLength-ref.svg fuzzy-if(skiaContent,1,200) == textLength-2.svg textLength-2-ref.svg @@ -143,7 +143,7 @@ fuzzy-if(/^Windows\x20NT\x2010\.0/.test(http.oscpu)||/^Windows\x20NT\x206\.[12]/ == ignore-position.svg ignore-position-ref.svg == ignore-margin.svg ignore-prop-ref.svg == ignore-padding.svg ignore-prop-ref.svg -== ignore-vertical-align.svg ignore-vertical-align-ref.svg +random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) == ignore-vertical-align.svg ignore-vertical-align-ref.svg # Bug 1392106 == ignore-overflow-scroll.svg ignore-prop-ref.svg == ignore-text-align.svg ignore-prop-ref.svg == ignore-text-align-2.svg ignore-text-align-2-ref.svg @@ -189,7 +189,7 @@ fuzzy-if(cocoaWidget,1,6) fuzzy-if(skiaContent,65,313) == pattern-content.svg pa fuzzy-if(skiaContent&&winWidget,126,336) == filter-applied.svg filter-applied-ref.svg # vertical text -fuzzy-if(skiaContent,1,80) random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) == textpath-vertical-dx.svg textpath-vertical-dx-ref.svg +fuzzy-if(skiaContent,1,80) random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) == textpath-vertical-dx.svg textpath-vertical-dx-ref.svg # Bug 1392106 # selection needs-focus == deselectAll.svg deselectAll-ref.svg diff --git a/layout/reftests/table-bordercollapse/reftest.list b/layout/reftests/table-bordercollapse/reftest.list index c17a37d0740c..a18399a3cdec 100644 --- a/layout/reftests/table-bordercollapse/reftest.list +++ b/layout/reftests/table-bordercollapse/reftest.list @@ -1,8 +1,8 @@ -== bug1375518.html bug1375518-ref.html -== bug1375518-2.html bug1375518-ref.html -== bug1375518-3.html bug1375518-ref.html -== bug1375518-4.html bug1375518-4-ref.html -== bug1375518-5.html bug1375518-5-ref.html +random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) == bug1375518.html bug1375518-ref.html # Bug 1392106 +random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) == bug1375518-2.html bug1375518-ref.html # Bug 1392106 +random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) == bug1375518-3.html bug1375518-ref.html # Bug 1392106 +random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) == bug1375518-4.html bug1375518-4-ref.html # Bug 1392106 +random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) == bug1375518-5.html bug1375518-5-ref.html # Bug 1392106 == bug1379306.html bug1379306-ref.html == bug1394226.html bug1394226-ref.html != bug1394226.html bug1394226-notref.html diff --git a/layout/reftests/table-html/reftest.list b/layout/reftests/table-html/reftest.list index c3a4010ca466..9fbd51aa3552 100644 --- a/layout/reftests/table-html/reftest.list +++ b/layout/reftests/table-html/reftest.list @@ -1,4 +1,4 @@ == cell-align-stopped-at-table-1-standards.html cell-align-stopped-at-table-1-standards-ref.html == cell-align-stopped-at-table-1-quirks.html cell-align-stopped-at-table-1-quirks-ref.html -== bug1379306-2.html bug1379306-2-ref.html -== bug1379306-3.html bug1379306-3-ref.html +random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) == bug1379306-2.html bug1379306-2-ref.html # Bug 1392106 +random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) == bug1379306-3.html bug1379306-3-ref.html # Bug 1392106 diff --git a/layout/reftests/text-transform/reftest.list b/layout/reftests/text-transform/reftest.list index 7994f056a3d7..e54b0edaefea 100644 --- a/layout/reftests/text-transform/reftest.list +++ b/layout/reftests/text-transform/reftest.list @@ -21,19 +21,19 @@ random-if(winWidget) == small-caps-1.html small-caps-1-ref.html # fails if defau fuzzy-if(cocoaWidget,250,15) == all-upper.html all-upper-ref.html # bug 1140292 fuzzy-if(cocoaWidget,250,15) fuzzy-if(skiaContent,1,1800) == all-lower.html all-lower-ref.html # bug 1140292 fuzzy-if(skiaContent,1,80) == all-title.html all-title-ref.html -== smtp-upper.html smtp-upper-ref.html -== smtp-lower.html smtp-lower-ref.html -== smtp-title.html smtp-title-ref.html -== turkish-casing-1.html turkish-casing-1-ref.html -!= small-caps-turkish-1.html small-caps-turkish-1-notref.html -== greek-uppercase-1a.html greek-uppercase-1-ref.html -== greek-uppercase-1b.html greek-uppercase-1-ref.html -== greek-uppercase-2.html greek-uppercase-2-ref.html -== greek-uppercase-3.html greek-uppercase-3-ref.html -== greek-small-caps-1.html greek-small-caps-1-ref.html -== irish-uppercase-1.html irish-uppercase-1-ref.html -== irish-lowercase-1a.html irish-lowercase-1-ref.html -== irish-lowercase-1b.html irish-lowercase-1-ref.html -== fullwidth-1.html fullwidth-1-ref.html -== fullwidth-2.html fullwidth-2-ref.html -== fullwidth-all.html fullwidth-all-ref.html +random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) == smtp-upper.html smtp-upper-ref.html # Bug 1392106 +random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) == smtp-lower.html smtp-lower-ref.html # Bug 1392106 +random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) == smtp-title.html smtp-title-ref.html # Bug 1392106 +random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) == turkish-casing-1.html turkish-casing-1-ref.html # Bug 1392106 +random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) != small-caps-turkish-1.html small-caps-turkish-1-notref.html # Bug 1392106 +random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) == greek-uppercase-1a.html greek-uppercase-1-ref.html # Bug 1392106 +random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) == greek-uppercase-1b.html greek-uppercase-1-ref.html # Bug 1392106 +random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) == greek-uppercase-2.html greek-uppercase-2-ref.html # Bug 1392106 +random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) == greek-uppercase-3.html greek-uppercase-3-ref.html # Bug 1392106 +random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) == greek-small-caps-1.html greek-small-caps-1-ref.html # Bug 1392106 +random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) == irish-uppercase-1.html irish-uppercase-1-ref.html # Bug 1392106 +random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) == irish-lowercase-1a.html irish-lowercase-1-ref.html # Bug 1392106 +random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) == irish-lowercase-1b.html irish-lowercase-1-ref.html # Bug 1392106 +random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) == fullwidth-1.html fullwidth-1-ref.html # Bug 1392106 +random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) == fullwidth-2.html fullwidth-2-ref.html # Bug 1392106 +random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) == fullwidth-all.html fullwidth-all-ref.html # Bug 1392106 diff --git a/layout/reftests/text/reftest.list b/layout/reftests/text/reftest.list index 4a8992b14e5e..eab91ce4c0b2 100644 --- a/layout/reftests/text/reftest.list +++ b/layout/reftests/text/reftest.list @@ -28,7 +28,7 @@ fails-if(cocoaWidget) == lineheight-metrics-1.html lineheight-metrics-1-ref.html == lineheight-metrics-2a.html lineheight-metrics-2-ref.html == lineheight-metrics-2b.html lineheight-metrics-2-ref.html == lineheight-percentage-1.html lineheight-percentage-1-ref.html -random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) == long-1.html long-ref.html +random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) == long-1.html long-ref.html # Bug 1392106 fuzzy-if(Android,255,325) == pre-line-1.html pre-line-1-ref.html == pre-line-2.html pre-line-2-ref.html == pre-line-3.html pre-line-3-ref.html @@ -150,7 +150,7 @@ random-if(cocoaWidget) random-if(gtkWidget) == zwnj-01.xhtml zwnj-01-ref.xhtml # != zwnj-01.html zwnj-01-notref.html == initial-zwj-1.html initial-zwj-1-ref.html == cgj-01.html cgj-01-ref.html -== 444656.html 444656-ref.html +random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) == 444656.html 444656-ref.html # Bug 1392106 == 449555-1.html 449555-1-ref.html == 467722.html 467722-ref.html fuzzy-if(skiaContent,1,600) == 475092-sub.html 475092-ref.html @@ -347,7 +347,7 @@ pref(layout.css.control-characters.visible,true) != control-chars-04d.html contr # handling of highly negative letter-spacing and intrinsic width == negative-letter-spacing-1.html negative-letter-spacing-1-ref.html -random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) == segment-break-transformation-1.html segment-break-transformation-1-ref.html +random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) == segment-break-transformation-1.html segment-break-transformation-1-ref.html # Bug 1392106 # color glyphs, opacity, and RTL runs - bug 1318539 == color-opacity-rtl-1.html color-opacity-rtl-1-ref.html diff --git a/layout/reftests/w3c-css/failures.list b/layout/reftests/w3c-css/failures.list index 3dddb6275069..55fc52459413 100644 --- a/layout/reftests/w3c-css/failures.list +++ b/layout/reftests/w3c-css/failures.list @@ -82,6 +82,9 @@ fails-if(Android) random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) css-writi fails-if(Android) random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) css-writing-modes/sizing-orthog-vrl-in-htb-015.xht fails-if(Android) random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) css-writing-modes/sizing-orthog-vrl-in-htb-021.xht random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) css-writing-modes/sizing-orthog-prct-htb-in-vlr-0??.xht +random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) css-writing-modes/sizing-orthog-prct-htb-in-vrl-0??.xht +random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) css-writing-modes/sizing-orthog-prct-vlr-in-htb-0??.xht +random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) css-writing-modes/sizing-orthog-prct-vrl-in-htb-0??.xht # Fuzzy fuzzy-if(OSX||winWidget,255,480) css-writing-modes/abs-pos-non-replaced-v??-???.xht @@ -101,7 +104,7 @@ fuzzy-if(OSX||winWidget,62,404) fuzzy-if(webrender&&winWidget,92-92,100-100) fai fuzzy-if(OSX||winWidget,218,621) css-writing-modes/inline-block-alignment-orthogonal-v??-00?.xht fuzzy-if(OSX||winWidget,135,1080) css-writing-modes/inline-block-alignment-slr-009.xht fuzzy-if(OSX||winWidget,112,960) css-writing-modes/inline-block-alignment-srl-008.xht -fuzzy-if(OSX||winWidget,213,1540) css-writing-modes/line-box-direction-???-0??.xht +fuzzy-if(OSX||winWidget,213,1540) random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) css-writing-modes/line-box-direction-???-0??.xht fuzzy-if(OSX||winWidget,110,1200) css-writing-modes/row-progression-???-0??.xht fuzzy-if(OSX||winWidget,110,1200) css-writing-modes/table-column-order-00?.xht fuzzy-if(winWidget,110,1200) fuzzy-if(webrender&&cocoaWidget,1-1,2-2) css-writing-modes/table-column-order-slr-007.xht @@ -329,3 +332,8 @@ skip selectors/selector-required-type-change-002.html skip selectors/selectors-attr-white-space-001.html skip selectors/selectors-empty-001.xml skip selectors/selectors-namespace-001.xml + +# Bug 1392106 +random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) counter-styles-3/system-cyclic.html +random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) counter-styles-3/dependent-builtin.html +random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) counter-styles-3/redefine-attr-mapping.html diff --git a/layout/reftests/w3c-css/received/reftest.list b/layout/reftests/w3c-css/received/reftest.list index 6461c52a7b12..d34d277cb1ba 100644 --- a/layout/reftests/w3c-css/received/reftest.list +++ b/layout/reftests/w3c-css/received/reftest.list @@ -800,43 +800,43 @@ fails == css-writing-modes/inline-table-alignment-002.xht css-writing-modes/inli fails == css-writing-modes/inline-table-alignment-003.xht css-writing-modes/inline-table-alignment-003-ref.xht fails == css-writing-modes/inline-table-alignment-004.xht css-writing-modes/inline-table-alignment-002-ref.xht fails == css-writing-modes/inline-table-alignment-005.xht css-writing-modes/inline-table-alignment-003-ref.xht -fuzzy-if(OSX||winWidget,213,1540) == css-writing-modes/line-box-direction-htb-001.xht css-writing-modes/block-flow-direction-001-ref.xht -fuzzy-if(OSX||winWidget,213,1540) == css-writing-modes/line-box-direction-slr-043.xht css-writing-modes/block-flow-direction-001-ref.xht -fuzzy-if(OSX||winWidget,213,1540) == css-writing-modes/line-box-direction-slr-047.xht css-writing-modes/block-flow-direction-002-ref.xht -fuzzy-if(OSX||winWidget,213,1540) == css-writing-modes/line-box-direction-slr-048.xht css-writing-modes/block-flow-direction-002-ref.xht -fuzzy-if(OSX||winWidget,213,1540) == css-writing-modes/line-box-direction-slr-050.xht css-writing-modes/block-flow-direction-001-ref.xht -fuzzy-if(OSX||winWidget,213,1540) == css-writing-modes/line-box-direction-slr-053.xht css-writing-modes/block-flow-direction-001-ref.xht -fuzzy-if(OSX||winWidget,213,1540) == css-writing-modes/line-box-direction-slr-054.xht css-writing-modes/block-flow-direction-001-ref.xht +fuzzy-if(OSX||winWidget,213,1540) random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) == css-writing-modes/line-box-direction-htb-001.xht css-writing-modes/block-flow-direction-001-ref.xht +fuzzy-if(OSX||winWidget,213,1540) random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) == css-writing-modes/line-box-direction-slr-043.xht css-writing-modes/block-flow-direction-001-ref.xht +fuzzy-if(OSX||winWidget,213,1540) random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) == css-writing-modes/line-box-direction-slr-047.xht css-writing-modes/block-flow-direction-002-ref.xht +fuzzy-if(OSX||winWidget,213,1540) random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) == css-writing-modes/line-box-direction-slr-048.xht css-writing-modes/block-flow-direction-002-ref.xht +fuzzy-if(OSX||winWidget,213,1540) random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) == css-writing-modes/line-box-direction-slr-050.xht css-writing-modes/block-flow-direction-001-ref.xht +fuzzy-if(OSX||winWidget,213,1540) random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) == css-writing-modes/line-box-direction-slr-053.xht css-writing-modes/block-flow-direction-001-ref.xht +fuzzy-if(OSX||winWidget,213,1540) random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) == css-writing-modes/line-box-direction-slr-054.xht css-writing-modes/block-flow-direction-001-ref.xht random == css-writing-modes/line-box-direction-slr-056.xht css-writing-modes/block-flow-direction-001-ref.xht -fuzzy-if(OSX||winWidget,213,1540) == css-writing-modes/line-box-direction-slr-058.xht css-writing-modes/block-flow-direction-001-ref.xht -fuzzy-if(OSX||winWidget,213,1540) == css-writing-modes/line-box-direction-slr-060.xht css-writing-modes/block-flow-direction-001-ref.xht -fuzzy-if(OSX||winWidget,213,1540) == css-writing-modes/line-box-direction-srl-042.xht css-writing-modes/block-flow-direction-001-ref.xht -fuzzy-if(OSX||winWidget,213,1540) == css-writing-modes/line-box-direction-srl-045.xht css-writing-modes/block-flow-direction-001-ref.xht -fuzzy-if(OSX||winWidget,213,1540) == css-writing-modes/line-box-direction-srl-046.xht css-writing-modes/block-flow-direction-001-ref.xht -fuzzy-if(OSX||winWidget,213,1540) == css-writing-modes/line-box-direction-srl-049.xht css-writing-modes/block-flow-direction-001-ref.xht -fuzzy-if(OSX||winWidget,213,1540) == css-writing-modes/line-box-direction-srl-051.xht css-writing-modes/block-flow-direction-001-ref.xht -fuzzy-if(OSX||winWidget,213,1540) == css-writing-modes/line-box-direction-srl-052.xht css-writing-modes/block-flow-direction-001-ref.xht +fuzzy-if(OSX||winWidget,213,1540) random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) == css-writing-modes/line-box-direction-slr-058.xht css-writing-modes/block-flow-direction-001-ref.xht +fuzzy-if(OSX||winWidget,213,1540) random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) == css-writing-modes/line-box-direction-slr-060.xht css-writing-modes/block-flow-direction-001-ref.xht +fuzzy-if(OSX||winWidget,213,1540) random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) == css-writing-modes/line-box-direction-srl-042.xht css-writing-modes/block-flow-direction-001-ref.xht +fuzzy-if(OSX||winWidget,213,1540) random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) == css-writing-modes/line-box-direction-srl-045.xht css-writing-modes/block-flow-direction-001-ref.xht +fuzzy-if(OSX||winWidget,213,1540) random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) == css-writing-modes/line-box-direction-srl-046.xht css-writing-modes/block-flow-direction-001-ref.xht +fuzzy-if(OSX||winWidget,213,1540) random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) == css-writing-modes/line-box-direction-srl-049.xht css-writing-modes/block-flow-direction-001-ref.xht +fuzzy-if(OSX||winWidget,213,1540) random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) == css-writing-modes/line-box-direction-srl-051.xht css-writing-modes/block-flow-direction-001-ref.xht +fuzzy-if(OSX||winWidget,213,1540) random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) == css-writing-modes/line-box-direction-srl-052.xht css-writing-modes/block-flow-direction-001-ref.xht random == css-writing-modes/line-box-direction-srl-055.xht css-writing-modes/block-flow-direction-001-ref.xht -fuzzy-if(OSX||winWidget,213,1540) == css-writing-modes/line-box-direction-srl-057.xht css-writing-modes/block-flow-direction-001-ref.xht -fuzzy-if(OSX||winWidget,213,1540) == css-writing-modes/line-box-direction-srl-059.xht css-writing-modes/block-flow-direction-001-ref.xht -fuzzy-if(OSX||winWidget,213,1540) == css-writing-modes/line-box-direction-vlr-003.xht css-writing-modes/block-flow-direction-001-ref.xht -fuzzy-if(OSX||winWidget,213,1540) == css-writing-modes/line-box-direction-vlr-007.xht css-writing-modes/block-flow-direction-002-ref.xht -fuzzy-if(OSX||winWidget,213,1540) == css-writing-modes/line-box-direction-vlr-008.xht css-writing-modes/block-flow-direction-002-ref.xht -fuzzy-if(OSX||winWidget,213,1540) == css-writing-modes/line-box-direction-vlr-010.xht css-writing-modes/block-flow-direction-001-ref.xht -fuzzy-if(OSX||winWidget,213,1540) == css-writing-modes/line-box-direction-vlr-013.xht css-writing-modes/block-flow-direction-001-ref.xht -fuzzy-if(OSX||winWidget,213,1540) == css-writing-modes/line-box-direction-vlr-014.xht css-writing-modes/block-flow-direction-001-ref.xht +fuzzy-if(OSX||winWidget,213,1540) random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) == css-writing-modes/line-box-direction-srl-057.xht css-writing-modes/block-flow-direction-001-ref.xht +fuzzy-if(OSX||winWidget,213,1540) random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) == css-writing-modes/line-box-direction-srl-059.xht css-writing-modes/block-flow-direction-001-ref.xht +fuzzy-if(OSX||winWidget,213,1540) random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) == css-writing-modes/line-box-direction-vlr-003.xht css-writing-modes/block-flow-direction-001-ref.xht +fuzzy-if(OSX||winWidget,213,1540) random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) == css-writing-modes/line-box-direction-vlr-007.xht css-writing-modes/block-flow-direction-002-ref.xht +fuzzy-if(OSX||winWidget,213,1540) random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) == css-writing-modes/line-box-direction-vlr-008.xht css-writing-modes/block-flow-direction-002-ref.xht +fuzzy-if(OSX||winWidget,213,1540) random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) == css-writing-modes/line-box-direction-vlr-010.xht css-writing-modes/block-flow-direction-001-ref.xht +fuzzy-if(OSX||winWidget,213,1540) random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) == css-writing-modes/line-box-direction-vlr-013.xht css-writing-modes/block-flow-direction-001-ref.xht +fuzzy-if(OSX||winWidget,213,1540) random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) == css-writing-modes/line-box-direction-vlr-014.xht css-writing-modes/block-flow-direction-001-ref.xht random == css-writing-modes/line-box-direction-vlr-016.xht css-writing-modes/block-flow-direction-001-ref.xht -fuzzy-if(OSX||winWidget,213,1540) == css-writing-modes/line-box-direction-vlr-018.xht css-writing-modes/block-flow-direction-001-ref.xht -fuzzy-if(OSX||winWidget,213,1540) == css-writing-modes/line-box-direction-vlr-020.xht css-writing-modes/block-flow-direction-001-ref.xht -fuzzy-if(OSX||winWidget,213,1540) == css-writing-modes/line-box-direction-vrl-002.xht css-writing-modes/block-flow-direction-001-ref.xht -fuzzy-if(OSX||winWidget,213,1540) == css-writing-modes/line-box-direction-vrl-005.xht css-writing-modes/block-flow-direction-001-ref.xht -fuzzy-if(OSX||winWidget,213,1540) == css-writing-modes/line-box-direction-vrl-006.xht css-writing-modes/block-flow-direction-001-ref.xht -fuzzy-if(OSX||winWidget,213,1540) == css-writing-modes/line-box-direction-vrl-009.xht css-writing-modes/block-flow-direction-001-ref.xht -fuzzy-if(OSX||winWidget,213,1540) == css-writing-modes/line-box-direction-vrl-011.xht css-writing-modes/block-flow-direction-001-ref.xht -fuzzy-if(OSX||winWidget,213,1540) == css-writing-modes/line-box-direction-vrl-012.xht css-writing-modes/block-flow-direction-001-ref.xht +fuzzy-if(OSX||winWidget,213,1540) random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) == css-writing-modes/line-box-direction-vlr-018.xht css-writing-modes/block-flow-direction-001-ref.xht +fuzzy-if(OSX||winWidget,213,1540) random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) == css-writing-modes/line-box-direction-vlr-020.xht css-writing-modes/block-flow-direction-001-ref.xht +fuzzy-if(OSX||winWidget,213,1540) random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) == css-writing-modes/line-box-direction-vrl-002.xht css-writing-modes/block-flow-direction-001-ref.xht +fuzzy-if(OSX||winWidget,213,1540) random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) == css-writing-modes/line-box-direction-vrl-005.xht css-writing-modes/block-flow-direction-001-ref.xht +fuzzy-if(OSX||winWidget,213,1540) random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) == css-writing-modes/line-box-direction-vrl-006.xht css-writing-modes/block-flow-direction-001-ref.xht +fuzzy-if(OSX||winWidget,213,1540) random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) == css-writing-modes/line-box-direction-vrl-009.xht css-writing-modes/block-flow-direction-001-ref.xht +fuzzy-if(OSX||winWidget,213,1540) random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) == css-writing-modes/line-box-direction-vrl-011.xht css-writing-modes/block-flow-direction-001-ref.xht +fuzzy-if(OSX||winWidget,213,1540) random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) == css-writing-modes/line-box-direction-vrl-012.xht css-writing-modes/block-flow-direction-001-ref.xht random == css-writing-modes/line-box-direction-vrl-015.xht css-writing-modes/block-flow-direction-001-ref.xht -fuzzy-if(OSX||winWidget,213,1540) == css-writing-modes/line-box-direction-vrl-017.xht css-writing-modes/block-flow-direction-001-ref.xht -fuzzy-if(OSX||winWidget,213,1540) == css-writing-modes/line-box-direction-vrl-019.xht css-writing-modes/block-flow-direction-001-ref.xht +fuzzy-if(OSX||winWidget,213,1540) random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) == css-writing-modes/line-box-direction-vrl-017.xht css-writing-modes/block-flow-direction-001-ref.xht +fuzzy-if(OSX||winWidget,213,1540) random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) == css-writing-modes/line-box-direction-vrl-019.xht css-writing-modes/block-flow-direction-001-ref.xht fails == css-writing-modes/line-box-height-vlr-003.xht css-writing-modes/line-box-height-vlr-003-ref.xht fails == css-writing-modes/line-box-height-vlr-005.xht css-writing-modes/line-box-height-vlr-003-ref.xht == css-writing-modes/line-box-height-vlr-007.xht css-writing-modes/line-box-height-vlr-007-ref.xht @@ -964,30 +964,30 @@ random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) == css-writing-modes/sizing random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) == css-writing-modes/sizing-orthog-prct-htb-in-vlr-006.xht css-writing-modes/sizing-orthog-prct-htb-in-vlr-006-ref.xht random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) == css-writing-modes/sizing-orthog-prct-htb-in-vlr-007.xht css-writing-modes/sizing-orthog-prct-htb-in-vlr-007-ref.xht random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) == css-writing-modes/sizing-orthog-prct-htb-in-vlr-008.xht css-writing-modes/sizing-orthog-prct-htb-in-vlr-008-ref.xht -== css-writing-modes/sizing-orthog-prct-htb-in-vrl-001.xht css-writing-modes/sizing-orthog-prct-htb-in-vrl-001-ref.xht -== css-writing-modes/sizing-orthog-prct-htb-in-vrl-002.xht css-writing-modes/sizing-orthog-prct-htb-in-vrl-002-ref.xht -== css-writing-modes/sizing-orthog-prct-htb-in-vrl-003.xht css-writing-modes/sizing-orthog-prct-htb-in-vrl-003-ref.xht -== css-writing-modes/sizing-orthog-prct-htb-in-vrl-004.xht css-writing-modes/sizing-orthog-prct-htb-in-vrl-004-ref.xht -== css-writing-modes/sizing-orthog-prct-htb-in-vrl-005.xht css-writing-modes/sizing-orthog-prct-htb-in-vrl-005-ref.xht -== css-writing-modes/sizing-orthog-prct-htb-in-vrl-006.xht css-writing-modes/sizing-orthog-prct-htb-in-vrl-006-ref.xht -== css-writing-modes/sizing-orthog-prct-htb-in-vrl-007.xht css-writing-modes/sizing-orthog-prct-htb-in-vrl-007-ref.xht -== css-writing-modes/sizing-orthog-prct-htb-in-vrl-008.xht css-writing-modes/sizing-orthog-prct-htb-in-vrl-008-ref.xht -== css-writing-modes/sizing-orthog-prct-vlr-in-htb-001.xht css-writing-modes/sizing-orthog-prct-vlr-in-htb-001-ref.xht -== css-writing-modes/sizing-orthog-prct-vlr-in-htb-002.xht css-writing-modes/sizing-orthog-prct-vlr-in-htb-002-ref.xht -== css-writing-modes/sizing-orthog-prct-vlr-in-htb-003.xht css-writing-modes/sizing-orthog-prct-vlr-in-htb-003-ref.xht -== css-writing-modes/sizing-orthog-prct-vlr-in-htb-004.xht css-writing-modes/sizing-orthog-prct-vlr-in-htb-004-ref.xht -== css-writing-modes/sizing-orthog-prct-vlr-in-htb-005.xht css-writing-modes/sizing-orthog-prct-vlr-in-htb-005-ref.xht -== css-writing-modes/sizing-orthog-prct-vlr-in-htb-006.xht css-writing-modes/sizing-orthog-prct-vlr-in-htb-006-ref.xht -== css-writing-modes/sizing-orthog-prct-vlr-in-htb-007.xht css-writing-modes/sizing-orthog-prct-vlr-in-htb-007-ref.xht -== css-writing-modes/sizing-orthog-prct-vlr-in-htb-008.xht css-writing-modes/sizing-orthog-prct-vlr-in-htb-008-ref.xht -== css-writing-modes/sizing-orthog-prct-vrl-in-htb-001.xht css-writing-modes/sizing-orthog-prct-vrl-in-htb-001-ref.xht -== css-writing-modes/sizing-orthog-prct-vrl-in-htb-002.xht css-writing-modes/sizing-orthog-prct-vrl-in-htb-002-ref.xht -== css-writing-modes/sizing-orthog-prct-vrl-in-htb-003.xht css-writing-modes/sizing-orthog-prct-vrl-in-htb-003-ref.xht -== css-writing-modes/sizing-orthog-prct-vrl-in-htb-004.xht css-writing-modes/sizing-orthog-prct-vrl-in-htb-004-ref.xht -== css-writing-modes/sizing-orthog-prct-vrl-in-htb-005.xht css-writing-modes/sizing-orthog-prct-vrl-in-htb-005-ref.xht -== css-writing-modes/sizing-orthog-prct-vrl-in-htb-006.xht css-writing-modes/sizing-orthog-prct-vrl-in-htb-006-ref.xht -== css-writing-modes/sizing-orthog-prct-vrl-in-htb-007.xht css-writing-modes/sizing-orthog-prct-vrl-in-htb-007-ref.xht -== css-writing-modes/sizing-orthog-prct-vrl-in-htb-008.xht css-writing-modes/sizing-orthog-prct-vrl-in-htb-008-ref.xht +random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) == css-writing-modes/sizing-orthog-prct-htb-in-vrl-001.xht css-writing-modes/sizing-orthog-prct-htb-in-vrl-001-ref.xht +random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) == css-writing-modes/sizing-orthog-prct-htb-in-vrl-002.xht css-writing-modes/sizing-orthog-prct-htb-in-vrl-002-ref.xht +random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) == css-writing-modes/sizing-orthog-prct-htb-in-vrl-003.xht css-writing-modes/sizing-orthog-prct-htb-in-vrl-003-ref.xht +random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) == css-writing-modes/sizing-orthog-prct-htb-in-vrl-004.xht css-writing-modes/sizing-orthog-prct-htb-in-vrl-004-ref.xht +random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) == css-writing-modes/sizing-orthog-prct-htb-in-vrl-005.xht css-writing-modes/sizing-orthog-prct-htb-in-vrl-005-ref.xht +random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) == css-writing-modes/sizing-orthog-prct-htb-in-vrl-006.xht css-writing-modes/sizing-orthog-prct-htb-in-vrl-006-ref.xht +random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) == css-writing-modes/sizing-orthog-prct-htb-in-vrl-007.xht css-writing-modes/sizing-orthog-prct-htb-in-vrl-007-ref.xht +random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) == css-writing-modes/sizing-orthog-prct-htb-in-vrl-008.xht css-writing-modes/sizing-orthog-prct-htb-in-vrl-008-ref.xht +random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) == css-writing-modes/sizing-orthog-prct-vlr-in-htb-001.xht css-writing-modes/sizing-orthog-prct-vlr-in-htb-001-ref.xht +random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) == css-writing-modes/sizing-orthog-prct-vlr-in-htb-002.xht css-writing-modes/sizing-orthog-prct-vlr-in-htb-002-ref.xht +random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) == css-writing-modes/sizing-orthog-prct-vlr-in-htb-003.xht css-writing-modes/sizing-orthog-prct-vlr-in-htb-003-ref.xht +random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) == css-writing-modes/sizing-orthog-prct-vlr-in-htb-004.xht css-writing-modes/sizing-orthog-prct-vlr-in-htb-004-ref.xht +random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) == css-writing-modes/sizing-orthog-prct-vlr-in-htb-005.xht css-writing-modes/sizing-orthog-prct-vlr-in-htb-005-ref.xht +random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) == css-writing-modes/sizing-orthog-prct-vlr-in-htb-006.xht css-writing-modes/sizing-orthog-prct-vlr-in-htb-006-ref.xht +random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) == css-writing-modes/sizing-orthog-prct-vlr-in-htb-007.xht css-writing-modes/sizing-orthog-prct-vlr-in-htb-007-ref.xht +random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) == css-writing-modes/sizing-orthog-prct-vlr-in-htb-008.xht css-writing-modes/sizing-orthog-prct-vlr-in-htb-008-ref.xht +random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) == css-writing-modes/sizing-orthog-prct-vrl-in-htb-001.xht css-writing-modes/sizing-orthog-prct-vrl-in-htb-001-ref.xht +random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) == css-writing-modes/sizing-orthog-prct-vrl-in-htb-002.xht css-writing-modes/sizing-orthog-prct-vrl-in-htb-002-ref.xht +random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) == css-writing-modes/sizing-orthog-prct-vrl-in-htb-003.xht css-writing-modes/sizing-orthog-prct-vrl-in-htb-003-ref.xht +random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) == css-writing-modes/sizing-orthog-prct-vrl-in-htb-004.xht css-writing-modes/sizing-orthog-prct-vrl-in-htb-004-ref.xht +random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) == css-writing-modes/sizing-orthog-prct-vrl-in-htb-005.xht css-writing-modes/sizing-orthog-prct-vrl-in-htb-005-ref.xht +random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) == css-writing-modes/sizing-orthog-prct-vrl-in-htb-006.xht css-writing-modes/sizing-orthog-prct-vrl-in-htb-006-ref.xht +random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) == css-writing-modes/sizing-orthog-prct-vrl-in-htb-007.xht css-writing-modes/sizing-orthog-prct-vrl-in-htb-007-ref.xht +random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) == css-writing-modes/sizing-orthog-prct-vrl-in-htb-008.xht css-writing-modes/sizing-orthog-prct-vrl-in-htb-008-ref.xht == css-writing-modes/sizing-orthog-vlr-in-htb-001.xht css-writing-modes/sizing-orthog-vlr-in-htb-001-ref.xht fails-if(Android) random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) == css-writing-modes/sizing-orthog-vlr-in-htb-003.xht css-writing-modes/sizing-orthog-vlr-in-htb-003-ref.xht == css-writing-modes/sizing-orthog-vlr-in-htb-004.xht css-writing-modes/sizing-orthog-vlr-in-htb-004-ref.xht diff --git a/layout/reftests/w3c-css/submitted/writing-modes-3/reftest.list b/layout/reftests/w3c-css/submitted/writing-modes-3/reftest.list index be4eea1fabb2..13c2ab636490 100644 --- a/layout/reftests/w3c-css/submitted/writing-modes-3/reftest.list +++ b/layout/reftests/w3c-css/submitted/writing-modes-3/reftest.list @@ -1,14 +1,14 @@ == text-combine-upright-break-inside-001.html text-combine-upright-break-inside-001-ref.html == text-combine-upright-break-inside-001a.html text-combine-upright-break-inside-001-ref.html -== text-combine-upright-compression-001.html text-combine-upright-compression-001-ref.html -== text-combine-upright-compression-002.html text-combine-upright-compression-002-ref.html -== text-combine-upright-compression-003.html text-combine-upright-compression-003-ref.html -== text-combine-upright-compression-004.html text-combine-upright-compression-004-ref.html -== text-combine-upright-compression-005.html text-combine-upright-compression-005-ref.html -== text-combine-upright-compression-005a.html text-combine-upright-compression-005-ref.html -== text-combine-upright-compression-006.html text-combine-upright-compression-006-ref.html -== text-combine-upright-compression-006a.html text-combine-upright-compression-006-ref.html -== text-combine-upright-compression-007.html text-combine-upright-compression-007-ref.html +random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) == text-combine-upright-compression-001.html text-combine-upright-compression-001-ref.html # Bug 1392106 +random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) == text-combine-upright-compression-002.html text-combine-upright-compression-002-ref.html # Bug 1392106 +random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) == text-combine-upright-compression-003.html text-combine-upright-compression-003-ref.html # Bug 1392106 +random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) == text-combine-upright-compression-004.html text-combine-upright-compression-004-ref.html # Bug 1392106 +random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) == text-combine-upright-compression-005.html text-combine-upright-compression-005-ref.html # Bug 1392106 +random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) == text-combine-upright-compression-005a.html text-combine-upright-compression-005-ref.html # Bug 1392106 +random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) == text-combine-upright-compression-006.html text-combine-upright-compression-006-ref.html # Bug 1392106 +random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) == text-combine-upright-compression-006a.html text-combine-upright-compression-006-ref.html # Bug 1392106 +random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) == text-combine-upright-compression-007.html text-combine-upright-compression-007-ref.html # Bug 1392106 == text-orientation-upright-directionality-001.html text-orientation-upright-directionality-001-ref.html diff --git a/layout/reftests/writing-mode/reftest.list b/layout/reftests/writing-mode/reftest.list index 2696f5f9d803..473cd6de33b8 100644 --- a/layout/reftests/writing-mode/reftest.list +++ b/layout/reftests/writing-mode/reftest.list @@ -12,7 +12,7 @@ fuzzy-if(gtkWidget,255,2) fuzzy-if(winWidget||Android,4,8704) == 1083848-3-inlin == 1088025-1.html 1088025-1-ref.html == 1089388-1.html 1089388-1-ref.html == 1089388-2.html 1089388-2-ref.html -== 1090159-1.html 1090159-1-ref.html +random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) == 1090159-1.html 1090159-1-ref.html # Bug 1392106 == 1090168-1.html 1090168-1-ref.html != 1090168-1.html 1090168-1-notref.html == 1090168-2.html 1090168-2-ref.html @@ -31,7 +31,7 @@ fails == 1102175-1a.html 1102175-1-ref.html == 1105268-2-min-max-dimensions.html 1105268-2-min-max-dimensions-ref.html == 1106669-1-intrinsic-for-container.html 1106669-1-intrinsic-for-container-ref.html == 1108923-1-percentage-margins.html 1108923-1-percentage-margins-ref.html -random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) == 1111944-1-list-marker.html 1111944-1-list-marker-ref.html +random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) == 1111944-1-list-marker.html 1111944-1-list-marker-ref.html # Bug 1392106 fuzzy(116,94) fuzzy-if(winWidget,135,124) == 1115916-1-vertical-metrics.html 1115916-1-vertical-metrics-ref.html == 1117210-1-vertical-baseline-snap.html 1117210-1-vertical-baseline-snap-ref.html == 1117227-1-text-overflow.html 1117227-1-text-overflow-ref.html @@ -138,7 +138,7 @@ test-pref(dom.meta-viewport.enabled,true) test-pref(font.size.inflation.emPerLin == 1156021-text-indent-percent.html 1156021-text-indent-percent-ref.html == 1157752-upright-bidi.html 1157752-upright-bidi-ref.html == 1157758-1-vertical-arabic.html 1157758-1-vertical-arabic-ref.html -random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) == 1158549-1-vertical-block-size-constraints.html 1158549-1-vertical-block-size-constraints-ref.html +random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) == 1158549-1-vertical-block-size-constraints.html 1158549-1-vertical-block-size-constraints-ref.html # Bug 1392106 == 1163238-orthogonal-auto-margins.html 1163238-orthogonal-auto-margins-ref.html == 1174450-intrinsic-sizing.html 1174450-intrinsic-sizing-ref.html skip-if(winWidget&&/^Windows\x20NT\x206\.1/.test(http.oscpu)) == 1175789-underline-overline-1.html 1175789-underline-overline-1-ref.html # bug 1442637 diff --git a/layout/reftests/writing-mode/tables/reftest.list b/layout/reftests/writing-mode/tables/reftest.list index d5df1cfa16b4..80b7bfa87903 100644 --- a/layout/reftests/writing-mode/tables/reftest.list +++ b/layout/reftests/writing-mode/tables/reftest.list @@ -92,7 +92,7 @@ fuzzy-if(cocoaWidget,23,162) == border-collapse-bevels-1e.html border-collapse-b == sideways-rl-row-progression-1a.html sideways-rl-row-progression-1-ref.html == sideways-rl-row-progression-1b.html sideways-rl-row-progression-1-ref.html -== 1259168-ref.html 1259168-vrl.html -== 1259168-ref.html 1259168-vlr.html -== 1259168-ref.html 1259168-srl.html -== 1259168-ref.html 1259168-slr.html +random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) == 1259168-ref.html 1259168-vrl.html # Bug 1392106 +random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) == 1259168-ref.html 1259168-vlr.html # Bug 1392106 +random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) == 1259168-ref.html 1259168-srl.html # Bug 1392106 +random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) == 1259168-ref.html 1259168-slr.html # Bug 1392106 diff --git a/mobile/android/components/BrowserCLH.js b/mobile/android/components/BrowserCLH.js index 2a4075579dcc..340480c917dc 100644 --- a/mobile/android/components/BrowserCLH.js +++ b/mobile/android/components/BrowserCLH.js @@ -116,7 +116,7 @@ BrowserCLH.prototype = { case "chrome-document-interactive": case "content-document-interactive": { - let contentWin = subject.QueryInterface(Ci.nsIDOMDocument).defaultView; + let contentWin = subject.defaultView; let win = GeckoViewUtils.getChromeWindow(contentWin); let dispatcher = GeckoViewUtils.getDispatcherForWindow(win); if (!win || !dispatcher || win !== contentWin) { diff --git a/modules/libpref/init/all.js b/modules/libpref/init/all.js index eca77f5f17a0..106a014525e7 100644 --- a/modules/libpref/init/all.js +++ b/modules/libpref/init/all.js @@ -4791,7 +4791,7 @@ pref("layers.enable-tiles", true); #else pref("layers.enable-tiles", false); #endif -#if defined(NIGHTLY_BUILD) && defined(XP_WIN) +#if defined(XP_WIN) pref("layers.enable-tiles-if-skia-pomtp", true); #else pref("layers.enable-tiles-if-skia-pomtp", false); diff --git a/netwerk/protocol/http/HttpChannelChild.cpp b/netwerk/protocol/http/HttpChannelChild.cpp index 39f75eb98e02..187a1d154833 100644 --- a/netwerk/protocol/http/HttpChannelChild.cpp +++ b/netwerk/protocol/http/HttpChannelChild.cpp @@ -2480,6 +2480,13 @@ HttpChannelChild::AsyncOpen(nsIStreamListener *listener, nsISupports *aContext) LOG(("HttpChannelChild::AsyncOpen [this=%p uri=%s]\n", this, mSpec.get())); LogCallingScriptLocation(this); + if (!mLoadGroup && !mCallbacks) { + // If no one called SetLoadGroup or SetNotificationCallbacks, the private + // state has not been updated on PrivateBrowsingChannel (which we derive from) + // Hence, we have to call UpdatePrivateBrowsing() here + UpdatePrivateBrowsing(); + } + #ifdef DEBUG AssertPrivateBrowsingId(); #endif diff --git a/netwerk/protocol/http/nsHttpChannel.cpp b/netwerk/protocol/http/nsHttpChannel.cpp index 5a415b3f2a7d..aa59bcdc54de 100644 --- a/netwerk/protocol/http/nsHttpChannel.cpp +++ b/netwerk/protocol/http/nsHttpChannel.cpp @@ -5962,6 +5962,13 @@ nsHttpChannel::AsyncOpen(nsIStreamListener *listener, nsISupports *context) return rv; } + if (!mLoadGroup && !mCallbacks) { + // If no one called SetLoadGroup or SetNotificationCallbacks, the private + // state has not been updated on PrivateBrowsingChannel (which we derive from) + // Hence, we have to call UpdatePrivateBrowsing() here + UpdatePrivateBrowsing(); + } + if (WaitingForTailUnblock()) { // This channel is marked as Tail and is part of a request context // that has positive number of non-tailed requestst, hence this channel diff --git a/package-lock.json b/package-lock.json index 76eb7960213d..25eb353d45ea 100644 --- a/package-lock.json +++ b/package-lock.json @@ -180,7 +180,7 @@ "circular-json": { "version": "0.3.3", "resolved": "https://registry.npmjs.org/circular-json/-/circular-json-0.3.3.tgz", - "integrity": "sha512-UZK3NBx2Mca+b5LsG7bY183pHWt5Y1xts4P3Pz7ENTwGVnJOUWbRb3ocjvX7hx9tq/yTAdclXm9sZ38gNuem4A==" + "integrity": "sha1-gVyZ6oT2gJUp0vRXkb34JxE1LWY=" }, "cli-cursor": { "version": "2.1.0", @@ -203,7 +203,7 @@ "color-convert": { "version": "1.9.1", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.1.tgz", - "integrity": "sha512-mjGanIiwQJskCC18rPR6OmrZ6fm2Lc7PeGFYwCmy5J34wC6F1PzdGL6xeMfmgicfYcNLGuVFA3WzXtIDCQSZxQ==", + "integrity": "sha1-wSYRB66y8pTr/+ye2eytUppgl+0=", "requires": { "color-name": "1.1.3" } @@ -247,7 +247,7 @@ "debug": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", - "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "integrity": "sha1-W7WgZyYotkFJVmuhaBnmFRjGcmE=", "requires": { "ms": "2.0.0" } @@ -431,7 +431,7 @@ "esprima": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.0.tgz", - "integrity": "sha512-oftTcaMu/EGrEIu904mWteKIv8vMuOgGYo7EhVJJN00R/EED9DCua/xxHRdYnKtcECzVg7xOWhflvJMnqcFZjw==" + "integrity": "sha1-RJnt3NERDgshi6zy+n9/WfVcqAQ=" }, "esquery": { "version": "1.0.1", @@ -520,7 +520,7 @@ "function-bind": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", - "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==" + "integrity": "sha1-pWiZ0+o8m6uHS7l3O3xe3pL0iV0=" }, "functional-red-black-tree": { "version": "1.0.1", @@ -530,7 +530,7 @@ "glob": { "version": "7.1.2", "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz", - "integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==", + "integrity": "sha1-wZyd+aAocC1nhhI4SmVSQExjbRU=", "requires": { "fs.realpath": "1.0.0", "inflight": "1.0.6", @@ -637,7 +637,7 @@ "inquirer": { "version": "3.3.0", "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-3.3.0.tgz", - "integrity": "sha512-h+xtnyk4EwKvFWHrUYsWErEVR+igKtLdchu+o0Z1RL7VU/jVMFbYir2bp6bAj8efFNxWqHX0dIss6fJQ+/+qeQ==", + "integrity": "sha1-ndLyrXZdyrH/BEO0kUQqILoifck=", "requires": { "ansi-escapes": "3.1.0", "chalk": "2.4.1", @@ -761,7 +761,7 @@ "minimatch": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", - "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "integrity": "sha1-UWbihkV/AzBgZL5Ul+jbsMPTIIM=", "requires": { "brace-expansion": "1.1.11" } @@ -864,7 +864,7 @@ "pluralize": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/pluralize/-/pluralize-7.0.0.tgz", - "integrity": "sha512-ARhBOdzS3e41FbkW/XWrTEtukqqLoK5+Z/4UeDaLuSW+39JPeFgs4gCGqsrJHVZX0fUrx//4OF0K1CUGwlIFow==" + "integrity": "sha1-KYuJ34uTsCIdv0Ia0rGx6iP8Z3c=" }, "prelude-ls": { "version": "1.1.2", @@ -931,7 +931,7 @@ "rimraf": { "version": "2.6.2", "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.2.tgz", - "integrity": "sha512-lreewLK/BlghmxtfH36YYVg1i8IAce4TI7oao75I1g245+6BctqTVQiBP3YUJ9C6DQOXJmkYR9X9fCLtCOJc5w==", + "integrity": "sha1-LtgVDSShbqhlHm1u8PR8QVjOejY=", "requires": { "glob": "7.1.2" } @@ -998,7 +998,7 @@ "slice-ansi": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-1.0.0.tgz", - "integrity": "sha512-POqxBK6Lb3q6s047D/XsDVNPnF9Dl8JSaqe9h9lURl0OdNqy/ujDrOiIHtsqXMGbWWTIomRzAMaTyawAU//Reg==", + "integrity": "sha1-BE8aSdiEL/MHqta1Be0Xi9lQE00=", "requires": { "is-fullwidth-code-point": "2.0.0" } @@ -1011,7 +1011,7 @@ "string-width": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", - "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", + "integrity": "sha1-q5Pyeo3BPSjKyBXEYhQ6bZASrp4=", "requires": { "is-fullwidth-code-point": "2.0.0", "strip-ansi": "4.0.0" @@ -1053,7 +1053,7 @@ "table": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/table/-/table-4.0.2.tgz", - "integrity": "sha512-UUkEAPdSGxtRpiV9ozJ5cMTtYiqz7Ni1OGqLXRCynrvzdtR1p+cfOWe2RJLwvUG8hNanaSRjecIqwOjqeatDsA==", + "integrity": "sha1-ozRHN1OR52atNNNIbm4q7chNLjY=", "requires": { "ajv": "5.5.2", "ajv-keywords": "2.1.1", @@ -1076,7 +1076,7 @@ "tmp": { "version": "0.0.33", "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz", - "integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==", + "integrity": "sha1-bTQzWIl2jSGyvNoKonfO07G/rfk=", "requires": { "os-tmpdir": "1.0.2" } @@ -1102,7 +1102,7 @@ "which": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/which/-/which-1.3.0.tgz", - "integrity": "sha512-xcJpopdamTuY5duC/KnTTNBraPK54YwpenP4lzxU8H91GudWpFv38u0CKjclE1Wi2EH2EDz5LRcHcKbCIzqGyg==", + "integrity": "sha1-/wS9/AEO5UfXgL7DjhrBwnd9JTo=", "requires": { "isexe": "2.0.0" } diff --git a/parser/htmlparser/tests/reftest/reftest.list b/parser/htmlparser/tests/reftest/reftest.list index e59eda6ca3fc..d2146060f772 100644 --- a/parser/htmlparser/tests/reftest/reftest.list +++ b/parser/htmlparser/tests/reftest/reftest.list @@ -1,5 +1,5 @@ -random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) == bug535530-1.html bug535530-1-ref.html -random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) == view-source:bug535530-2.html bug535530-2-ref.html +random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) == bug535530-1.html bug535530-1-ref.html # Bug 1392106 +random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) == view-source:bug535530-2.html bug535530-2-ref.html # Bug 1392106 == bug566280-1.html bug566280-1-ref.html == bug569229-1.xml bug569229-1-ref.xml == bug577418-1.html bug577418-1-ref.html @@ -10,12 +10,12 @@ fuzzy-if(skiaContent,1,5) == bug599320-1.html bug599320-1-ref.html fuzzy-if(skiaContent,2,5) == bug608373-1.html bug608373-1-ref.html fuzzy-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)&&!layersGPUAccelerated&&!azureSkia,73,1) == view-source:bug482921-1.html bug482921-1-ref.html == view-source:bug482921-2.xhtml bug482921-2-ref.html -fuzzy-if(skiaContent,2,5) == bug659763-1.html bug659763-1-ref.html -fuzzy-if(skiaContent,1,5) == bug659763-2.html bug659763-2-ref.html -fuzzy-if(skiaContent,1,5) == bug659763-3.html bug659763-3-ref.html -fuzzy-if(skiaContent,2,3) == bug659763-4.html bug659763-4-ref.html -fuzzy-if(skiaContent,1,5) == bug659763-5.html bug659763-5-ref.html -fuzzy-if(skiaContent,1,5) == bug659763-6.html bug659763-6-ref.html +fuzzy-if(skiaContent,2,5) random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) == bug659763-1.html bug659763-1-ref.html # Bug 1392106 +fuzzy-if(skiaContent,1,5) random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) == bug659763-2.html bug659763-2-ref.html # Bug 1392106 +fuzzy-if(skiaContent,1,5) random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) == bug659763-3.html bug659763-3-ref.html # Bug 1392106 +fuzzy-if(skiaContent,2,3) random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) == bug659763-4.html bug659763-4-ref.html # Bug 1392106 +fuzzy-if(skiaContent,1,5) random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) == bug659763-5.html bug659763-5-ref.html # Bug 1392106 +fuzzy-if(skiaContent,1,5) random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) == bug659763-6.html bug659763-6-ref.html # Bug 1392106 == view-source:bug673094-1.html view-source:bug673094-1-ref.html == bug696651-1.html bug696651-1-ref.html == bug696651-2.html bug696651-2-ref.html diff --git a/servo/.cargo/config b/servo/.cargo/config deleted file mode 100644 index 9b0e47abcd45..000000000000 --- a/servo/.cargo/config +++ /dev/null @@ -1,22 +0,0 @@ -[target.arm-linux-androideabi] -linker = "./ports/servo/fake-ld-arm.sh" -ar = "arm-linux-androideabi-ar" - -[target.armv7-linux-androideabi] -linker = "./ports/servo/fake-ld-armv7.sh" -ar = "arm-linux-androideabi-ar" - -[target.aarch64-linux-android] -linker = "./ports/servo/fake-ld-arm64.sh" -ar = "aarch64-linux-android-ar" - -[target.arm-unknown-linux-gnueabihf] -linker = "arm-linux-gnueabihf-gcc" -ar = "arm-linux-gnueabihf-ar" - -[target.aarch64-unknown-linux-gnu] -linker = "aarch64-linux-gnu-gcc" -ar = "aarch64-linux-gnu-ar" - -[target.'cfg(target_os=windows)'] -linker = "./ports/servo/fake-ld.cmd" \ No newline at end of file diff --git a/servo/.gitattributes b/servo/.gitattributes deleted file mode 100644 index 3ff2dd9c7b3c..000000000000 --- a/servo/.gitattributes +++ /dev/null @@ -1 +0,0 @@ -tests/* linguist-vendored diff --git a/servo/.gitignore b/servo/.gitignore deleted file mode 100644 index 35b7815ab7e3..000000000000 --- a/servo/.gitignore +++ /dev/null @@ -1,41 +0,0 @@ -/.servo -/.cargo/* -!/.cargo/config.* -/.servobuild -/target -/ports/android/bin -/ports/android/libs -/ports/android/local.properties -/ports/android/obj -/python/_virtualenv -/python/tidy/servo_tidy.egg-info -/tests/wpt/sync -*~ -*.pkl -*.pyc -*.swp -*.swo -*.csv -*.rej -*.orig -.DS_Store -Servo.app -.config.mk.last -/glfw -capture_webrender/ - -# Editors - -# IntelliJ -.idea -*.iws -*.iml - -#Gradle -.gradle - -# VSCode -.vscode - -/unminified-js - diff --git a/servo/.hgignore b/servo/.hgignore deleted file mode 100644 index 32cd546b4a59..000000000000 --- a/servo/.hgignore +++ /dev/null @@ -1,30 +0,0 @@ -^\.servo -^\.cargo -^\.servobuild -^target/ -^ports/android/bin -^ports/android/libs -^ports/android/local.properties -^ports/android/obj -^python/_virtualenv -^python/tidy/servo_tidy\.egg-info -~$ -\.pkl$ -\.pyc$ -\.swp$ -\.swo$ -\.csv$ - -\.DS_Store$ -Servo\.app/ -\.config\.mk\.last$ -/glfw - -# Editors - -# IntelliJ -\.idea -\.iws$ - -# VSCode -\.vscode diff --git a/servo/.mailmap b/servo/.mailmap deleted file mode 100644 index ead257b2c87d..000000000000 --- a/servo/.mailmap +++ /dev/null @@ -1,94 +0,0 @@ -Achal Shah -Adenilson Cavalcanti -Adenilson Cavalcanti -Adrian Heine -Agoston Szepessy -Alexander Popiak -Alexandrov Sergey -Antonio de Luna -Askeing Yen (fyen) -Attila Dusnoki -bd339 -Beomjin Kim -Bogdan Cuza -bors-servo -bors-servo -Brian Anderson -Brian J. Burg -Clark Gaebel -Clark Gaebel -Connor Brewster -Daniel Robertson -Daniel Robertson -David Raifaizen David Raifaizen -Dirkjan Ochtman -edunham -Emilio Cobos Álvarez -Emilio Cobos Álvarez -Felipe Lacerda -Glenn Watson -Glenn Watson -Gregory Terzian -Guillaume Gomez -hgentry -Hugo Thiessard -HyunJune Kim -Ilyong Cho -Jacob Parker -James Graham -Jansen Jan -Jason Williams -Jason Williams -Jason Williams -Jinwoo Ahn -JJ Weber -Junyoung Cho -Junyoung Cho -Kamil Muszyński -Keegan McAllister -Kuba Birecki -Lars Bergstrom -Lars Bergstrom -Luqman Aden -Manish Goregaokar -Margaret Meyerhofer -Martin Robinson -Mike Blumenkrantz -Mike Blumenkrantz -Mike Blumenkrantz -Ms2ger -Nicholas Nethercote -Nicolas -patrick kim -Patrick Trottier -Per Lundberg -Pierre Louis Aublin -Prabhjyot Singh Sodhi -Ravi Shankar -Rohan Prinja -Rohan Prinja -Rohit Zambre -Rohit Zambre -Roman Klauke -rwakulszowa -rwakulszowa -Seth Fowler -Shing Lyu -Stephen (Ziyun) Li -Tamir Duberstein -Tetsuharu OHZEKI -Thiago Pontes -Thiago Pontes -Tim Kuehn -Tim Kuehn -Valentin Fokin -Valentin Fokin -Valentin Fokin -Xidorn Quan -Ying-Ruei Liang (KK) -Yongjin Kim -Yongjin Kim -Young-il Choi -Youngmin Yoo -Zakor Gyula -Zakor Gyula diff --git a/servo/.taskcluster.yml b/servo/.taskcluster.yml deleted file mode 100644 index 2a58201812ac..000000000000 --- a/servo/.taskcluster.yml +++ /dev/null @@ -1,37 +0,0 @@ -version: 0 -metadata: - name: servo - description: >- - A modern, high-performance browser engine designed for both application - and embedded use. - owner: '{{ event.head.user.email }}' - source: '{{ event.head.repo.url }}' -tasks: - - provisionerId: '{{ taskcluster.docker.provisionerId }}' - workerType: '{{ taskcluster.docker.workerType }}' - extra: - github: - events: - - pull_request.opened - - pull_request.reopened - - pull_request.synchronize - payload: - maxRunTime: 3600 - image: 'servobrowser/servo-linux-dev:servo-linux-build-deps-2017-06-30' - command: - - /bin/bash - - '--login' - - '-c' - - '-x' - - >- - git clone {{event.head.repo.url}} servo && - cd servo && - git config advice.detachedHead false && - git checkout {{event.head.sha}} && - etc/ci/taskcluster-test.sh - metadata: - name: linux-tests - description: Run Linux tests. - owner: '{{ event.head.user.email }}' - source: '{{ event.head.repo.url }}' -allowPullRequests: public diff --git a/servo/.travis.yml b/servo/.travis.yml deleted file mode 100644 index 0f19ada7e32a..000000000000 --- a/servo/.travis.yml +++ /dev/null @@ -1,59 +0,0 @@ -language: python - -matrix: - fast_finish: true - include: - - sudo: false - script: - - ./mach test-tidy --no-progress --all - - ./mach test-tidy --no-progress --self-test - - python ./etc/memory_reports_over_time.py --test - - bash etc/ci/check_no_panic.sh - - bash etc/ci/manifest_changed.sh - cache: false - - sudo: 9000 - dist: trusty - before_install: - - sudo add-apt-repository ppa:ubuntu-toolchain-r/test -y - - sudo add-apt-repository 'deb http://apt.llvm.org/precise/ llvm-toolchain-precise-3.9 main' -y - - sudo apt-get update -q - - sudo apt-get install clang-3.9 llvm-3.9 llvm-3.9-runtime -y - - export LLVM_CONFIG=/usr/lib/llvm-3.9/bin/llvm-config - - curl https://sh.rustup.rs -sSf | sh -s -- --default-toolchain none -y - - source ~/.profile - script: - - ./mach build -d --verbose - - ./mach test-unit - - ./mach clean - - ./mach build-geckolib - - ./mach test-stylo - - bash etc/ci/lockfile_changed.sh - cache: - directories: - - .servo - - $HOME/.cargo - - $HOME/.rustup - - $HOME/.ccache - before_cache: - - ./mach clean-nightlies --keep 2 --force - - ./mach clean-cargo-cache --keep 2 --force - env: - CCACHE=/usr/bin/ccache - RUSTFLAGS=-Dwarnings - CARGO_INCREMENTAL=0 - addons: - apt: - packages: - - cmake - - gperf - - libosmesa6-dev - - libgles2-mesa-dev - - python-virtualenv - - xorg-dev - - ccache - - libdbus-glib-1-dev - - libedit-dev - -branches: - only: - - master diff --git a/servo/CLOBBER b/servo/CLOBBER deleted file mode 100644 index bd5a74d5625b..000000000000 --- a/servo/CLOBBER +++ /dev/null @@ -1,8 +0,0 @@ -# To trigger a clobber replace ALL of the textual description below, -# giving a pull request number and a one line description of why a clobber is -# required. -# -# Modifying this file will now automatically clobber the buildbot machines \o/ -# - -Pull 16722 - Added CLOBBER file diff --git a/servo/CONTRIBUTING.md b/servo/CONTRIBUTING.md deleted file mode 100644 index bc3240c7d1a0..000000000000 --- a/servo/CONTRIBUTING.md +++ /dev/null @@ -1,56 +0,0 @@ -# Contributing to Servo - -Servo welcomes contribution from everyone. Here are the guidelines if you are -thinking of helping us: - - -## Contributions - -Contributions to Servo or its dependencies should be made in the form of GitHub -pull requests. Each pull request will be reviewed by a core contributor -(someone with permission to land patches) and either landed in the main tree or -given feedback for changes that would be required. All contributions should -follow this format, even those from core contributors. - -Should you wish to work on an issue, please claim it first by commenting on -the GitHub issue that you want to work on it. This is to prevent duplicated -efforts from contributors on the same issue. - -Head over to [Servo Starters](http://servo.github.io/servo-starters/) to find -good tasks to start with. If you come across words or jargon that do not make -sense, please check [the glossary](docs/glossary.md) first. If there's no -matching entry, please make a pull request to add one with the content `TODO` -so we can correct that! - -See [`HACKING_QUICKSTART.md`](docs/HACKING_QUICKSTART.md) for more information -on how to start working on Servo. - -## Pull Request Checklist - -- Branch from the master branch and, if needed, rebase to the current master - branch before submitting your pull request. If it doesn't merge cleanly with - master you may be asked to rebase your changes. - -- Commits should be as small as possible, while ensuring that each commit is - correct independently (i.e., each commit should compile and pass tests). - -- If your patch is not getting reviewed or you need a specific person to review - it, you can @-reply a reviewer asking for a review in the pull request or a - comment, or you can ask for a review in `#servo` on `irc.mozilla.org`. - -- Add tests relevant to the fixed bug or new feature. For a DOM change this - will usually be a web platform test; for layout, a reftest. See our [testing - guide](https://github.com/servo/servo/wiki/Testing) for more information. - -For specific git instructions, see [GitHub workflow 101](https://github.com/servo/servo/wiki/Github-workflow). - -## Conduct - -In all Servo-related forums, we follow the [Rust Code of Conduct](http://www.rust-lang.org/conduct.html). For escalation or moderation issues, please contact Jack (jmoffitt@mozilla.com) and Lars (larsberg@mozilla.com) instead of the Rust moderation team. - - -## Communication - -Servo contributors frequent the `#servo` channel on [`irc.mozilla.org`](https://wiki.mozilla.org/IRC). - -You can also join the [`dev-servo` mailing list](https://lists.mozilla.org/listinfo/dev-servo). diff --git a/servo/Cargo.lock b/servo/Cargo.lock deleted file mode 100644 index 6bfb874a24fc..000000000000 --- a/servo/Cargo.lock +++ /dev/null @@ -1,4096 +0,0 @@ -[[package]] -name = "adler32" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "aho-corasick" -version = "0.6.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "memchr 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "alloc-no-stdlib" -version = "1.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "android_glue" -version = "0.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "android_injected_glue" -version = "0.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "ansi_term" -version = "0.10.2" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "antidote" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "app_units" -version = "0.6.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "num-traits 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "arrayvec" -version = "0.4.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "nodrop 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "atomic_refcell" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "atty" -version = "0.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.39 (registry+https://github.com/rust-lang/crates.io-index)", - "termion 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "audio-video-metadata" -version = "0.1.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "mp3-metadata 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "mp4parse 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)", - "ogg_metadata 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "azure" -version = "0.28.0" -source = "git+https://github.com/servo/rust-azure#29f0c063ad366b5364e06af26d3e9d1ee588e3b2" -dependencies = [ - "cmake 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", - "euclid 0.17.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.39 (registry+https://github.com/rust-lang/crates.io-index)", - "servo-freetype-sys 4.0.3 (registry+https://github.com/rust-lang/crates.io-index)", - "servo-skia 0.30000013.1 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "backtrace" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "backtrace-sys 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)", - "cfg-if 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "dbghelp-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.39 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-demangle 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "backtrace-sys" -version = "0.1.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "cc 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.39 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "base64" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "byteorder 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "safemem 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "binary-space-partition" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "bincode" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "byteorder 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "bindgen" -version = "0.33.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "cexpr 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "cfg-if 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "clang-sys 0.22.0 (registry+https://github.com/rust-lang/crates.io-index)", - "clap 2.28.0 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "peeking_take_while 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)", - "regex 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "which 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "bitflags" -version = "0.9.1" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "bitflags" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "bitreader" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "block" -version = "0.1.6" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "bluetooth" -version = "0.0.1" -dependencies = [ - "bitflags 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "bluetooth_traits 0.0.1", - "device 0.0.1 (git+https://github.com/servo/devices)", - "ipc-channel 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)", - "servo_config 0.0.1", - "servo_rand 0.0.1", - "tinyfiledialogs 3.3.5 (registry+https://github.com/rust-lang/crates.io-index)", - "uuid 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "bluetooth_traits" -version = "0.0.1" -dependencies = [ - "ipc-channel 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)", - "regex 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)", - "servo_config 0.0.1", -] - -[[package]] -name = "blurdroid" -version = "0.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "blurmac" -version = "0.1.0" -source = "git+https://github.com/servo/devices#eeb6eaddb79c019bb5c85558b3410b836da57a57" -dependencies = [ - "log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", - "objc 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "blurmock" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "blurz" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "dbus 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "brotli" -version = "1.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "alloc-no-stdlib 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "brotli-decompressor 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "brotli-decompressor" -version = "1.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "alloc-no-stdlib 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "byteorder" -version = "1.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "bytes" -version = "0.4.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "byteorder 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "iovec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "canvas" -version = "0.0.1" -dependencies = [ - "azure 0.28.0 (git+https://github.com/servo/rust-azure)", - "canvas_traits 0.0.1", - "compositing 0.0.1", - "cssparser 0.23.2 (registry+https://github.com/rust-lang/crates.io-index)", - "euclid 0.17.2 (registry+https://github.com/rust-lang/crates.io-index)", - "fnv 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", - "gleam 0.4.29 (registry+https://github.com/rust-lang/crates.io-index)", - "ipc-channel 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", - "num-traits 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)", - "offscreen_gl_context 0.15.1 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_bytes 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)", - "servo_config 0.0.1", - "webrender 0.57.0 (git+https://github.com/servo/webrender)", - "webrender_api 0.57.0 (git+https://github.com/servo/webrender)", -] - -[[package]] -name = "canvas_traits" -version = "0.0.1" -dependencies = [ - "cssparser 0.23.2 (registry+https://github.com/rust-lang/crates.io-index)", - "euclid 0.17.2 (registry+https://github.com/rust-lang/crates.io-index)", - "ipc-channel 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "malloc_size_of 0.0.1", - "malloc_size_of_derive 0.0.1", - "nonzero 0.0.1", - "offscreen_gl_context 0.15.1 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_bytes 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)", - "servo_config 0.0.1", - "webrender_api 0.57.0 (git+https://github.com/servo/webrender)", -] - -[[package]] -name = "caseless" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "regex 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "unicode-normalization 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "cc" -version = "1.0.5" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "cexpr" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "nom 1.2.4 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "cfg-if" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "cgl" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "gleam 0.4.29 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.39 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "chrono" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "num 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)", - "time 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "clang-sys" -version = "0.22.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "glob 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.39 (registry+https://github.com/rust-lang/crates.io-index)", - "libloading 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "clap" -version = "2.28.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "ansi_term 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)", - "atty 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", - "bitflags 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "strsim 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", - "textwrap 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", - "unicode-width 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", - "vec_map 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "clipboard" -version = "0.4.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "clipboard-win 2.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "objc 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "objc-foundation 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "objc_id 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "x11-clipboard 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "clipboard-win" -version = "2.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "winapi 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "cmake" -version = "0.1.29" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "cc 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "cocoa" -version = "0.14.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "bitflags 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "block 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "core-graphics 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.39 (registry+https://github.com/rust-lang/crates.io-index)", - "objc 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "color_quant" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "compositing" -version = "0.0.1" -dependencies = [ - "euclid 0.17.2 (registry+https://github.com/rust-lang/crates.io-index)", - "gfx_traits 0.0.1", - "gleam 0.4.29 (registry+https://github.com/rust-lang/crates.io-index)", - "image 0.18.0 (registry+https://github.com/rust-lang/crates.io-index)", - "ipc-channel 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.39 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", - "msg 0.0.1", - "net_traits 0.0.1", - "nonzero 0.0.1", - "profile_traits 0.0.1", - "script_traits 0.0.1", - "servo_config 0.0.1", - "servo_geometry 0.0.1", - "servo_url 0.0.1", - "style_traits 0.0.1", - "time 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)", - "toml 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", - "webrender 0.57.0 (git+https://github.com/servo/webrender)", - "webrender_api 0.57.0 (git+https://github.com/servo/webrender)", -] - -[[package]] -name = "constellation" -version = "0.0.1" -dependencies = [ - "backtrace 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", - "bluetooth_traits 0.0.1", - "canvas 0.0.1", - "canvas_traits 0.0.1", - "clipboard 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "compositing 0.0.1", - "debugger 0.0.1", - "devtools_traits 0.0.1", - "euclid 0.17.2 (registry+https://github.com/rust-lang/crates.io-index)", - "gaol 0.0.1 (git+https://github.com/servo/gaol)", - "gfx 0.0.1", - "gfx_traits 0.0.1", - "hyper 0.10.13 (registry+https://github.com/rust-lang/crates.io-index)", - "ipc-channel 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)", - "layout_traits 0.0.1", - "log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", - "metrics 0.0.1", - "msg 0.0.1", - "net 0.0.1", - "net_traits 0.0.1", - "profile_traits 0.0.1", - "script_traits 0.0.1", - "serde 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)", - "servo_config 0.0.1", - "servo_rand 0.0.1", - "servo_remutex 0.0.1", - "servo_url 0.0.1", - "style_traits 0.0.1", - "webrender_api 0.57.0 (git+https://github.com/servo/webrender)", - "webvr_traits 0.0.1", -] - -[[package]] -name = "cookie" -version = "0.10.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "time 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "core-foundation" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "core-foundation-sys 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.39 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "core-foundation-sys" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "libc 0.2.39 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "core-graphics" -version = "0.13.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "bitflags 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "core-foundation 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", - "foreign-types 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.39 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "core-text" -version = "9.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "core-foundation 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", - "core-graphics 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)", - "foreign-types 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.39 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "crossbeam-deque" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "crossbeam-epoch 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "crossbeam-utils 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "crossbeam-epoch" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "arrayvec 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "cfg-if 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "crossbeam-utils 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "memoffset 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "nodrop 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", - "scopeguard 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "crossbeam-utils" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "cfg-if 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "cssparser" -version = "0.23.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "cssparser-macros 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "dtoa-short 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "itoa 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "matches 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", - "phf 0.7.21 (registry+https://github.com/rust-lang/crates.io-index)", - "procedural-masquerade 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)", - "smallvec 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.11.11 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "cssparser-macros" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "phf_codegen 0.7.21 (registry+https://github.com/rust-lang/crates.io-index)", - "procedural-masquerade 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.11.11 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "cstr" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "cstr-macros 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "procedural-masquerade 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "cstr-macros" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "procedural-masquerade 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.12.12 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "darling" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "darling_core 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "darling_macro 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "darling_core" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "ident_case 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.12.12 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "darling_macro" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "darling_core 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.12.12 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "dbghelp-sys" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "dbus" -version = "0.5.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "libc 0.2.39 (registry+https://github.com/rust-lang/crates.io-index)", - "libdbus-sys 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "debug_unreachable" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "unreachable 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "debugger" -version = "0.0.1" -dependencies = [ - "log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", - "ws 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "deflate" -version = "0.7.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "adler32 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "byteorder 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "deny_public_fields" -version = "0.0.1" -dependencies = [ - "syn 0.12.12 (registry+https://github.com/rust-lang/crates.io-index)", - "synstructure 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "deny_public_fields_tests" -version = "0.0.1" -dependencies = [ - "deny_public_fields 0.0.1", -] - -[[package]] -name = "device" -version = "0.0.1" -source = "git+https://github.com/servo/devices#eeb6eaddb79c019bb5c85558b3410b836da57a57" -dependencies = [ - "blurdroid 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", - "blurmac 0.1.0 (git+https://github.com/servo/devices)", - "blurmock 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "blurz 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "devtools" -version = "0.0.1" -dependencies = [ - "devtools_traits 0.0.1", - "hyper 0.10.13 (registry+https://github.com/rust-lang/crates.io-index)", - "hyper_serde 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", - "ipc-channel 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", - "msg 0.0.1", - "serde 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "time 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "devtools_traits" -version = "0.0.1" -dependencies = [ - "bitflags 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "hyper 0.10.13 (registry+https://github.com/rust-lang/crates.io-index)", - "hyper_serde 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", - "ipc-channel 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)", - "malloc_size_of 0.0.1", - "malloc_size_of_derive 0.0.1", - "msg 0.0.1", - "serde 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)", - "servo_url 0.0.1", - "time 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "dlib" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "libloading 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "dom_struct" -version = "0.0.1" - -[[package]] -name = "domobject_derive" -version = "0.0.1" -dependencies = [ - "quote 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.12.12 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "dtoa" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "dtoa-short" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "dtoa 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "dwrote" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "gdi32-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.39 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "either" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "encoding_rs" -version = "0.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "cfg-if 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "energy-monitor" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "energymon" -version = "0.3.0" -source = "git+https://github.com/energymon/energymon-rust.git#89daf8f37858eab96ad8eec7cc81accb17b2411e" -dependencies = [ - "energy-monitor 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "energymon-default-sys 0.3.0 (git+https://github.com/energymon/energymon-sys.git)", - "libc 0.2.39 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "energymon-builder" -version = "0.3.0" -source = "git+https://github.com/energymon/energymon-sys.git#f8d77ea2906b25f9c0fd358aa9d300a46dc3e97c" -dependencies = [ - "cmake 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", - "pkg-config 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "energymon-default-sys" -version = "0.3.0" -source = "git+https://github.com/energymon/energymon-sys.git#f8d77ea2906b25f9c0fd358aa9d300a46dc3e97c" -dependencies = [ - "energymon-builder 0.3.0 (git+https://github.com/energymon/energymon-sys.git)", - "energymon-sys 0.3.0 (git+https://github.com/energymon/energymon-sys.git)", - "libc 0.2.39 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "energymon-sys" -version = "0.3.0" -source = "git+https://github.com/energymon/energymon-sys.git#f8d77ea2906b25f9c0fd358aa9d300a46dc3e97c" -dependencies = [ - "libc 0.2.39 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "enum_primitive" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "num-traits 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "env_logger" -version = "0.5.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "atty 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", - "humantime 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", - "regex 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "termcolor 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "error-chain" -version = "0.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "backtrace 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "euclid" -version = "0.17.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "num-traits 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "expat-sys" -version = "2.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "cmake 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", - "pkg-config 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "fallible" -version = "0.0.1" -dependencies = [ - "hashglobe 0.1.0", - "smallvec 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "flate2" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "libc 0.2.39 (registry+https://github.com/rust-lang/crates.io-index)", - "miniz-sys 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "fnv" -version = "1.0.5" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "fontsan" -version = "0.4.0" -source = "git+https://github.com/servo/fontsan#29e879c870348c4b3fd51086e42dbb6365171479" -dependencies = [ - "cmake 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.39 (registry+https://github.com/rust-lang/crates.io-index)", - "miniz-sys 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "foreign-types" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "foreign-types-shared 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "foreign-types-shared" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "freetype" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "libc 0.2.39 (registry+https://github.com/rust-lang/crates.io-index)", - "servo-freetype-sys 4.0.3 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "fuchsia-zircon" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "bitflags 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "fuchsia-zircon-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "fuchsia-zircon-sys" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "futf" -version = "0.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "debug_unreachable 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "mac 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "fxhash" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "byteorder 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "gaol" -version = "0.0.1" -source = "git+https://github.com/servo/gaol#227ff0bae1eb1b44a273c6c5610debfe214991ee" -dependencies = [ - "libc 0.2.39 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.3.22 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "gdi32-sys" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "geckoservo" -version = "0.0.1" -dependencies = [ - "atomic_refcell 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "cssparser 0.23.2 (registry+https://github.com/rust-lang/crates.io-index)", - "cstr 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "env_logger 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.39 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", - "malloc_size_of 0.0.1", - "nsstring 0.1.0", - "parking_lot 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)", - "selectors 0.19.0", - "servo_arc 0.1.1", - "smallvec 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", - "style 0.0.1", - "style_traits 0.0.1", -] - -[[package]] -name = "getopts" -version = "0.2.14" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "gfx" -version = "0.0.1" -dependencies = [ - "app_units 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", - "bitflags 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "byteorder 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "core-foundation 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", - "core-graphics 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)", - "core-text 9.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "dwrote 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", - "euclid 0.17.2 (registry+https://github.com/rust-lang/crates.io-index)", - "fnv 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", - "fontsan 0.4.0 (git+https://github.com/servo/fontsan)", - "freetype 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "gfx_traits 0.0.1", - "harfbuzz-sys 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)", - "ipc-channel 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.39 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", - "malloc_size_of 0.0.1", - "malloc_size_of_derive 0.0.1", - "msg 0.0.1", - "net_traits 0.0.1", - "ordered-float 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "range 0.0.1", - "serde 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)", - "servo-fontconfig 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "servo_allocator 0.0.1", - "servo_arc 0.1.1", - "servo_atoms 0.0.1", - "servo_geometry 0.0.1", - "servo_url 0.0.1", - "simd 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "smallvec 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", - "style 0.0.1", - "time 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)", - "truetype 0.26.0 (registry+https://github.com/rust-lang/crates.io-index)", - "unicode-bidi 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", - "unicode-script 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "webrender_api 0.57.0 (git+https://github.com/servo/webrender)", - "xi-unicode 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "xml5ever 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "gfx_traits" -version = "0.0.1" -dependencies = [ - "malloc_size_of 0.0.1", - "malloc_size_of_derive 0.0.1", - "range 0.0.1", - "serde 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "gif" -version = "0.9.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "color_quant 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "lzw 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "gl_generator" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "khronos_api 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", - "xml-rs 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "gleam" -version = "0.4.29" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "gl_generator 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "glob" -version = "0.2.11" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "glutin" -version = "0.13.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "android_glue 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", - "cgl 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "cocoa 0.14.0 (registry+https://github.com/rust-lang/crates.io-index)", - "core-foundation 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", - "core-graphics 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)", - "gl_generator 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.39 (registry+https://github.com/rust-lang/crates.io-index)", - "objc 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "osmesa-sys 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "shared_library 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", - "wayland-client 0.12.5 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", - "winit 0.11.3 (registry+https://github.com/rust-lang/crates.io-index)", - "x11-dl 2.17.3 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "glx" -version = "0.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "gl_generator 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.39 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "gvr-sys" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "half" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "harfbuzz-sys" -version = "0.1.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "cmake 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", - "freetype 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.39 (registry+https://github.com/rust-lang/crates.io-index)", - "pkg-config 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "hashglobe" -version = "0.1.0" -dependencies = [ - "libc 0.2.39 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "heartbeats-simple" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "heartbeats-simple-sys 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.39 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "heartbeats-simple-sys" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "cmake 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.39 (registry+https://github.com/rust-lang/crates.io-index)", - "pkg-config 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "histogram" -version = "0.6.8" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "html5ever" -version = "0.22.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", - "mac 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "markup5ever 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.11.11 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "httparse" -version = "1.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "humantime" -version = "1.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "quick-error 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "hyper" -version = "0.10.13" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "base64 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", - "httparse 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "language-tags 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", - "mime 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)", - "num_cpus 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "time 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)", - "traitobject 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "typeable 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "unicase 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "url 1.6.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "hyper-openssl" -version = "0.2.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "antidote 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "hyper 0.10.13 (registry+https://github.com/rust-lang/crates.io-index)", - "openssl 0.9.24 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "hyper_serde" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "cookie 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)", - "hyper 0.10.13 (registry+https://github.com/rust-lang/crates.io-index)", - "mime 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_bytes 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)", - "time 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "ident_case" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "idna" -version = "0.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "matches 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", - "unicode-bidi 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", - "unicode-normalization 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "image" -version = "0.18.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "byteorder 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "enum_primitive 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "gif 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)", - "jpeg-decoder 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)", - "num-iter 0.1.33 (registry+https://github.com/rust-lang/crates.io-index)", - "num-rational 0.1.36 (registry+https://github.com/rust-lang/crates.io-index)", - "num-traits 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)", - "png 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", - "scoped_threadpool 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "immeta" -version = "0.3.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "arrayvec 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "byteorder 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "num-traits 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "inflate" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "adler32 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "influent" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "hyper 0.10.13 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "io-surface" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "cgl 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "core-foundation 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", - "gleam 0.4.29 (registry+https://github.com/rust-lang/crates.io-index)", - "leaky-cow 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.39 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "iovec" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "libc 0.2.39 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "ipc-channel" -version = "0.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "bincode 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "fnv 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.39 (registry+https://github.com/rust-lang/crates.io-index)", - "mio 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.3.22 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)", - "uuid 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "itertools" -version = "0.7.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "either 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "itoa" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "jemalloc-sys" -version = "0.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "cc 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.39 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "jemallocator" -version = "0.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "jemalloc-sys 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.39 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "jpeg-decoder" -version = "0.1.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "byteorder 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "rayon 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "jstraceable_derive" -version = "0.0.1" -dependencies = [ - "quote 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.12.12 (registry+https://github.com/rust-lang/crates.io-index)", - "synstructure 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "kernel32-sys" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "khronos_api" -version = "2.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "language-tags" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "layout" -version = "0.0.1" -dependencies = [ - "app_units 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", - "atomic_refcell 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "bitflags 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "canvas_traits 0.0.1", - "euclid 0.17.2 (registry+https://github.com/rust-lang/crates.io-index)", - "fnv 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", - "gfx 0.0.1", - "gfx_traits 0.0.1", - "html5ever 0.22.0 (registry+https://github.com/rust-lang/crates.io-index)", - "ipc-channel 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.39 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", - "malloc_size_of 0.0.1", - "msg 0.0.1", - "net_traits 0.0.1", - "ordered-float 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "parking_lot 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)", - "profile_traits 0.0.1", - "range 0.0.1", - "rayon 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "script_layout_interface 0.0.1", - "script_traits 0.0.1", - "selectors 0.19.0", - "serde 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "servo_arc 0.1.1", - "servo_atoms 0.0.1", - "servo_config 0.0.1", - "servo_geometry 0.0.1", - "servo_url 0.0.1", - "size_of_test 0.0.1", - "smallvec 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", - "style 0.0.1", - "style_traits 0.0.1", - "unicode-bidi 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", - "unicode-script 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "webrender_api 0.57.0 (git+https://github.com/servo/webrender)", - "xi-unicode 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "layout_thread" -version = "0.0.1" -dependencies = [ - "app_units 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", - "atomic_refcell 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "euclid 0.17.2 (registry+https://github.com/rust-lang/crates.io-index)", - "fnv 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", - "gfx 0.0.1", - "gfx_traits 0.0.1", - "histogram 0.6.8 (registry+https://github.com/rust-lang/crates.io-index)", - "html5ever 0.22.0 (registry+https://github.com/rust-lang/crates.io-index)", - "ipc-channel 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)", - "layout 0.0.1", - "layout_traits 0.0.1", - "lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.39 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", - "malloc_size_of 0.0.1", - "metrics 0.0.1", - "msg 0.0.1", - "net_traits 0.0.1", - "parking_lot 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)", - "profile_traits 0.0.1", - "range 0.0.1", - "rayon 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "script 0.0.1", - "script_layout_interface 0.0.1", - "script_traits 0.0.1", - "selectors 0.19.0", - "serde_json 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "servo_allocator 0.0.1", - "servo_arc 0.1.1", - "servo_atoms 0.0.1", - "servo_config 0.0.1", - "servo_geometry 0.0.1", - "servo_url 0.0.1", - "style 0.0.1", - "style_traits 0.0.1", - "time 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)", - "webrender_api 0.57.0 (git+https://github.com/servo/webrender)", -] - -[[package]] -name = "layout_traits" -version = "0.0.1" -dependencies = [ - "gfx 0.0.1", - "ipc-channel 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)", - "metrics 0.0.1", - "msg 0.0.1", - "net_traits 0.0.1", - "profile_traits 0.0.1", - "script_traits 0.0.1", - "servo_url 0.0.1", - "webrender_api 0.57.0 (git+https://github.com/servo/webrender)", -] - -[[package]] -name = "lazy_static" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "lazycell" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "leak" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "leaky-cow" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "leak 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "libc" -version = "0.2.39" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "libdbus-sys" -version = "0.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "pkg-config 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "libloading" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "cc 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "libservo" -version = "0.0.1" -dependencies = [ - "bluetooth 0.0.1", - "bluetooth_traits 0.0.1", - "canvas 0.0.1", - "canvas_traits 0.0.1", - "compositing 0.0.1", - "constellation 0.0.1", - "debugger 0.0.1", - "devtools 0.0.1", - "devtools_traits 0.0.1", - "env_logger 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)", - "euclid 0.17.2 (registry+https://github.com/rust-lang/crates.io-index)", - "gaol 0.0.1 (git+https://github.com/servo/gaol)", - "gfx 0.0.1", - "gleam 0.4.29 (registry+https://github.com/rust-lang/crates.io-index)", - "ipc-channel 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)", - "layout_thread 0.0.1", - "log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", - "msg 0.0.1", - "net 0.0.1", - "net_traits 0.0.1", - "profile 0.0.1", - "profile_traits 0.0.1", - "script 0.0.1", - "script_layout_interface 0.0.1", - "script_traits 0.0.1", - "servo_config 0.0.1", - "servo_geometry 0.0.1", - "servo_url 0.0.1", - "style 0.0.1", - "style_traits 0.0.1", - "webdriver_server 0.0.1", - "webrender 0.57.0 (git+https://github.com/servo/webrender)", - "webrender_api 0.57.0 (git+https://github.com/servo/webrender)", - "webvr 0.0.1", - "webvr_traits 0.0.1", -] - -[[package]] -name = "libz-sys" -version = "1.0.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "cc 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.39 (registry+https://github.com/rust-lang/crates.io-index)", - "pkg-config 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", - "vcpkg 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "log" -version = "0.3.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "log" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "cfg-if 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "lzw" -version = "0.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "mac" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "malloc_buf" -version = "0.0.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "libc 0.2.39 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "malloc_size_of" -version = "0.0.1" -dependencies = [ - "app_units 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", - "cssparser 0.23.2 (registry+https://github.com/rust-lang/crates.io-index)", - "euclid 0.17.2 (registry+https://github.com/rust-lang/crates.io-index)", - "hashglobe 0.1.0", - "hyper 0.10.13 (registry+https://github.com/rust-lang/crates.io-index)", - "hyper_serde 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", - "mozjs 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", - "selectors 0.19.0", - "serde 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_bytes 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)", - "servo_arc 0.1.1", - "smallbitvec 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "smallvec 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", - "string_cache 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", - "time 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)", - "url 1.6.0 (registry+https://github.com/rust-lang/crates.io-index)", - "void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "webrender_api 0.57.0 (git+https://github.com/servo/webrender)", - "xml5ever 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "malloc_size_of_derive" -version = "0.0.1" -dependencies = [ - "quote 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.12.12 (registry+https://github.com/rust-lang/crates.io-index)", - "synstructure 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "malloc_size_of_tests" -version = "0.0.1" -dependencies = [ - "malloc_size_of 0.0.1", - "servo_arc 0.1.1", -] - -[[package]] -name = "markup5ever" -version = "0.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "phf 0.7.21 (registry+https://github.com/rust-lang/crates.io-index)", - "phf_codegen 0.7.21 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "string_cache 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", - "string_cache_codegen 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "tendril 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "matches" -version = "0.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "memchr" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "libc 0.2.39 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "memmap" -version = "0.6.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "libc 0.2.39 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "memoffset" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "metrics" -version = "0.0.1" -dependencies = [ - "gfx_traits 0.0.1", - "ipc-channel 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", - "malloc_size_of 0.0.1", - "malloc_size_of_derive 0.0.1", - "msg 0.0.1", - "profile_traits 0.0.1", - "script_traits 0.0.1", - "servo_config 0.0.1", - "servo_url 0.0.1", - "time 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "metrics_tests" -version = "0.0.1" -dependencies = [ - "gfx 0.0.1", - "gfx_traits 0.0.1", - "ipc-channel 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)", - "metrics 0.0.1", - "msg 0.0.1", - "net_traits 0.0.1", - "profile_traits 0.0.1", - "servo_url 0.0.1", - "time 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)", - "webrender_api 0.57.0 (git+https://github.com/servo/webrender)", -] - -[[package]] -name = "mime" -version = "0.2.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "mime_guess" -version = "1.8.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "mime 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)", - "phf 0.7.21 (registry+https://github.com/rust-lang/crates.io-index)", - "phf_codegen 0.7.21 (registry+https://github.com/rust-lang/crates.io-index)", - "unicase 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "miniz-sys" -version = "0.1.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "cc 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.39 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "mio" -version = "0.6.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", - "fuchsia-zircon-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", - "iovec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "lazycell 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.39 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", - "miow 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "net2 0.2.29 (registry+https://github.com/rust-lang/crates.io-index)", - "slab 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "miow" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "net2 0.2.29 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", - "ws2_32-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "mitochondria" -version = "1.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "mozangle" -version = "0.1.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "cc 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "mozjs" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "cmake 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.39 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", - "mozjs_sys 0.50.1 (registry+https://github.com/rust-lang/crates.io-index)", - "num-traits 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "mozjs_sys" -version = "0.50.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "libc 0.2.39 (registry+https://github.com/rust-lang/crates.io-index)", - "libz-sys 1.0.18 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "mp3-metadata" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "mp4parse" -version = "0.9.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "bitreader 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "byteorder 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "num-traits 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "msg" -version = "0.0.1" -dependencies = [ - "bitflags 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "malloc_size_of 0.0.1", - "malloc_size_of_derive 0.0.1", - "nonzero 0.0.1", - "serde 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)", - "size_of_test 0.0.1", - "webrender_api 0.57.0 (git+https://github.com/servo/webrender)", -] - -[[package]] -name = "net" -version = "0.0.1" -dependencies = [ - "base64 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", - "brotli 1.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "cookie 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)", - "devtools_traits 0.0.1", - "flate2 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", - "hyper 0.10.13 (registry+https://github.com/rust-lang/crates.io-index)", - "hyper-openssl 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", - "hyper_serde 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", - "immeta 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", - "ipc-channel 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", - "malloc_size_of 0.0.1", - "malloc_size_of_derive 0.0.1", - "matches 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", - "mime 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)", - "mime_guess 1.8.1 (registry+https://github.com/rust-lang/crates.io-index)", - "msg 0.0.1", - "net_traits 0.0.1", - "openssl 0.9.24 (registry+https://github.com/rust-lang/crates.io-index)", - "profile_traits 0.0.1", - "serde 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "servo-websocket 0.21.0 (registry+https://github.com/rust-lang/crates.io-index)", - "servo_allocator 0.0.1", - "servo_arc 0.1.1", - "servo_config 0.0.1", - "servo_url 0.0.1", - "threadpool 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", - "time 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)", - "tinyfiledialogs 3.3.5 (registry+https://github.com/rust-lang/crates.io-index)", - "unicase 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "url 1.6.0 (registry+https://github.com/rust-lang/crates.io-index)", - "uuid 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", - "webrender_api 0.57.0 (git+https://github.com/servo/webrender)", -] - -[[package]] -name = "net2" -version = "0.2.29" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "cfg-if 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.39 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", - "ws2_32-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "net_traits" -version = "0.0.1" -dependencies = [ - "cookie 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)", - "hyper 0.10.13 (registry+https://github.com/rust-lang/crates.io-index)", - "hyper_serde 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", - "image 0.18.0 (registry+https://github.com/rust-lang/crates.io-index)", - "ipc-channel 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", - "malloc_size_of 0.0.1", - "malloc_size_of_derive 0.0.1", - "msg 0.0.1", - "num-traits 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)", - "servo_arc 0.1.1", - "servo_config 0.0.1", - "servo_url 0.0.1", - "url 1.6.0 (registry+https://github.com/rust-lang/crates.io-index)", - "uuid 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", - "webrender_api 0.57.0 (git+https://github.com/servo/webrender)", -] - -[[package]] -name = "nodrop" -version = "0.1.12" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "nom" -version = "1.2.4" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "nonzero" -version = "0.0.1" -dependencies = [ - "serde 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "nsstring" -version = "0.1.0" -dependencies = [ - "bitflags 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "num" -version = "0.1.37" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "num-integer 0.1.34 (registry+https://github.com/rust-lang/crates.io-index)", - "num-iter 0.1.33 (registry+https://github.com/rust-lang/crates.io-index)", - "num-traits 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "num-integer" -version = "0.1.34" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "num-traits 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "num-iter" -version = "0.1.33" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "num-integer 0.1.34 (registry+https://github.com/rust-lang/crates.io-index)", - "num-traits 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "num-rational" -version = "0.1.36" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "num-integer 0.1.34 (registry+https://github.com/rust-lang/crates.io-index)", - "num-traits 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "num-traits" -version = "0.1.37" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "num_cpus" -version = "1.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "libc 0.2.39 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "objc" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "malloc_buf 0.0.6 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "objc-foundation" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "block 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "objc 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "objc_id 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "objc_id" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "objc 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "offscreen_gl_context" -version = "0.15.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "cgl 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "core-foundation 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", - "euclid 0.17.2 (registry+https://github.com/rust-lang/crates.io-index)", - "gl_generator 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", - "gleam 0.4.29 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libloading 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", - "objc 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "osmesa-sys 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", - "x11 2.17.3 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "ogg" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "byteorder 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "ogg_metadata" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "byteorder 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "ogg 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "openssl" -version = "0.9.24" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "bitflags 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)", - "foreign-types 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.39 (registry+https://github.com/rust-lang/crates.io-index)", - "openssl-sys 0.9.27 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "openssl-sys" -version = "0.9.27" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "cc 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.39 (registry+https://github.com/rust-lang/crates.io-index)", - "pkg-config 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", - "vcpkg 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "ordered-float" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "num-traits 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)", - "unreachable 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "osmesa-src" -version = "17.3.1-devel" -source = "git+https://github.com/servo/osmesa-src#6d23daede16f7edf7c66bdcce73c7583d0853733" - -[[package]] -name = "osmesa-sys" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "shared_library 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "ovr-mobile-sys" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "owning_ref" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "stable_deref_trait 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "parking_lot" -version = "0.5.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "owning_ref 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", - "parking_lot_core 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "parking_lot_core" -version = "0.2.13" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "libc 0.2.39 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", - "smallvec 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "peeking_take_while" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "percent-encoding" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "phf" -version = "0.7.21" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "phf_shared 0.7.21 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "phf_codegen" -version = "0.7.21" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "phf_generator 0.7.21 (registry+https://github.com/rust-lang/crates.io-index)", - "phf_shared 0.7.21 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "phf_generator" -version = "0.7.21" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "phf_shared 0.7.21 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.3.22 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "phf_shared" -version = "0.7.21" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "siphasher 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "unicase 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "pkg-config" -version = "0.3.9" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "plane-split" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "binary-space-partition 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "euclid 0.17.2 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", - "num-traits 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "png" -version = "0.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "bitflags 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "deflate 0.7.5 (registry+https://github.com/rust-lang/crates.io-index)", - "inflate 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", - "num-iter 0.1.33 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "precomputed-hash" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "proc-macro2" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "procedural-masquerade" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "profile" -version = "0.0.1" -dependencies = [ - "heartbeats-simple 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "influent 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "ipc-channel 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)", - "jemalloc-sys 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.39 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", - "profile_traits 0.0.1", - "regex 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "servo_config 0.0.1", - "task_info 0.0.1", - "time 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "profile_tests" -version = "0.0.1" -dependencies = [ - "ipc-channel 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)", - "profile 0.0.1", - "profile_traits 0.0.1", - "servo_allocator 0.0.1", - "servo_config 0.0.1", -] - -[[package]] -name = "profile_traits" -version = "0.0.1" -dependencies = [ - "bincode 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "energy-monitor 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "energymon 0.3.0 (git+https://github.com/energymon/energymon-rust.git)", - "ipc-channel 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)", - "servo_config 0.0.1", - "signpost 0.1.0 (git+https://github.com/pcwalton/signpost.git)", - "time 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "quick-error" -version = "1.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "quote" -version = "0.3.15" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "quote" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "proc-macro2 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "rand" -version = "0.3.22" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.39 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "rand" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.39 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "range" -version = "0.0.1" -dependencies = [ - "malloc_size_of 0.0.1", - "malloc_size_of_derive 0.0.1", - "num-traits 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "rayon" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "either 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rayon-core 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "rayon-core" -version = "1.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "crossbeam-deque 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.39 (registry+https://github.com/rust-lang/crates.io-index)", - "num_cpus 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "redox_syscall" -version = "0.1.17" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "redox_termios" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "redox_syscall 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "ref_filter_map" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "ref_slice" -version = "1.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "regex" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "aho-corasick 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)", - "memchr 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", - "regex-syntax 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", - "thread_local 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", - "utf8-ranges 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "regex-syntax" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "ron" -version = "0.1.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "serde 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "rust-webvr" -version = "0.9.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "gl_generator 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", - "gvr-sys 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libloading 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", - "ovr-mobile-sys 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rust-webvr-api 0.9.2 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "rust-webvr-api" -version = "0.9.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "android_injected_glue 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)", - "time 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "rustc-demangle" -version = "0.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "rustc-serialize" -version = "0.3.24" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "rustc_version" -version = "0.1.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "semver 0.1.20 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "safemem" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "same-file" -version = "1.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "winapi 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "scoped_threadpool" -version = "0.1.7" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "scopeguard" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "script" -version = "0.0.1" -dependencies = [ - "app_units 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", - "audio-video-metadata 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "base64 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", - "bitflags 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "bluetooth_traits 0.0.1", - "byteorder 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "canvas_traits 0.0.1", - "caseless 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "chrono 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "cmake 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", - "cookie 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)", - "cssparser 0.23.2 (registry+https://github.com/rust-lang/crates.io-index)", - "deny_public_fields 0.0.1", - "devtools_traits 0.0.1", - "dom_struct 0.0.1", - "domobject_derive 0.0.1", - "encoding_rs 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", - "euclid 0.17.2 (registry+https://github.com/rust-lang/crates.io-index)", - "fnv 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", - "gleam 0.4.29 (registry+https://github.com/rust-lang/crates.io-index)", - "half 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "html5ever 0.22.0 (registry+https://github.com/rust-lang/crates.io-index)", - "hyper 0.10.13 (registry+https://github.com/rust-lang/crates.io-index)", - "hyper_serde 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", - "image 0.18.0 (registry+https://github.com/rust-lang/crates.io-index)", - "ipc-channel 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)", - "itertools 0.7.6 (registry+https://github.com/rust-lang/crates.io-index)", - "jstraceable_derive 0.0.1", - "lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.39 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", - "malloc_size_of 0.0.1", - "malloc_size_of_derive 0.0.1", - "metrics 0.0.1", - "mime 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)", - "mime_guess 1.8.1 (registry+https://github.com/rust-lang/crates.io-index)", - "mitochondria 1.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "mozangle 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "mozjs 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", - "msg 0.0.1", - "net_traits 0.0.1", - "num-traits 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)", - "offscreen_gl_context 0.15.1 (registry+https://github.com/rust-lang/crates.io-index)", - "parking_lot 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)", - "phf 0.7.21 (registry+https://github.com/rust-lang/crates.io-index)", - "phf_codegen 0.7.21 (registry+https://github.com/rust-lang/crates.io-index)", - "phf_shared 0.7.21 (registry+https://github.com/rust-lang/crates.io-index)", - "profile_traits 0.0.1", - "ref_filter_map 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", - "ref_slice 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "regex 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "script_layout_interface 0.0.1", - "script_plugins 0.0.1", - "script_traits 0.0.1", - "selectors 0.19.0", - "serde 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_bytes 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "servo_allocator 0.0.1", - "servo_arc 0.1.1", - "servo_atoms 0.0.1", - "servo_config 0.0.1", - "servo_geometry 0.0.1", - "servo_rand 0.0.1", - "servo_url 0.0.1", - "smallvec 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", - "style 0.0.1", - "style_traits 0.0.1", - "swapper 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "time 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)", - "tinyfiledialogs 3.3.5 (registry+https://github.com/rust-lang/crates.io-index)", - "unicode-segmentation 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "url 1.6.0 (registry+https://github.com/rust-lang/crates.io-index)", - "utf-8 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", - "uuid 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", - "webrender_api 0.57.0 (git+https://github.com/servo/webrender)", - "webvr_traits 0.0.1", - "xml5ever 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "script_layout_interface" -version = "0.0.1" -dependencies = [ - "app_units 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", - "atomic_refcell 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "canvas_traits 0.0.1", - "cssparser 0.23.2 (registry+https://github.com/rust-lang/crates.io-index)", - "euclid 0.17.2 (registry+https://github.com/rust-lang/crates.io-index)", - "gfx_traits 0.0.1", - "html5ever 0.22.0 (registry+https://github.com/rust-lang/crates.io-index)", - "ipc-channel 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.39 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", - "malloc_size_of 0.0.1", - "malloc_size_of_derive 0.0.1", - "metrics 0.0.1", - "msg 0.0.1", - "net_traits 0.0.1", - "profile_traits 0.0.1", - "range 0.0.1", - "script_traits 0.0.1", - "selectors 0.19.0", - "servo_arc 0.1.1", - "servo_atoms 0.0.1", - "servo_url 0.0.1", - "style 0.0.1", - "time 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)", - "webrender_api 0.57.0 (git+https://github.com/servo/webrender)", -] - -[[package]] -name = "script_plugins" -version = "0.0.1" - -[[package]] -name = "script_plugins_tests" -version = "0.0.1" -dependencies = [ - "script_plugins 0.0.1", -] - -[[package]] -name = "script_tests" -version = "0.0.1" -dependencies = [ - "euclid 0.17.2 (registry+https://github.com/rust-lang/crates.io-index)", - "msg 0.0.1", - "script 0.0.1", - "servo_url 0.0.1", - "style 0.0.1", -] - -[[package]] -name = "script_traits" -version = "0.0.1" -dependencies = [ - "bluetooth_traits 0.0.1", - "canvas_traits 0.0.1", - "cookie 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)", - "devtools_traits 0.0.1", - "euclid 0.17.2 (registry+https://github.com/rust-lang/crates.io-index)", - "gfx_traits 0.0.1", - "hyper 0.10.13 (registry+https://github.com/rust-lang/crates.io-index)", - "hyper_serde 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", - "ipc-channel 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.39 (registry+https://github.com/rust-lang/crates.io-index)", - "malloc_size_of 0.0.1", - "malloc_size_of_derive 0.0.1", - "msg 0.0.1", - "net_traits 0.0.1", - "profile_traits 0.0.1", - "rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)", - "servo_atoms 0.0.1", - "servo_url 0.0.1", - "style_traits 0.0.1", - "time 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)", - "url 1.6.0 (registry+https://github.com/rust-lang/crates.io-index)", - "webrender_api 0.57.0 (git+https://github.com/servo/webrender)", - "webvr_traits 0.0.1", -] - -[[package]] -name = "selectors" -version = "0.19.0" -dependencies = [ - "bitflags 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "cssparser 0.23.2 (registry+https://github.com/rust-lang/crates.io-index)", - "fnv 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", - "matches 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", - "phf 0.7.21 (registry+https://github.com/rust-lang/crates.io-index)", - "phf_codegen 0.7.21 (registry+https://github.com/rust-lang/crates.io-index)", - "precomputed-hash 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "servo_arc 0.1.1", - "smallvec 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "semver" -version = "0.1.20" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "serde" -version = "1.0.27" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "serde_derive 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "serde_bytes" -version = "0.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "serde 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "serde_derive" -version = "1.0.27" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive_internals 0.19.0 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.11.11 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "serde_derive_internals" -version = "0.19.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "syn 0.11.11 (registry+https://github.com/rust-lang/crates.io-index)", - "synom 0.11.3 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "serde_json" -version = "1.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "dtoa 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", - "itoa 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "num-traits 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "servo" -version = "0.0.1" -dependencies = [ - "android_injected_glue 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", - "backtrace 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", - "bitflags 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "euclid 0.17.2 (registry+https://github.com/rust-lang/crates.io-index)", - "gdi32-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "gleam 0.4.29 (registry+https://github.com/rust-lang/crates.io-index)", - "glutin 0.13.1 (registry+https://github.com/rust-lang/crates.io-index)", - "libservo 0.0.1", - "log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", - "osmesa-src 17.3.1-devel (git+https://github.com/servo/osmesa-src)", - "osmesa-sys 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "servo-egl 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "sig 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "tinyfiledialogs 3.3.5 (registry+https://github.com/rust-lang/crates.io-index)", - "user32-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", - "winit 0.11.3 (registry+https://github.com/rust-lang/crates.io-index)", - "winres 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "x11 2.17.3 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "servo-egl" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "libc 0.2.39 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "servo-fontconfig" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "libc 0.2.39 (registry+https://github.com/rust-lang/crates.io-index)", - "servo-fontconfig-sys 4.0.4 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "servo-fontconfig-sys" -version = "4.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "expat-sys 2.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "pkg-config 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", - "servo-freetype-sys 4.0.3 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "servo-freetype-sys" -version = "4.0.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "cmake 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", - "pkg-config 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "servo-skia" -version = "0.30000013.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "cgl 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "cmake 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", - "euclid 0.17.2 (registry+https://github.com/rust-lang/crates.io-index)", - "expat-sys 2.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "gleam 0.4.29 (registry+https://github.com/rust-lang/crates.io-index)", - "glutin 0.13.1 (registry+https://github.com/rust-lang/crates.io-index)", - "glx 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", - "io-surface 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.39 (registry+https://github.com/rust-lang/crates.io-index)", - "servo-egl 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "servo-fontconfig-sys 4.0.4 (registry+https://github.com/rust-lang/crates.io-index)", - "servo-freetype-sys 4.0.3 (registry+https://github.com/rust-lang/crates.io-index)", - "x11 2.17.3 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "servo-websocket" -version = "0.21.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "base64 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", - "bitflags 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "byteorder 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "hyper 0.10.13 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.3.22 (registry+https://github.com/rust-lang/crates.io-index)", - "sha1 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "unicase 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "url 1.6.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "servo_allocator" -version = "0.0.1" -dependencies = [ - "jemallocator 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", - "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.39 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "servo_arc" -version = "0.1.1" -dependencies = [ - "nodrop 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)", - "stable_deref_trait 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "servo_atoms" -version = "0.0.1" -dependencies = [ - "string_cache 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", - "string_cache_codegen 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "servo_config" -version = "0.0.1" -dependencies = [ - "android_injected_glue 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", - "env_logger 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)", - "euclid 0.17.2 (registry+https://github.com/rust-lang/crates.io-index)", - "getopts 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", - "num_cpus 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)", - "servo_geometry 0.0.1", - "servo_url 0.0.1", - "url 1.6.0 (registry+https://github.com/rust-lang/crates.io-index)", - "xdg 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "servo_geometry" -version = "0.0.1" -dependencies = [ - "app_units 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", - "euclid 0.17.2 (registry+https://github.com/rust-lang/crates.io-index)", - "malloc_size_of 0.0.1", - "malloc_size_of_derive 0.0.1", - "style_traits 0.0.1", - "webrender_api 0.57.0 (git+https://github.com/servo/webrender)", -] - -[[package]] -name = "servo_rand" -version = "0.0.1" -dependencies = [ - "lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", - "uuid 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "servo_remutex" -version = "0.0.1" -dependencies = [ - "lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", - "nonzero 0.0.1", -] - -[[package]] -name = "servo_url" -version = "0.0.1" -dependencies = [ - "malloc_size_of 0.0.1", - "malloc_size_of_derive 0.0.1", - "serde 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)", - "servo_rand 0.0.1", - "url 1.6.0 (registry+https://github.com/rust-lang/crates.io-index)", - "url_serde 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "uuid 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "sha1" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "shared_library" -version = "0.1.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.39 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "sig" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "signpost" -version = "0.1.0" -source = "git+https://github.com/pcwalton/signpost.git#7ed712507f343c38646b9d1fefd049166f9c9a18" - -[[package]] -name = "simd" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "siphasher" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "size_of_test" -version = "0.0.1" - -[[package]] -name = "slab" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "smallbitvec" -version = "2.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "smallvec" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "stable_deref_trait" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "string_cache" -version = "0.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "debug_unreachable 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "phf_shared 0.7.21 (registry+https://github.com/rust-lang/crates.io-index)", - "precomputed-hash 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)", - "string_cache_codegen 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "string_cache_shared 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "string_cache_codegen" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "phf_generator 0.7.21 (registry+https://github.com/rust-lang/crates.io-index)", - "phf_shared 0.7.21 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)", - "string_cache_shared 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "string_cache_shared" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "strsim" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "style" -version = "0.0.1" -dependencies = [ - "app_units 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", - "arrayvec 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "atomic_refcell 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "bindgen 0.33.2 (registry+https://github.com/rust-lang/crates.io-index)", - "bitflags 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "byteorder 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "cfg-if 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "cssparser 0.23.2 (registry+https://github.com/rust-lang/crates.io-index)", - "debug_unreachable 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "encoding_rs 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", - "euclid 0.17.2 (registry+https://github.com/rust-lang/crates.io-index)", - "fallible 0.0.1", - "fnv 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", - "hashglobe 0.1.0", - "html5ever 0.22.0 (registry+https://github.com/rust-lang/crates.io-index)", - "itertools 0.7.6 (registry+https://github.com/rust-lang/crates.io-index)", - "itoa 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", - "malloc_size_of 0.0.1", - "malloc_size_of_derive 0.0.1", - "matches 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", - "nsstring 0.1.0", - "num-integer 0.1.34 (registry+https://github.com/rust-lang/crates.io-index)", - "num-traits 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)", - "num_cpus 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "ordered-float 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "owning_ref 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", - "parking_lot 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)", - "precomputed-hash 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "rayon 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "regex 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "selectors 0.19.0", - "serde 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)", - "servo_arc 0.1.1", - "servo_atoms 0.0.1", - "servo_config 0.0.1", - "servo_url 0.0.1", - "smallbitvec 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "smallvec 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", - "string_cache 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", - "style_derive 0.0.1", - "style_traits 0.0.1", - "time 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)", - "toml 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", - "uluru 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "unicode-bidi 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", - "unicode-segmentation 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "walkdir 2.1.4 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "style_derive" -version = "0.0.1" -dependencies = [ - "darling 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.12.12 (registry+https://github.com/rust-lang/crates.io-index)", - "synstructure 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "style_tests" -version = "0.0.1" -dependencies = [ - "app_units 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", - "byteorder 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "cssparser 0.23.2 (registry+https://github.com/rust-lang/crates.io-index)", - "euclid 0.17.2 (registry+https://github.com/rust-lang/crates.io-index)", - "html5ever 0.22.0 (registry+https://github.com/rust-lang/crates.io-index)", - "parking_lot 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)", - "rayon 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "selectors 0.19.0", - "serde_json 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "servo_arc 0.1.1", - "servo_atoms 0.0.1", - "servo_config 0.0.1", - "servo_url 0.0.1", - "size_of_test 0.0.1", - "style 0.0.1", - "style_traits 0.0.1", -] - -[[package]] -name = "style_traits" -version = "0.0.1" -dependencies = [ - "app_units 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", - "bitflags 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "cssparser 0.23.2 (registry+https://github.com/rust-lang/crates.io-index)", - "euclid 0.17.2 (registry+https://github.com/rust-lang/crates.io-index)", - "malloc_size_of 0.0.1", - "malloc_size_of_derive 0.0.1", - "selectors 0.19.0", - "serde 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)", - "servo_arc 0.1.1", - "servo_atoms 0.0.1", - "webrender_api 0.57.0 (git+https://github.com/servo/webrender)", -] - -[[package]] -name = "stylo_tests" -version = "0.0.1" -dependencies = [ - "atomic_refcell 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "cssparser 0.23.2 (registry+https://github.com/rust-lang/crates.io-index)", - "cstr 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "env_logger 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)", - "euclid 0.17.2 (registry+https://github.com/rust-lang/crates.io-index)", - "geckoservo 0.0.1", - "libc 0.2.39 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", - "malloc_size_of 0.0.1", - "regex 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "selectors 0.19.0", - "size_of_test 0.0.1", - "smallvec 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", - "style 0.0.1", - "style_traits 0.0.1", -] - -[[package]] -name = "swapper" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "syn" -version = "0.11.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)", - "synom 0.11.3 (registry+https://github.com/rust-lang/crates.io-index)", - "unicode-xid 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "syn" -version = "0.12.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "proc-macro2 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", - "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "synom" -version = "0.11.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "unicode-xid 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "synstructure" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "proc-macro2 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.12.12 (registry+https://github.com/rust-lang/crates.io-index)", - "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "task_info" -version = "0.0.1" -dependencies = [ - "cc 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "tempfile" -version = "2.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.39 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.3.22 (registry+https://github.com/rust-lang/crates.io-index)", - "redox_syscall 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "tendril" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "futf 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", - "mac 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "utf-8 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "termcolor" -version = "0.3.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "wincolor 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "termion" -version = "1.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "libc 0.2.39 (registry+https://github.com/rust-lang/crates.io-index)", - "redox_syscall 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)", - "redox_termios 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "textwrap" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "unicode-width 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "thread-id" -version = "3.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.39 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "thread_local" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "thread-id 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "unreachable 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "thread_profiler" -version = "0.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "threadpool" -version = "1.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "time" -version = "0.1.37" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.39 (registry+https://github.com/rust-lang/crates.io-index)", - "redox_syscall 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "tinyfiledialogs" -version = "3.3.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "cc 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.39 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "token_store" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "toml" -version = "0.4.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "serde 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "traitobject" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "truetype" -version = "0.26.0" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "typeable" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "uluru" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "arrayvec 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "unicase" -version = "1.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "rustc_version 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "unicode-bidi" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "matches 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "unicode-normalization" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "unicode-script" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "harfbuzz-sys 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "unicode-segmentation" -version = "1.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "unicode-width" -version = "0.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "unicode-xid" -version = "0.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "unicode-xid" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "unreachable" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "url" -version = "1.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "idna 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", - "matches 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", - "percent-encoding 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "url_serde" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "serde 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)", - "url 1.6.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "user32-sys" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "utf-8" -version = "0.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "matches 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "utf8-ranges" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "uuid" -version = "0.6.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "cfg-if 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "vcpkg" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "vec_map" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "void" -version = "1.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "walkdir" -version = "2.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "same-file 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "wayland-client" -version = "0.12.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "bitflags 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.39 (registry+https://github.com/rust-lang/crates.io-index)", - "token_store 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "wayland-scanner 0.12.5 (registry+https://github.com/rust-lang/crates.io-index)", - "wayland-sys 0.12.5 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "wayland-kbd" -version = "0.13.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "bitflags 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "dlib 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "memmap 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", - "wayland-client 0.12.5 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "wayland-protocols" -version = "0.12.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "bitflags 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "wayland-client 0.12.5 (registry+https://github.com/rust-lang/crates.io-index)", - "wayland-scanner 0.12.5 (registry+https://github.com/rust-lang/crates.io-index)", - "wayland-sys 0.12.5 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "wayland-scanner" -version = "0.12.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "xml-rs 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "wayland-sys" -version = "0.12.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "dlib 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "wayland-window" -version = "0.13.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "memmap 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", - "tempfile 2.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "wayland-client 0.12.5 (registry+https://github.com/rust-lang/crates.io-index)", - "wayland-protocols 0.12.5 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "webdriver" -version = "0.33.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "cookie 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)", - "hyper 0.10.13 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", - "regex 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)", - "time 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)", - "url 1.6.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "webdriver_server" -version = "0.0.1" -dependencies = [ - "base64 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", - "cookie 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)", - "euclid 0.17.2 (registry+https://github.com/rust-lang/crates.io-index)", - "hyper 0.10.13 (registry+https://github.com/rust-lang/crates.io-index)", - "image 0.18.0 (registry+https://github.com/rust-lang/crates.io-index)", - "ipc-channel 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", - "msg 0.0.1", - "net_traits 0.0.1", - "regex 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)", - "script_traits 0.0.1", - "servo_config 0.0.1", - "servo_url 0.0.1", - "url 1.6.0 (registry+https://github.com/rust-lang/crates.io-index)", - "uuid 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", - "webdriver 0.33.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "webrender" -version = "0.57.0" -source = "git+https://github.com/servo/webrender#53750b8b5760a9e63414ae486de7249cd49ac700" -dependencies = [ - "app_units 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", - "base64 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", - "bincode 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "bitflags 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "byteorder 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "core-foundation 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", - "core-graphics 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)", - "core-text 9.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "dwrote 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", - "euclid 0.17.2 (registry+https://github.com/rust-lang/crates.io-index)", - "freetype 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "fxhash 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "gleam 0.4.29 (registry+https://github.com/rust-lang/crates.io-index)", - "image 0.18.0 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", - "num-traits 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)", - "plane-split 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rayon 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "ron 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "smallvec 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", - "thread_profiler 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", - "time 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)", - "webrender_api 0.57.0 (git+https://github.com/servo/webrender)", - "ws 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "webrender_api" -version = "0.57.0" -source = "git+https://github.com/servo/webrender#53750b8b5760a9e63414ae486de7249cd49ac700" -dependencies = [ - "app_units 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", - "bincode 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "bitflags 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "byteorder 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "core-foundation 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", - "core-graphics 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)", - "dwrote 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", - "euclid 0.17.2 (registry+https://github.com/rust-lang/crates.io-index)", - "ipc-channel 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)", - "time 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "webvr" -version = "0.0.1" -dependencies = [ - "canvas_traits 0.0.1", - "euclid 0.17.2 (registry+https://github.com/rust-lang/crates.io-index)", - "ipc-channel 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", - "msg 0.0.1", - "rust-webvr 0.9.10 (registry+https://github.com/rust-lang/crates.io-index)", - "script_traits 0.0.1", - "servo_config 0.0.1", - "webvr_traits 0.0.1", -] - -[[package]] -name = "webvr_traits" -version = "0.0.1" -dependencies = [ - "ipc-channel 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)", - "msg 0.0.1", - "rust-webvr-api 0.9.2 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "which" -version = "1.0.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "libc 0.2.39 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "winapi" -version = "0.2.8" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "winapi" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "winapi-i686-pc-windows-gnu 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi-x86_64-pc-windows-gnu 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "winapi-build" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "winapi-i686-pc-windows-gnu" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "winapi-x86_64-pc-windows-gnu" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "wincolor" -version = "0.1.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "winapi 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "winit" -version = "0.11.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "android_glue 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", - "cocoa 0.14.0 (registry+https://github.com/rust-lang/crates.io-index)", - "core-foundation 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", - "core-graphics 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.39 (registry+https://github.com/rust-lang/crates.io-index)", - "objc 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "percent-encoding 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "wayland-client 0.12.5 (registry+https://github.com/rust-lang/crates.io-index)", - "wayland-kbd 0.13.1 (registry+https://github.com/rust-lang/crates.io-index)", - "wayland-protocols 0.12.5 (registry+https://github.com/rust-lang/crates.io-index)", - "wayland-window 0.13.2 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", - "x11-dl 2.17.3 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "winres" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "toml 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "ws" -version = "0.7.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "byteorder 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "bytes 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "httparse 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", - "mio 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.3.22 (registry+https://github.com/rust-lang/crates.io-index)", - "sha1 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "slab 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "url 1.6.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "ws2_32-sys" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "x11" -version = "2.17.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "libc 0.2.39 (registry+https://github.com/rust-lang/crates.io-index)", - "pkg-config 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "x11-clipboard" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "error-chain 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", - "xcb 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "x11-dl" -version = "2.17.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.39 (registry+https://github.com/rust-lang/crates.io-index)", - "pkg-config 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "xcb" -version = "0.8.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "libc 0.2.39 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "xdg" -version = "2.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "xi-unicode" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "xml-rs" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "bitflags 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "xml5ever" -version = "0.12.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", - "mac 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "markup5ever 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", - "time 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[metadata] -"checksum adler32 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3ff33fe13a08dbce05bcefa2c68eea4844941437e33d6f808240b54d7157b9cd" -"checksum aho-corasick 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)" = "500909c4f87a9e52355b26626d890833e9e1d53ac566db76c36faa984b889699" -"checksum alloc-no-stdlib 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b21f6ad9c9957eb5d70c3dee16d31c092b3cab339628f821766b05e6833d72b8" -"checksum android_glue 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "000444226fcff248f2bc4c7625be32c63caccfecc2723a2b9f78a7487a49c407" -"checksum android_injected_glue 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "80b9e34fcbf29c0563547cb2ecce9b49504597cad6166769b1e4efb45c6c2951" -"checksum ansi_term 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6b3568b48b7cefa6b8ce125f9bb4989e52fbcc29ebea88df04cc7c5f12f70455" -"checksum antidote 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "34fde25430d87a9388dadbe6e34d7f72a462c8b43ac8d309b42b0a8505d7e2a5" -"checksum app_units 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)" = "c4720c83543de184d9f6add2fdb8e8031543497b8506620884c16e125b493c09" -"checksum arrayvec 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "2f0ef4a9820019a0c91d918918c93dc71d469f581a49b47ddc1d285d4270bbe2" -"checksum atomic_refcell 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fb2dcb6e6d35f20276943cc04bb98e538b348d525a04ac79c10021561d202f21" -"checksum atty 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "21e50800ec991574876040fff8ee46b136a53e985286fbe6a3bdfe6421b78860" -"checksum audio-video-metadata 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "71536082079f5ba92c274fba7c2dcd4e2f9d5c13ce6d7f8fe9acbbb258916d18" -"checksum azure 0.28.0 (git+https://github.com/servo/rust-azure)" = "" -"checksum backtrace 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "72f9b4182546f4b04ebc4ab7f84948953a118bd6021a1b6a6c909e3e94f6be76" -"checksum backtrace-sys 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)" = "44585761d6161b0f57afc49482ab6bd067e4edef48c12a152c237eb0203f7661" -"checksum base64 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "96434f987501f0ed4eb336a411e0631ecd1afa11574fe148587adc4ff96143c9" -"checksum binary-space-partition 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "88ceb0d16c4fd0e42876e298d7d3ce3780dd9ebdcbe4199816a32c77e08597ff" -"checksum bincode 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bda13183df33055cbb84b847becce220d392df502ebe7a4a78d7021771ed94d0" -"checksum bindgen 0.33.2 (registry+https://github.com/rust-lang/crates.io-index)" = "603ed8d8392ace9581e834e26bd09799bf1e989a79bd1aedbb893e72962bdc6e" -"checksum bitflags 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)" = "4efd02e230a02e18f92fc2735f44597385ed02ad8f831e7c1c1156ee5e1ab3a5" -"checksum bitflags 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f5cde24d1b2e2216a726368b2363a273739c91f4e3eb4e0dd12d672d396ad989" -"checksum bitreader 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "80b13e2ab064ff3aa0bdbf1eff533f9822dc37899821f5f98c67f263eab51707" -"checksum block 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "0d8c1fef690941d3e7788d328517591fecc684c084084702d6ff1641e993699a" -"checksum blurdroid 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "d7daba519d29beebfc7d302795af88a16b43f431b9b268586926ac61cc655a68" -"checksum blurmac 0.1.0 (git+https://github.com/servo/devices)" = "" -"checksum blurmock 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "68dd72da3a3bb40f3d3bdd366c4cf8e2b1d208c366304f382c80cef8126ca8da" -"checksum blurz 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e73bda0f4c71c63a047351070097f3f507e6718e86b9ee525173371ef7b94b73" -"checksum brotli 1.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "fe87b40996b84fdc56e57c165d93079f4b50cb806598118e692ddfaa3d3c57c0" -"checksum brotli-decompressor 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "313f4b6cc0b365d6b88eda5aa40175ee34ac6efa9a79e0b3b8202eca90247ba8" -"checksum byteorder 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "652805b7e73fada9d85e9a6682a4abd490cb52d96aeecc12e33a0de34dfd0d23" -"checksum bytes 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "1b7db437d718977f6dc9b2e3fd6fc343c02ac6b899b73fdd2179163447bd9ce9" -"checksum caseless 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e3261638034d9db4f94a666ebb16494846341ae5a8456c05c1616d66980cf39a" -"checksum cc 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "9be26b24e988625409b19736d130f0c7d224f01d06454b5f81d8d23d6c1a618f" -"checksum cexpr 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "393a5f0088efbe41f9d1fcd062f24e83c278608420e62109feb2c8abee07de7d" -"checksum cfg-if 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "d4c819a1287eb618df47cc647173c5c4c66ba19d888a6e50d605672aed3140de" -"checksum cgl 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "86765cb42c2a2c497e142af72517c1b4d7ae5bb2f25dfa77a5c69642f2342d89" -"checksum chrono 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7c20ebe0b2b08b0aeddba49c609fe7957ba2e33449882cb186a180bc60682fa9" -"checksum clang-sys 0.22.0 (registry+https://github.com/rust-lang/crates.io-index)" = "939a1a34310b120d26eba35c29475933128b0ec58e24b43327f8dbe6036fc538" -"checksum clap 2.28.0 (registry+https://github.com/rust-lang/crates.io-index)" = "dc34bf7d5d66268b466b9852bca925ec1d2650654dab4da081e63fd230145c2e" -"checksum clipboard 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "b9b4623b47d8637fc9d47564583d4cc01eb8c8e34e26b2bf348bf4b036acb657" -"checksum clipboard-win 2.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "14cc3e6c075926b96490d5f90d4a5af7be8012a4d8a8698e619655085a7641a3" -"checksum cmake 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)" = "56d741ea7a69e577f6d06b36b7dff4738f680593dc27a701ffa8506b73ce28bb" -"checksum cocoa 0.14.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b0c23085dde1ef4429df6e5896b89356d35cdd321fb43afe3e378d010bb5adc6" -"checksum color_quant 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a475fc4af42d83d28adf72968d9bcfaf035a1a9381642d8e85d8a04957767b0d" -"checksum cookie 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)" = "746858cae4eae40fff37e1998320068df317bc247dc91a67c6cfa053afdc2abb" -"checksum core-foundation 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "286e0b41c3a20da26536c6000a280585d519fd07b3956b43aed8a79e9edce980" -"checksum core-foundation-sys 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "716c271e8613ace48344f723b60b900a93150271e5be206212d052bbc0883efa" -"checksum core-graphics 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fb0ed45fdc32f9ab426238fba9407dfead7bacd7900c9b4dd3f396f46eafdae3" -"checksum core-text 9.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2bd581c37283d0c23311d179aefbb891f2324ee0405da58a26e8594ab76e5748" -"checksum crossbeam-deque 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f739f8c5363aca78cfb059edf753d8f0d36908c348f3d8d1503f03d8b75d9cf3" -"checksum crossbeam-epoch 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "927121f5407de9956180ff5e936fe3cf4324279280001cd56b669d28ee7e9150" -"checksum crossbeam-utils 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "2760899e32a1d58d5abb31129f8fae5de75220bc2176e77ff7c627ae45c918d9" -"checksum cssparser 0.23.2 (registry+https://github.com/rust-lang/crates.io-index)" = "8a807ac3ab7a217829c2a3b65732b926b2befe6a35f33b4bf8b503692430f223" -"checksum cssparser-macros 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "079adec4af52bb5275eadd004292028c79eb3c5f5b4ee8086a36d4197032f6df" -"checksum cstr 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "b84061a2fd1af9319e98f733dc1ede67e0b208c455f17f1aa445cc8f4d0e635c" -"checksum cstr-macros 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f9f316203d1ea36f4f18316822806f6999aa3dc5ed1adf51e35b77e3b3933d78" -"checksum darling 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d3effd06d4057f275cb7858889f4952920bab78dd8ff0f6e7dfe0c8d2e67ed89" -"checksum darling_core 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "167dd3e235c2f1da16a635c282630452cdf49191eb05711de1bcd1d3d5068c00" -"checksum darling_macro 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c53edaba455f6073a10c27c72440860eb3f60444f8c8660a391032eeae744d82" -"checksum dbghelp-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "97590ba53bcb8ac28279161ca943a924d1fd4a8fb3fa63302591647c4fc5b850" -"checksum dbus 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)" = "acd824d45fad5ff0e178fcb3c040f13780e73f63a0a6d5cde59e7894f251ab0e" -"checksum debug_unreachable 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "9a032eac705ca39214d169f83e3d3da290af06d8d1d344d1baad2fd002dca4b3" -"checksum deflate 0.7.5 (registry+https://github.com/rust-lang/crates.io-index)" = "ebb02aaf4b775afc96684b8402510a338086974e38570a1f65bea8c202eb77a7" -"checksum device 0.0.1 (git+https://github.com/servo/devices)" = "" -"checksum dlib 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "77e51249a9d823a4cb79e3eca6dcd756153e8ed0157b6c04775d04bf1b13b76a" -"checksum dtoa 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "80c8b71fd71146990a9742fc06dcbbde19161a267e0ad4e572c35162f4578c90" -"checksum dtoa-short 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fe6f727b406462fd57c95fed84d1b0dbfb5f0136fcac005adba9ea0367c05cc8" -"checksum dwrote 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "b26e30aaa6bf31ec830db15fec14ed04f0f2ecfcc486ecfce88c55d3389b237f" -"checksum either 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "18785c1ba806c258137c937e44ada9ee7e69a37e3c72077542cd2f069d78562a" -"checksum encoding_rs 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "f5215aabf22b83153be3ee44dfe3f940214541b2ce13d419c55e7a115c8c51a9" -"checksum energy-monitor 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fe872d0664f1cc60db36349af245d892ee67d3c8f78055df0ebc43271fd4e05c" -"checksum energymon 0.3.0 (git+https://github.com/energymon/energymon-rust.git)" = "" -"checksum energymon-builder 0.3.0 (git+https://github.com/energymon/energymon-sys.git)" = "" -"checksum energymon-default-sys 0.3.0 (git+https://github.com/energymon/energymon-sys.git)" = "" -"checksum energymon-sys 0.3.0 (git+https://github.com/energymon/energymon-sys.git)" = "" -"checksum enum_primitive 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "be4551092f4d519593039259a9ed8daedf0da12e5109c5280338073eaeb81180" -"checksum env_logger 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)" = "0561146661ae44c579e993456bc76d11ce1e0c7d745e57b2fa7146b6e49fa2ad" -"checksum error-chain 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ff511d5dc435d703f4971bc399647c9bc38e20cb41452e3b9feb4765419ed3f3" -"checksum euclid 0.17.2 (registry+https://github.com/rust-lang/crates.io-index)" = "adfe67a9343519c1449d208da5998c6de582de698f7a39c4ac82ffba23d131a5" -"checksum expat-sys 2.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "c470ccb972f2088549b023db8029ed9da9426f5affbf9b62efff7009ab8ed5b1" -"checksum flate2 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "9fac2277e84e5e858483756647a9d0aa8d9a2b7cba517fd84325a0aaa69a0909" -"checksum fnv 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "6cc484842f1e2884faf56f529f960cc12ad8c71ce96cc7abba0a067c98fee344" -"checksum fontsan 0.4.0 (git+https://github.com/servo/fontsan)" = "" -"checksum foreign-types 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1" -"checksum foreign-types-shared 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" -"checksum freetype 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "398b8a11884898184d55aca9806f002b3cf68f0e860e0cbb4586f834ee39b0e7" -"checksum fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "2e9763c69ebaae630ba35f74888db465e49e259ba1bc0eda7d06f4a067615d82" -"checksum fuchsia-zircon-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "3dcaa9ae7725d12cdb85b3ad99a434db70b468c09ded17e012d86b5c1010f7a7" -"checksum futf 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "51f93f3de6ba1794dcd5810b3546d004600a59a98266487c8407bc4b24e398f3" -"checksum fxhash 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "c31b6d751ae2c7f11320402d34e41349dd1016f8d5d45e48c4312bc8625af50c" -"checksum gaol 0.0.1 (git+https://github.com/servo/gaol)" = "" -"checksum gdi32-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0912515a8ff24ba900422ecda800b52f4016a56251922d397c576bf92c690518" -"checksum getopts 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)" = "d9047cfbd08a437050b363d35ef160452c5fe8ea5187ae0a624708c91581d685" -"checksum gif 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)" = "8a80d6fe9e52f637df9afd4779449a7be17c39cc9c35b01589bb833f956ba596" -"checksum gl_generator 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7a795170cbd85b5a7baa58d6d7525cae6a03e486859860c220f7ebbbdd379d0a" -"checksum gleam 0.4.29 (registry+https://github.com/rust-lang/crates.io-index)" = "b74def65dc2902b459fc7dd258b10695130408b79fd8f8beb59f475b1536ed81" -"checksum glob 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "8be18de09a56b60ed0edf84bc9df007e30040691af7acd1c41874faac5895bfb" -"checksum glutin 0.13.1 (registry+https://github.com/rust-lang/crates.io-index)" = "90de8e0391e57098acfbfe693b23065e9186255d370ebae12c933b7d77df8424" -"checksum glx 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "63a6e7c2846e12626455f45ebaff9d92161436dd0fa703d9d198012e528ca7b9" -"checksum gvr-sys 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b1334b94d8ce67319ddc44663daef53d8c1538629a11562530c981dbd9085b9a" -"checksum half 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "63d68db75012a85555434ee079e7e6337931f87a087ab2988becbadf64673a7f" -"checksum harfbuzz-sys 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)" = "52aa65c5649a0a2f1b27ab30093b3cc84681e17ddb552267e21948c5a6fa6b05" -"checksum heartbeats-simple 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9ad003ce233955e9d95f2c69cde84e68302ba9ba4a673d351c9bff93c738aadc" -"checksum heartbeats-simple-sys 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "e1a408c0011427cc0e0049f7861c70377819aedfc006e8c901b1c70fd98fb1a4" -"checksum histogram 0.6.8 (registry+https://github.com/rust-lang/crates.io-index)" = "1bdcec4094c1ca961b685384ea7af76af5718230b3f34657d1a71fd2dcf4cc9d" -"checksum html5ever 0.22.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e579ac8647178ab915d400d7d22938bda5cd351c6c62e1c294d56884ccfc75fe" -"checksum httparse 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a6e7a63e511f9edffbab707141fbb8707d1a3098615fb2adbd5769cdfcc9b17d" -"checksum humantime 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0484fda3e7007f2a4a0d9c3a703ca38c71c54c55602ce4660c419fd32e188c9e" -"checksum hyper 0.10.13 (registry+https://github.com/rust-lang/crates.io-index)" = "368cb56b2740ebf4230520e2b90ebb0461e69034d85d1945febd9b3971426db2" -"checksum hyper-openssl 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "85a372eb692590b3fe014c196c30f9f52d4c42f58cd49dd94caeee1593c9cc37" -"checksum hyper_serde 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0997ad463f64ce6ba02cf5af320622bb9782e4f8355b650a2cc7ccca69a7cc2e" -"checksum ident_case 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3c9826188e666f2ed92071d2dadef6edc430b11b158b5b2b3f4babbcc891eaaa" -"checksum idna 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "014b298351066f1512874135335d62a789ffe78a9974f94b43ed5621951eaf7d" -"checksum image 0.18.0 (registry+https://github.com/rust-lang/crates.io-index)" = "545f000e8aa4e569e93f49c446987133452e0091c2494ac3efd3606aa3d309f2" -"checksum immeta 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "1aaaa557fbc7323c857871ce15f2b2c08d90548cba4aabda4251fac1b4778337" -"checksum inflate 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "10ec05638adf7c5c788bc0cfa608cd479a13572beda20feb4898fe1d85d2c64b" -"checksum influent 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a22b311b83431be3ab9af96ca9ea41554bb4a8551ea871ae44c3ce0c57e55f2c" -"checksum io-surface 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "623ace1e5f7de3512ec45302572a72349fdadcbef650c3dfc5d8244209be7653" -"checksum iovec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "dbe6e417e7d0975db6512b90796e8ce223145ac4e33c377e4a42882a0e88bb08" -"checksum ipc-channel 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "db9daf099728ac5390c73f54e6e3708f0c514d2b51f24373830f568702eadfca" -"checksum itertools 0.7.6 (registry+https://github.com/rust-lang/crates.io-index)" = "b07332223953b5051bceb67e8c4700aa65291535568e1f12408c43c4a42c0394" -"checksum itoa 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "eb2f404fbc66fd9aac13e998248505e7ecb2ad8e44ab6388684c5fb11c6c251c" -"checksum jemalloc-sys 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "479294d130502fada93c7a957e8d059b632b03d6204aca37af557dee947f30a9" -"checksum jemallocator 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "28b211ca65c440322b6d4d9b5b850b01e8e298393b7ebcb8205b7cbb14ea6329" -"checksum jpeg-decoder 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)" = "0dfe27a6c0dabd772d0f9b9f8701c4ca12c4d1eebcadf2be1f6f70396f6a1434" -"checksum kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d" -"checksum khronos_api 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d9ef23fcc4059260c5936f638c9805ebfc87cb172fa6661d130cba7f97d58f55" -"checksum language-tags 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "a91d884b6667cd606bb5a69aa0c99ba811a115fc68915e7056ec08a46e93199a" -"checksum lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c8f31047daa365f19be14b47c29df4f7c3b581832407daabe6ae77397619237d" -"checksum lazycell 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a6f08839bc70ef4a3fe1d566d5350f519c5912ea86be0df1740a7d247c7fc0ef" -"checksum leak 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "bd100e01f1154f2908dfa7d02219aeab25d0b9c7fa955164192e3245255a0c73" -"checksum leaky-cow 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "40a8225d44241fd324a8af2806ba635fc7c8a7e9a7de4d5cf3ef54e71f5926fc" -"checksum libc 0.2.39 (registry+https://github.com/rust-lang/crates.io-index)" = "f54263ad99207254cf58b5f701ecb432c717445ea2ee8af387334bdd1a03fdff" -"checksum libdbus-sys 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "8720f9274907052cb50313f91201597868da9d625f8dd125f2aca5bddb7e83a1" -"checksum libloading 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9c3ad660d7cb8c5822cd83d10897b0f1f1526792737a179e73896152f85b88c2" -"checksum libz-sys 1.0.18 (registry+https://github.com/rust-lang/crates.io-index)" = "87f737ad6cc6fd6eefe3d9dc5412f1573865bded441300904d2f42269e140f16" -"checksum log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)" = "e19e8d5c34a3e0e2223db8e060f9e8264aeeb5c5fc64a4ee9965c062211c024b" -"checksum log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "89f010e843f2b1a31dbd316b3b8d443758bc634bed37aabade59c686d644e0a2" -"checksum lzw 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7d947cbb889ed21c2a84be6ffbaebf5b4e0f4340638cba0444907e38b56be084" -"checksum mac 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "c41e0c4fef86961ac6d6f8a82609f55f31b05e4fce149ac5710e439df7619ba4" -"checksum malloc_buf 0.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = "62bb907fe88d54d8d9ce32a3cceab4218ed2f6b7d35617cafe9adf84e43919cb" -"checksum markup5ever 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "c220b3a3d75543b76e5c1fcab6635a8430ab5f9bfa011d003c3787ae0abf4ffa" -"checksum matches 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "efd7622e3022e1a6eaa602c4cea8912254e5582c9c692e9167714182244801b1" -"checksum memchr 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "1dbccc0e46f1ea47b9f17e6d67c5a96bd27030519c519c9c91327e31275a47b4" -"checksum memmap 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e2ffa2c986de11a9df78620c01eeaaf27d94d3ff02bf81bfcca953102dd0c6ff" -"checksum memoffset 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0f9dc261e2b62d7a622bf416ea3c5245cdd5d9a7fcc428c0d06804dfce1775b3" -"checksum mime 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)" = "9d69889cdc6336ed56b174514ce876c4c3dc564cc23dd872e7bca589bb2a36c8" -"checksum mime_guess 1.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "76da6df85047af8c0edfa53f48eb1073012ce1cc95c8fedc0a374f659a89dd65" -"checksum miniz-sys 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)" = "609ce024854aeb19a0ef7567d348aaa5a746b32fb72e336df7fcc16869d7e2b4" -"checksum mio 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)" = "75f72a93f046f1517e3cfddc0a096eb756a2ba727d36edc8227dee769a50a9b0" -"checksum miow 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "8c1f2f3b1cf331de6896aabf6e9d55dca90356cc9960cca7eaaf408a355ae919" -"checksum mitochondria 1.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "9de3eca27871df31c33b807f834b94ef7d000956f57aa25c5aed9c5f0aae8f6f" -"checksum mozangle 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "1f0583e6792917f498bb3a7440f777a59353102063445ab7f5e9d1dc4ed593aa" -"checksum mozjs 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "469f86d1ce125f1a9960e9f5f924388e47b58ac6bf7525f8f98fdc1160decf58" -"checksum mozjs_sys 0.50.1 (registry+https://github.com/rust-lang/crates.io-index)" = "e61a792a125b1364c5ec50255ed8343ce02dc56098f8868dd209d472c8de006a" -"checksum mp3-metadata 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4ab5f1d2693586420208d1200ce5a51cd44726f055b635176188137aff42c7de" -"checksum mp4parse 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)" = "f821e3799bc0fd16d9b861fb02fa7ee1b5fba29f45ad591dade105c48ca9a1a0" -"checksum net2 0.2.29 (registry+https://github.com/rust-lang/crates.io-index)" = "bc01404e7568680f1259aa5729539f221cb1e6d047a0d9053cab4be8a73b5d67" -"checksum nodrop 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)" = "9a2228dca57108069a5262f2ed8bd2e82496d2e074a06d1ccc7ce1687b6ae0a2" -"checksum nom 1.2.4 (registry+https://github.com/rust-lang/crates.io-index)" = "a5b8c256fd9471521bcb84c3cdba98921497f1a331cbc15b8030fc63b82050ce" -"checksum num 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)" = "98b15ba84e910ea7a1973bccd3df7b31ae282bf9d8bd2897779950c9b8303d40" -"checksum num-integer 0.1.34 (registry+https://github.com/rust-lang/crates.io-index)" = "ef1a4bf6f9174aa5783a9b4cc892cacd11aebad6c69ad027a0b65c6ca5f8aa37" -"checksum num-iter 0.1.33 (registry+https://github.com/rust-lang/crates.io-index)" = "f7d1891bd7b936f12349b7d1403761c8a0b85a18b148e9da4429d5d102c1a41e" -"checksum num-rational 0.1.36 (registry+https://github.com/rust-lang/crates.io-index)" = "c2dc5ea04020a8f18318ae485c751f8cfa1c0e69dcf465c29ddaaa64a313cc44" -"checksum num-traits 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)" = "e1cbfa3781f3fe73dc05321bed52a06d2d491eaa764c52335cf4399f046ece99" -"checksum num_cpus 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ca313f1862c7ec3e0dfe8ace9fa91b1d9cb5c84ace3d00f5ec4216238e93c167" -"checksum objc 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "877f30f37acef6749b1841cceab289707f211aecfc756553cd63976190e6cc2e" -"checksum objc-foundation 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "1add1b659e36c9607c7aab864a76c7a4c2760cd0cd2e120f3fb8b952c7e22bf9" -"checksum objc_id 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e4730aa1c64d722db45f7ccc4113a3e2c465d018de6db4d3e7dfe031e8c8a297" -"checksum offscreen_gl_context 0.15.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b0daacb4e8c5760ab0addb80938f6bde4cd23b71b39a84d90080ae0c7215716a" -"checksum ogg 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7137bf02687385302f4c0aecd77cfce052b69f5b4ee937be778e125c62f67e30" -"checksum ogg_metadata 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "fc665717454399cba557c55ad226148996e9266ee291f8a37a98bb2cded0a490" -"checksum openssl 0.9.24 (registry+https://github.com/rust-lang/crates.io-index)" = "a3605c298474a3aa69de92d21139fb5e2a81688d308262359d85cdd0d12a7985" -"checksum openssl-sys 0.9.27 (registry+https://github.com/rust-lang/crates.io-index)" = "d6fdc5c4a02e69ce65046f1763a0181107038e02176233acb0b3351d7cc588f9" -"checksum ordered-float 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "da12c96037889ae0be29dd2bdd260e5a62a7df24e6466d5a15bb8131c1c200a8" -"checksum osmesa-src 17.3.1-devel (git+https://github.com/servo/osmesa-src)" = "" -"checksum osmesa-sys 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "88cfece6e95d2e717e0872a7f53a8684712ad13822a7979bc760b9c77ec0013b" -"checksum ovr-mobile-sys 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a69b517feac6fc640f0679625defa0998bbcb32871a6901e63063c2abf9c4cbe" -"checksum owning_ref 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "cdf84f41639e037b484f93433aa3897863b561ed65c6e59c7073d7c561710f37" -"checksum parking_lot 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)" = "9fd9d732f2de194336fb02fe11f9eed13d9e76f13f4315b4d88a14ca411750cd" -"checksum parking_lot_core 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)" = "538ef00b7317875071d5e00f603f24d16f0b474c1a5fc0ccb8b454ca72eafa79" -"checksum peeking_take_while 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "19b17cddbe7ec3f8bc800887bab5e717348c95ea2ca0b1bf0837fb964dc67099" -"checksum percent-encoding 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "de154f638187706bde41d9b4738748933d64e6b37bdbffc0b47a97d16a6ae356" -"checksum phf 0.7.21 (registry+https://github.com/rust-lang/crates.io-index)" = "cb325642290f28ee14d8c6201159949a872f220c62af6e110a56ea914fbe42fc" -"checksum phf_codegen 0.7.21 (registry+https://github.com/rust-lang/crates.io-index)" = "d62594c0bb54c464f633175d502038177e90309daf2e0158be42ed5f023ce88f" -"checksum phf_generator 0.7.21 (registry+https://github.com/rust-lang/crates.io-index)" = "6b07ffcc532ccc85e3afc45865469bf5d9e4ef5bfcf9622e3cfe80c2d275ec03" -"checksum phf_shared 0.7.21 (registry+https://github.com/rust-lang/crates.io-index)" = "07e24b0ca9643bdecd0632f2b3da6b1b89bbb0030e0b992afc1113b23a7bc2f2" -"checksum pkg-config 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)" = "3a8b4c6b8165cd1a1cd4b9b120978131389f64bdaf456435caa41e630edba903" -"checksum plane-split 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "69c557e11e3a1533bc969fa596e5011e1d9f76dd61cd102ef942c9f8654b17a2" -"checksum png 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f0b0cabbbd20c2d7f06dbf015e06aad59b6ca3d9ed14848783e98af9aaf19925" -"checksum precomputed-hash 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "925383efa346730478fb4838dbe9137d2a47675ad789c546d150a6e1dd4ab31c" -"checksum proc-macro2 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "d1cb7aaaa4bf022ec2b14ff2f2ba1643a22f3cee88df014a85e14b392282c61d" -"checksum procedural-masquerade 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "c93cdc1fb30af9ddf3debc4afbdb0f35126cbd99daa229dd76cdd5349b41d989" -"checksum quick-error 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "eda5fe9b71976e62bc81b781206aaa076401769b2143379d3eb2118388babac4" -"checksum quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)" = "7a6e920b65c65f10b2ae65c831a81a073a89edd28c7cce89475bff467ab4167a" -"checksum quote 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "1eca14c727ad12702eb4b6bfb5a232287dcf8385cb8ca83a3eeaf6519c44c408" -"checksum rand 0.3.22 (registry+https://github.com/rust-lang/crates.io-index)" = "15a732abf9d20f0ad8eeb6f909bf6868722d9a06e1e50802b6a70351f40b4eb1" -"checksum rand 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "eba5f8cb59cc50ed56be8880a5c7b496bfd9bd26394e176bc67884094145c2c5" -"checksum rayon 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "485541959c8ecc49865526fe6c4de9653dd6e60d829d6edf0be228167b60372d" -"checksum rayon-core 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9d24ad214285a7729b174ed6d3bcfcb80177807f959d95fafd5bfc5c4f201ac8" -"checksum redox_syscall 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)" = "29dbdfd4b9df8ab31dec47c6087b7b13cbf4a776f335e4de8efba8288dda075b" -"checksum redox_termios 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7e891cfe48e9100a70a3b6eb652fef28920c117d366339687bd5576160db0f76" -"checksum ref_filter_map 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2b5ceb840e4009da4841ed22a15eb49f64fdd00a2138945c5beacf506b2fb5ed" -"checksum ref_slice 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "825740057197b7d43025e7faf6477eaabc03434e153233da02d1f44602f71527" -"checksum regex 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "1731164734096285ec2a5ec7fea5248ae2f5485b3feeb0115af4fda2183b2d1b" -"checksum regex-syntax 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ad890a5eef7953f55427c50575c680c42841653abd2b028b68cd223d157f62db" -"checksum ron 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "da06feaa07f69125ab9ddc769b11de29090122170b402547f64b86fe16ebc399" -"checksum rust-webvr 0.9.10 (registry+https://github.com/rust-lang/crates.io-index)" = "9629ce5b5c3cda05259d225e639851daf39c55c170358d3056205dd205deaab2" -"checksum rust-webvr-api 0.9.2 (registry+https://github.com/rust-lang/crates.io-index)" = "712e22ba3c03a7075b40842ae91029a0ab96a81f95e97c0cf623800ec0cbac07" -"checksum rustc-demangle 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "3058a43ada2c2d0b92b3ae38007a2d0fa5e9db971be260e0171408a4ff471c95" -"checksum rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)" = "dcf128d1287d2ea9d80910b5f1120d0b8eede3fbf1abe91c40d39ea7d51e6fda" -"checksum rustc_version 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "c5f5376ea5e30ce23c03eb77cbe4962b988deead10910c372b226388b594c084" -"checksum safemem 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e27a8b19b835f7aea908818e871f5cc3a5a186550c30773be987e155e8163d8f" -"checksum same-file 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "cfb6eded0b06a0b512c8ddbcf04089138c9b4362c2f696f3c3d76039d68f3637" -"checksum scoped_threadpool 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "3ef399c8893e8cb7aa9696e895427fab3a6bf265977bb96e126f24ddd2cda85a" -"checksum scopeguard 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "c79eb2c3ac4bc2507cda80e7f3ac5b88bd8eae4c0914d5663e6a8933994be918" -"checksum semver 0.1.20 (registry+https://github.com/rust-lang/crates.io-index)" = "d4f410fedcf71af0345d7607d246e7ad15faaadd49d240ee3b24e5dc21a820ac" -"checksum serde 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)" = "db99f3919e20faa51bb2996057f5031d8685019b5a06139b1ce761da671b8526" -"checksum serde_bytes 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7a73f5ad9bb83e1e407254c7a355f4efdaffe3c1442fc0657ddb8b9b6b225655" -"checksum serde_derive 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)" = "f4ba7591cfe93755e89eeecdbcc668885624829b020050e6aec99c2a03bd3fd0" -"checksum serde_derive_internals 0.19.0 (registry+https://github.com/rust-lang/crates.io-index)" = "6e03f1c9530c3fb0a0a5c9b826bdd9246a5921ae995d75f512ac917fc4dd55b5" -"checksum serde_json 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "48b04779552e92037212c3615370f6bd57a40ebba7f20e554ff9f55e41a69a7b" -"checksum servo-egl 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "21069a884c33fe6ee596975e1f3849ed88c4ec857fbaf11d33672d8ebe051217" -"checksum servo-fontconfig 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "93f799b649b4a2bf362398910eca35240704c7e765e780349b2bb1070d892262" -"checksum servo-fontconfig-sys 4.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "38b494f03009ee81914b0e7d387ad7c145cafcd69747c2ec89b0e17bb94f303a" -"checksum servo-freetype-sys 4.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "9232032c2e85118c0282c6562c84cab12316e655491ba0a5d1905b2320060d1b" -"checksum servo-skia 0.30000013.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3fb707c7dc3d8a053b8c9d48ed9eb7f2a0c0751616dfbe3598f526948408bc33" -"checksum servo-websocket 0.21.0 (registry+https://github.com/rust-lang/crates.io-index)" = "6bac1e2295e72f0525147d993c626761811acf0441dac1cee8707f12dc7f3363" -"checksum sha1 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "cc30b1e1e8c40c121ca33b86c23308a090d19974ef001b4bf6e61fd1a0fb095c" -"checksum shared_library 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "8254bf098ce4d8d7cc7cc6de438c5488adc5297e5b7ffef88816c0a91bd289c1" -"checksum sig 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "c6649e43c1a1e68d29ed56d0dc3b5b6cf3b901da77cf107c4066b9e3da036df5" -"checksum signpost 0.1.0 (git+https://github.com/pcwalton/signpost.git)" = "" -"checksum simd 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7a94d14a2ae1f1f110937de5fb69e494372560181c7e1739a097fcc2cee37ba0" -"checksum siphasher 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "0df90a788073e8d0235a67e50441d47db7c8ad9debd91cbf43736a2a92d36537" -"checksum slab 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "17b4fcaed89ab08ef143da37bc52adbcc04d4a69014f4c1208d6b51f0c47bc23" -"checksum smallbitvec 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "665fbc8384f961eb55c548daa2a4b1efff1f9d03b7a10f162ac6ad6a781ca966" -"checksum smallvec 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "44db0ecb22921ef790d17ae13a3f6d15784183ff5f2a01aa32098c7498d2b4b9" -"checksum stable_deref_trait 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "15132e0e364248108c5e2c02e3ab539be8d6f5d52a01ca9bbf27ed657316f02b" -"checksum string_cache 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "39cb4173bcbd1319da31faa5468a7e3870683d7a237150b0b0aaafd546f6ad12" -"checksum string_cache_codegen 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "479cde50c3539481f33906a387f2bd17c8e87cb848c35b6021d41fb81ff9b4d7" -"checksum string_cache_shared 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b1884d1bc09741d466d9b14e6d37ac89d6909cbcac41dd9ae982d4d063bbedfc" -"checksum strsim 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b4d15c810519a91cf877e7e36e63fe068815c678181439f2f29e2562147c3694" -"checksum swapper 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e454d048db5527d000bfddb77bd072bbf3a1e2ae785f16d9bd116e07c2ab45eb" -"checksum syn 0.11.11 (registry+https://github.com/rust-lang/crates.io-index)" = "d3b891b9015c88c576343b9b3e41c2c11a51c219ef067b264bd9c8aa9b441dad" -"checksum syn 0.12.12 (registry+https://github.com/rust-lang/crates.io-index)" = "9e1c669ed757c0ebd04337f6a5bb972d05e0c08fe2540dd3ee3dd9e4daf1604c" -"checksum synom 0.11.3 (registry+https://github.com/rust-lang/crates.io-index)" = "a393066ed9010ebaed60b9eafa373d4b1baac186dd7e008555b0f702b51945b6" -"checksum synstructure 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "010366096045d8250555904c58da03377289e7f4b2ce7a5b1027e2b532f41000" -"checksum tempfile 2.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "11ce2fe9db64b842314052e2421ac61a73ce41b898dc8e3750398b219c5fc1e0" -"checksum tendril 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9de21546595a0873061940d994bbbc5c35f024ae4fd61ec5c5b159115684f508" -"checksum termcolor 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "adc4587ead41bf016f11af03e55a624c06568b5a19db4e90fde573d805074f83" -"checksum termion 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "689a3bdfaab439fd92bc87df5c4c78417d3cbe537487274e9b0b2dce76e92096" -"checksum textwrap 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c0b59b6b4b44d867f1370ef1bd91bfb262bf07bf0ae65c202ea2fbc16153b693" -"checksum thread-id 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8df7875b676fddfadffd96deea3b1124e5ede707d4884248931077518cf1f773" -"checksum thread_local 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "c85048c6260d17cf486ceae3282d9fb6b90be220bf5b28c400f5485ffc29f0c7" -"checksum thread_profiler 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "5920e77802b177479ab5795767fa48e68f61b2f516c2ac0041e2978dd8efe483" -"checksum threadpool 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "59f6d3eff89920113dac9db44dde461d71d01e88a5b57b258a0466c32b5d7fe1" -"checksum time 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)" = "ffd7ccbf969a892bf83f1e441126968a07a3941c24ff522a26af9f9f4585d1a3" -"checksum tinyfiledialogs 3.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "d79833ca2c493c726ea6a7b651ba0ff8a790add5156cd11bf3743f346005c0c8" -"checksum token_store 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "a686838375fc11103b9c1529c6508320b7bd5e2401cd62831ca51b3e82e61849" -"checksum toml 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)" = "a7540f4ffc193e0d3c94121edb19b055670d369f77d5804db11ae053a45b6e7e" -"checksum traitobject 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "efd1f82c56340fdf16f2a953d7bda4f8fdffba13d93b00844c25572110b26079" -"checksum truetype 0.26.0 (registry+https://github.com/rust-lang/crates.io-index)" = "acec30350633d6dac9dc1a625786b6cbe9150664be941aac2c35ad7199eab877" -"checksum typeable 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "1410f6f91f21d1612654e7cc69193b0334f909dcf2c790c4826254fbb86f8887" -"checksum uluru 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "519130f0ea964ba540a9d8af1373738c2226f1d465eda07e61db29feb5479db9" -"checksum unicase 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "13a5906ca2b98c799f4b1ab4557b76367ebd6ae5ef14930ec841c74aed5f3764" -"checksum unicode-bidi 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "a6a2c4e3710edd365cd7e78383153ed739fa31af19f9172f72d3575060f5a43a" -"checksum unicode-normalization 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "51ccda9ef9efa3f7ef5d91e8f9b83bbe6955f9bf86aec89d5cce2c874625920f" -"checksum unicode-script 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "e5430ae21ef212551680d0021fc7dbd936e8b268c5ea8fdae8814e0b2496d80f" -"checksum unicode-segmentation 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a8083c594e02b8ae1654ae26f0ade5158b119bd88ad0e8227a5d8fcd72407946" -"checksum unicode-width 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "bf3a113775714a22dcb774d8ea3655c53a32debae63a063acc00a91cc586245f" -"checksum unicode-xid 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "8c1f860d7d29cf02cb2f3f359fd35991af3d30bac52c57d265a3c461074cb4dc" -"checksum unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fc72304796d0818e357ead4e000d19c9c174ab23dc11093ac919054d20a6a7fc" -"checksum unreachable 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "1f2ae5ddb18e1c92664717616dd9549dde73f539f01bd7b77c2edb2446bdff91" -"checksum url 1.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fa35e768d4daf1d85733418a49fb42e10d7f633e394fccab4ab7aba897053fe2" -"checksum url_serde 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "74e7d099f1ee52f823d4bdd60c93c3602043c728f5db3b97bdb548467f7bddea" -"checksum user32-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4ef4711d107b21b410a3a974b1204d9accc8b10dad75d8324b5d755de1617d47" -"checksum utf-8 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b6f923c601c7ac48ef1d66f7d5b5b2d9a7ba9c51333ab75a3ddf8d0309185a56" -"checksum utf8-ranges 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "662fab6525a98beff2921d7f61a39e7d59e0b425ebc7d0d9e66d316e55124122" -"checksum uuid 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "d4670e1e935f7edd193a413f802e2ee52274aed62a09ccaab1656515c9c53a66" -"checksum vcpkg 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "9e0a7d8bed3178a8fb112199d466eeca9ed09a14ba8ad67718179b4fd5487d0b" -"checksum vec_map 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "887b5b631c2ad01628bbbaa7dd4c869f80d3186688f8d0b6f58774fbe324988c" -"checksum void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d" -"checksum walkdir 2.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "63636bd0eb3d00ccb8b9036381b526efac53caf112b7783b730ab3f8e44da369" -"checksum wayland-client 0.12.5 (registry+https://github.com/rust-lang/crates.io-index)" = "2b90adf943117ee4930d7944fe103dcb6f36ba05421f46521cb5adbf6bf0fbc8" -"checksum wayland-kbd 0.13.1 (registry+https://github.com/rust-lang/crates.io-index)" = "4fe0fb1c9917da9529d781659e456d84a693d74fe873d1658109758444616f76" -"checksum wayland-protocols 0.12.5 (registry+https://github.com/rust-lang/crates.io-index)" = "fb5942dd2fc79d934db437c9ea3aabffceb49b546046ea453bcba531005e5537" -"checksum wayland-scanner 0.12.5 (registry+https://github.com/rust-lang/crates.io-index)" = "dcffa55a621e6f2c3d436de64d840fc325e1d0a467b92ee5e7292e17552e08ad" -"checksum wayland-sys 0.12.5 (registry+https://github.com/rust-lang/crates.io-index)" = "377a2f83063c463e801ca10ae8cb9666e6e597eecac0049ac36cc7b9a83b0db3" -"checksum wayland-window 0.13.2 (registry+https://github.com/rust-lang/crates.io-index)" = "2d94d3c23f8f2e0a09d82c6ca765da3c1efe65ef0280f750d74a6c6c6bb4ca8f" -"checksum webdriver 0.33.0 (registry+https://github.com/rust-lang/crates.io-index)" = "6577005cf83a9df4ba39910f8baf3b835b5e4a0a5e9a0d71f3eceae6214ebf28" -"checksum webrender 0.57.0 (git+https://github.com/servo/webrender)" = "" -"checksum webrender_api 0.57.0 (git+https://github.com/servo/webrender)" = "" -"checksum which 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "4be6cfa54dab45266e98b5d7be2f8ce959ddd49abd141a05d52dce4b07f803bb" -"checksum winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "167dc9d6949a9b857f3451275e911c3f44255842c1f7a76f33c55103a909087a" -"checksum winapi 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "b09fb3b6f248ea4cd42c9a65113a847d612e17505d6ebd1f7357ad68a8bf8693" -"checksum winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2d315eee3b34aca4797b2da6b13ed88266e6d612562a0c46390af8299fc699bc" -"checksum winapi-i686-pc-windows-gnu 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "ec6667f60c23eca65c561e63a13d81b44234c2e38a6b6c959025ee907ec614cc" -"checksum winapi-x86_64-pc-windows-gnu 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "98f12c52b2630cd05d2c3ffd8e008f7f48252c042b4871c72aed9dc733b96668" -"checksum wincolor 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "eeb06499a3a4d44302791052df005d5232b927ed1a9658146d842165c4de7767" -"checksum winit 0.11.3 (registry+https://github.com/rust-lang/crates.io-index)" = "f1a29847ed6928d6cbabe6b2d5b11dd0ce63380af53a8dcd41775d27d104d285" -"checksum winres 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "27d9192d6356d7efe8405dec6c5506b67543cf64b6049968f39f4c4623b4f25d" -"checksum ws 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)" = "89c48c53bf9dee34411a08993c10b879c36e105d609b46e25673befe3a5c1320" -"checksum ws2_32-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d59cefebd0c892fa2dd6de581e937301d8552cb44489cdff035c6187cb63fa5e" -"checksum x11 2.17.3 (registry+https://github.com/rust-lang/crates.io-index)" = "7e5c4ac579b5d324dc4add02312b5d0e3e0218521e2d5779d526ac39ee4bb171" -"checksum x11-clipboard 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "2e7374c7699210cca7084ca61d57e09640fc744d1391808cb9ae2fe4ca9bd1df" -"checksum x11-dl 2.17.3 (registry+https://github.com/rust-lang/crates.io-index)" = "29e78a65a3239e5511ffe2c832edb9224982ebf67bcaabc218ef1b07d8494b3e" -"checksum xcb 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)" = "5e917a3f24142e9ff8be2414e36c649d47d6cc2ba81f16201cdef96e533e02de" -"checksum xdg 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a66b7c2281ebde13cf4391d70d4c7e5946c3c25e72a7b859ca8f677dcd0b0c61" -"checksum xi-unicode 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "12ea8eda4b1eb72f02d148402e23832d56a33f55d8c1b2d5bcdde91d79d47cb1" -"checksum xml-rs 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3c1cb601d29fe2c2ac60a2b2e5e293994d87a1f6fa9687a31a15270f909be9c2" -"checksum xml5ever 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ead952cf8bab253fb5cb56e1fff780747bbf7a7258fb0451afe645a166050b1f" diff --git a/servo/Cargo.toml b/servo/Cargo.toml deleted file mode 100644 index 55ee0c37e775..000000000000 --- a/servo/Cargo.toml +++ /dev/null @@ -1,30 +0,0 @@ -[workspace] -members = [ - "ports/servo", - "tests/unit/*", - - "ports/geckolib", - "ports/geckolib/tests", -] -default-members = [ - "ports/servo", - "tests/unit/*", -] -exclude = [".cargo"] - -[profile.release] -opt-level = 3 -# Uncomment to profile on Linux: -# debug = true -# lto = false - -[patch.crates-io] -# If you need to temporarily test Servo with a local fork of some upstream -# crate, add that here. Use the form: -# -# = { path = "/path/to/local/checkout" } -# -# Or for a git dependency: -# -# [patch."https://github.com/servo/"] -# = { path = "/path/to/local/checkout" } diff --git a/servo/Info.plist b/servo/Info.plist deleted file mode 100644 index ded92bf02676..000000000000 --- a/servo/Info.plist +++ /dev/null @@ -1,28 +0,0 @@ - - - - - CFBundleExecutable - servo - CFBundleGetInfoString - Servo - CFBundleIconFile - servo.icns - CFBundleIdentifier - org.servo.Servo - CFBundleInfoDictionaryVersion - 6.0 - CFBundleName - Servo - CFBundlePackageType - APPL - CFBundleShortVersionString - 0.0.1 - NSHighResolutionCapable - - NSPrincipalClass - NSApplication - NSQuitAlwaysKeepsWindows - - - diff --git a/servo/LICENSE b/servo/LICENSE deleted file mode 100644 index 398385c9fb9b..000000000000 --- a/servo/LICENSE +++ /dev/null @@ -1,374 +0,0 @@ - Mozilla Public License Version 2.0 -================================== - -1. Definitions --------------- - -1.1. "Contributor" -means each individual or legal entity that creates, contributes to -the creation of, or owns Covered Software. - -1.2. "Contributor Version" -means the combination of the Contributions of others (if any) used -by a Contributor and that particular Contributor's Contribution. - -1.3. "Contribution" -means Covered Software of a particular Contributor. - -1.4. "Covered Software" -means Source Code Form to which the initial Contributor has attached -the notice in Exhibit A, the Executable Form of such Source Code -Form, and Modifications of such Source Code Form, in each case -including portions thereof. - -1.5. "Incompatible With Secondary Licenses" -means - -(a) that the initial Contributor has attached the notice described -in Exhibit B to the Covered Software; or - -(b) that the Covered Software was made available under the terms of -version 1.1 or earlier of the License, but not also under the -terms of a Secondary License. - -1.6. "Executable Form" -means any form of the work other than Source Code Form. - -1.7. "Larger Work" -means a work that combines Covered Software with other material, in -a separate file or files, that is not Covered Software. - -1.8. "License" -means this document. - -1.9. "Licensable" -means having the right to grant, to the maximum extent possible, -whether at the time of the initial grant or subsequently, any and -all of the rights conveyed by this License. - -1.10. "Modifications" -means any of the following: - -(a) any file in Source Code Form that results from an addition to, -deletion from, or modification of the contents of Covered -Software; or - -(b) any new file in Source Code Form that contains any Covered -Software. - -1.11. "Patent Claims" of a Contributor -means any patent claim(s), including without limitation, method, -process, and apparatus claims, in any patent Licensable by such -Contributor that would be infringed, but for the grant of the -License, by the making, using, selling, offering for sale, having -made, import, or transfer of either its Contributions or its -Contributor Version. - -1.12. "Secondary License" -means either the GNU General Public License, Version 2.0, the GNU -Lesser General Public License, Version 2.1, the GNU Affero General -Public License, Version 3.0, or any later versions of those -licenses. - -1.13. "Source Code Form" -means the form of the work preferred for making modifications. - -1.14. "You" (or "Your") -means an individual or a legal entity exercising rights under this -License. For legal entities, "You" includes any entity that -controls, is controlled by, or is under common control with You. For -purposes of this definition, "control" means (a) the power, direct -or indirect, to cause the direction or management of such entity, -whether by contract or otherwise, or (b) ownership of more than -fifty percent (50%) of the outstanding shares or beneficial -ownership of such entity. - -2. License Grants and Conditions --------------------------------- - -2.1. Grants - -Each Contributor hereby grants You a world-wide, royalty-free, -non-exclusive license: - -(a) under intellectual property rights (other than patent or trademark) -Licensable by such Contributor to use, reproduce, make available, -modify, display, perform, distribute, and otherwise exploit its -Contributions, either on an unmodified basis, with Modifications, or -as part of a Larger Work; and - -(b) under Patent Claims of such Contributor to make, use, sell, offer -for sale, have made, import, and otherwise transfer either its -Contributions or its Contributor Version. - -2.2. Effective Date - -The licenses granted in Section 2.1 with respect to any Contribution -become effective for each Contribution on the date the Contributor first -distributes such Contribution. - -2.3. Limitations on Grant Scope - -The licenses granted in this Section 2 are the only rights granted under -this License. No additional rights or licenses will be implied from the -distribution or licensing of Covered Software under this License. -Notwithstanding Section 2.1(b) above, no patent license is granted by a -Contributor: - -(a) for any code that a Contributor has removed from Covered Software; -or - -(b) for infringements caused by: (i) Your and any other third party's -modifications of Covered Software, or (ii) the combination of its -Contributions with other software (except as part of its Contributor -Version); or - -(c) under Patent Claims infringed by Covered Software in the absence of -its Contributions. - -This License does not grant any rights in the trademarks, service marks, -or logos of any Contributor (except as may be necessary to comply with -the notice requirements in Section 3.4). - -2.4. Subsequent Licenses - -No Contributor makes additional grants as a result of Your choice to -distribute the Covered Software under a subsequent version of this -License (see Section 10.2) or under the terms of a Secondary License (if -permitted under the terms of Section 3.3). - -2.5. Representation - -Each Contributor represents that the Contributor believes its -Contributions are its original creation(s) or it has sufficient rights -to grant the rights to its Contributions conveyed by this License. - -2.6. Fair Use - -This License is not intended to limit any rights You have under -applicable copyright doctrines of fair use, fair dealing, or other -equivalents. - -2.7. Conditions - -Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted -in Section 2.1. - -3. Responsibilities -------------------- - -3.1. Distribution of Source Form - -All distribution of Covered Software in Source Code Form, including any -Modifications that You create or to which You contribute, must be under -the terms of this License. You must inform recipients that the Source -Code Form of the Covered Software is governed by the terms of this -License, and how they can obtain a copy of this License. You may not -attempt to alter or restrict the recipients' rights in the Source Code -Form. - -3.2. Distribution of Executable Form - -If You distribute Covered Software in Executable Form then: - -(a) such Covered Software must also be made available in Source Code -Form, as described in Section 3.1, and You must inform recipients of -the Executable Form how they can obtain a copy of such Source Code -Form by reasonable means in a timely manner, at a charge no more -than the cost of distribution to the recipient; and - -(b) You may distribute such Executable Form under the terms of this -License, or sublicense it under different terms, provided that the -license for the Executable Form does not attempt to limit or alter -the recipients' rights in the Source Code Form under this License. - -3.3. Distribution of a Larger Work - -You may create and distribute a Larger Work under terms of Your choice, -provided that You also comply with the requirements of this License for -the Covered Software. If the Larger Work is a combination of Covered -Software with a work governed by one or more Secondary Licenses, and the -Covered Software is not Incompatible With Secondary Licenses, this -License permits You to additionally distribute such Covered Software -under the terms of such Secondary License(s), so that the recipient of -the Larger Work may, at their option, further distribute the Covered -Software under the terms of either this License or such Secondary -License(s). - -3.4. Notices - -You may not remove or alter the substance of any license notices -(including copyright notices, patent notices, disclaimers of warranty, -or limitations of liability) contained within the Source Code Form of -the Covered Software, except that You may alter any license notices to -the extent required to remedy known factual inaccuracies. - -3.5. Application of Additional Terms - -You may choose to offer, and to charge a fee for, warranty, support, -indemnity or liability obligations to one or more recipients of Covered -Software. However, You may do so only on Your own behalf, and not on -behalf of any Contributor. You must make it absolutely clear that any -such warranty, support, indemnity, or liability obligation is offered by -You alone, and You hereby agree to indemnify every Contributor for any -liability incurred by such Contributor as a result of warranty, support, -indemnity or liability terms You offer. You may include additional -disclaimers of warranty and limitations of liability specific to any -jurisdiction. - -4. Inability to Comply Due to Statute or Regulation ---------------------------------------------------- - -If it is impossible for You to comply with any of the terms of this -License with respect to some or all of the Covered Software due to -statute, judicial order, or regulation then You must: (a) comply with -the terms of this License to the maximum extent possible; and (b) -describe the limitations and the code they affect. Such description must -be placed in a text file included with all distributions of the Covered -Software under this License. Except to the extent prohibited by statute -or regulation, such description must be sufficiently detailed for a -recipient of ordinary skill to be able to understand it. - -5. Termination --------------- - -5.1. The rights granted under this License will terminate automatically -if You fail to comply with any of its terms. However, if You become -compliant, then the rights granted under this License from a particular -Contributor are reinstated (a) provisionally, unless and until such -Contributor explicitly and finally terminates Your grants, and (b) on an -ongoing basis, if such Contributor fails to notify You of the -non-compliance by some reasonable means prior to 60 days after You have -come back into compliance. Moreover, Your grants from a particular -Contributor are reinstated on an ongoing basis if such Contributor -notifies You of the non-compliance by some reasonable means, this is the -first time You have received notice of non-compliance with this License -from such Contributor, and You become compliant prior to 30 days after -Your receipt of the notice. - -5.2. If You initiate litigation against any entity by asserting a patent -infringement claim (excluding declaratory judgment actions, -counter-claims, and cross-claims) alleging that a Contributor Version -directly or indirectly infringes any patent, then the rights granted to -You by any and all Contributors for the Covered Software under Section -2.1 of this License shall terminate. - -5.3. In the event of termination under Sections 5.1 or 5.2 above, all -end user license agreements (excluding distributors and resellers) which -have been validly granted by You or Your distributors under this License -prior to termination shall survive termination. - -************************************************************************ -* * -* 6. Disclaimer of Warranty * -* ------------------------- * -* * -* Covered Software is provided under this License on an "as is" * -* basis, without warranty of any kind, either expressed, implied, or * -* statutory, including, without limitation, warranties that the * -* Covered Software is free of defects, merchantable, fit for a * -* particular purpose or non-infringing. The entire risk as to the * -* quality and performance of the Covered Software is with You. * -* Should any Covered Software prove defective in any respect, You * -* (not any Contributor) assume the cost of any necessary servicing, * -* repair, or correction. This disclaimer of warranty constitutes an * -* essential part of this License. No use of any Covered Software is * -* authorized under this License except under this disclaimer. * -* * -************************************************************************ - -************************************************************************ -* * -* 7. Limitation of Liability * -* -------------------------- * -* * -* Under no circumstances and under no legal theory, whether tort * -* (including negligence), contract, or otherwise, shall any * -* Contributor, or anyone who distributes Covered Software as * -* permitted above, be liable to You for any direct, indirect, * -* special, incidental, or consequential damages of any character * -* including, without limitation, damages for lost profits, loss of * -* goodwill, work stoppage, computer failure or malfunction, or any * -* and all other commercial damages or losses, even if such party * -* shall have been informed of the possibility of such damages. This * -* limitation of liability shall not apply to liability for death or * -* personal injury resulting from such party's negligence to the * -* extent applicable law prohibits such limitation. Some * -* jurisdictions do not allow the exclusion or limitation of * -* incidental or consequential damages, so this exclusion and * -* limitation may not apply to You. * -* * -************************************************************************ - -8. Litigation -------------- - -Any litigation relating to this License may be brought only in the -courts of a jurisdiction where the defendant maintains its principal -place of business and such litigation shall be governed by laws of that -jurisdiction, without reference to its conflict-of-law provisions. -Nothing in this Section shall prevent a party's ability to bring -cross-claims or counter-claims. - -9. Miscellaneous ----------------- - -This License represents the complete agreement concerning the subject -matter hereof. If any provision of this License is held to be -unenforceable, such provision shall be reformed only to the extent -necessary to make it enforceable. Any law or regulation which provides -that the language of a contract shall be construed against the drafter -shall not be used to construe this License against a Contributor. - -10. Versions of the License ---------------------------- - -10.1. New Versions - -Mozilla Foundation is the license steward. Except as provided in Section -10.3, no one other than the license steward has the right to modify or -publish new versions of this License. Each version will be given a -distinguishing version number. - -10.2. Effect of New Versions - -You may distribute the Covered Software under the terms of the version -of the License under which You originally received the Covered Software, -or under the terms of any subsequent version published by the license -steward. - -10.3. Modified Versions - -If you create software not governed by this License, and you want to -create a new license for such software, you may create and use a -modified version of this License if you rename the license and remove -any references to the name of the license steward (except to note that -such modified license differs from this License). - -10.4. Distributing Source Code Form that is Incompatible With Secondary -Licenses - -If You choose to distribute Source Code Form that is Incompatible With -Secondary Licenses under the terms of this version of the License, the -notice described in Exhibit B of this License must be attached. - -Exhibit A - Source Code Form License Notice -------------------------------------------- - -This Source Code Form is subject to the terms of the Mozilla Public -License, v. 2.0. If a copy of the MPL was not distributed with this -file, You can obtain one at http://mozilla.org/MPL/2.0/. - -If it is not possible or desirable to put the notice in a particular -file, then You may include the notice in a location (such as a LICENSE -file in a relevant directory) where a recipient would be likely to look -for such a notice. - -You may add additional accurate notices of copyright ownership. - -Exhibit B - "Incompatible With Secondary Licenses" Notice ---------------------------------------------------------- - -This Source Code Form is "Incompatible With Secondary Licenses", as -defined by the Mozilla Public License, v. 2.0. - diff --git a/servo/PULL_REQUEST_TEMPLATE.md b/servo/PULL_REQUEST_TEMPLATE.md deleted file mode 100644 index 03ab69123dcb..000000000000 --- a/servo/PULL_REQUEST_TEMPLATE.md +++ /dev/null @@ -1,17 +0,0 @@ - - - ---- - -- [ ] `./mach build -d` does not report any errors -- [ ] `./mach build-geckolib` does not report any errors -- [ ] `./mach test-tidy` does not report any errors -- [ ] These changes fix #__ (github issue number if applicable). - - -- [ ] There are tests for these changes OR -- [ ] These changes do not require tests because _____ - - - - diff --git a/servo/README.md b/servo/README.md deleted file mode 100644 index 057f1360a4b1..000000000000 --- a/servo/README.md +++ /dev/null @@ -1,279 +0,0 @@ -# The Servo Parallel Browser Engine Project - -[![Linux Build Status](https://img.shields.io/travis/servo/servo/master.svg?label=Linux%20build)](https://travis-ci.org/servo/servo) [![Windows Build Status](https://img.shields.io/appveyor/ci/servo/servo/master.svg?label=Windows%20build)](https://ci.appveyor.com/project/servo/servo/branch/master) [![Changelog #228](https://img.shields.io/badge/changelog-%23228-9E978E.svg)](https://changelog.com/podcast/228) - -Servo is a prototype web browser engine written in the -[Rust](https://github.com/rust-lang/rust) language. It is currently developed on -64-bit macOS, 64-bit Linux, 64-bit Windows, and Android. - -Servo welcomes contribution from everyone. See -[`CONTRIBUTING.md`](CONTRIBUTING.md) and [`HACKING_QUICKSTART.md`](docs/HACKING_QUICKSTART.md) -for help getting started. - -Visit the [Servo Project page](https://servo.org/) for news and guides. - -## Setting up your environment - -### Rustup.rs - -Building servo requires [rustup](https://rustup.rs/), version 1.8.0 or more recent. -If you have an older version, run `rustup self update`. - -To install on Windows, download and run [`rustup-init.exe`](https://win.rustup.rs/) -then follow the onscreen instructions. - -To install on other systems, run: - -```sh -curl https://sh.rustup.rs -sSf | sh -``` - -This will also download the current stable version of Rust, which Servo won’t use. -To skip that step, run instead: - -``` -curl https://sh.rustup.rs -sSf | sh -s -- --default-toolchain none -``` - -See also [Other installation methods]( -https://github.com/rust-lang-nursery/rustup.rs/#other-installation-methods) - -### Other dependencies - -Please select your operating system: -* [macOS](#macos) -* [Debian-based Linuxes](#on-debian-based-linuxes) -* [Fedora](#on-fedora) -* [Arch Linux](#on-arch-linux) -* [openSUSE](#on-opensuse-linux) -* [Gentoo Linux](#on-gentoo-linux) -* [Microsoft Windows](#on-windows-msvc) -* [Android](#cross-compilation-for-android) - -#### macOS -#### On macOS (homebrew) - -``` sh -brew install automake pkg-config python cmake yasm -pip install virtualenv -``` -#### On macOS (MacPorts) - -``` sh -sudo port install python27 py27-virtualenv cmake yasm -``` -#### On macOS >= 10.11 (El Capitan), you also have to install OpenSSL - -``` sh -brew install openssl - -export OPENSSL_INCLUDE_DIR="$(brew --prefix openssl)/include" -export OPENSSL_LIB_DIR="$(brew --prefix openssl)/lib" - -./mach build ... -``` - -If you've already partially compiled servo but forgot to do this step, run `./mach clean`, set the shell variables, and recompile. - -#### On Debian-based Linuxes - -``` sh -sudo apt install git curl autoconf libx11-dev \ - libfreetype6-dev libgl1-mesa-dri libglib2.0-dev xorg-dev \ - gperf g++ build-essential cmake virtualenv python-pip \ - libssl1.0-dev libbz2-dev libosmesa6-dev libxmu6 libxmu-dev \ - libglu1-mesa-dev libgles2-mesa-dev libegl1-mesa-dev libdbus-1-dev \ - libharfbuzz-dev ccache -``` - -If you using a version prior to **Ubuntu 17.04** or **Debian Sid**, replace `libssl1.0-dev` with `libssl-dev`. - -If you are on **Ubuntu 14.04** and encountered errors on installing these dependencies involving `libcheese`, see [#6158](https://github.com/servo/servo/issues/6158) for a workaround. - -If `virtualenv` does not exist, try `python-virtualenv`. - -#### On Fedora - -``` sh -sudo dnf install curl libtool gcc-c++ libXi-devel \ - freetype-devel mesa-libGL-devel mesa-libEGL-devel glib2-devel libX11-devel libXrandr-devel gperf \ - fontconfig-devel cabextract ttmkfdir python python-virtualenv python-pip expat-devel \ - rpm-build openssl-devel cmake bzip2-devel libXcursor-devel libXmu-devel mesa-libOSMesa-devel \ - dbus-devel ncurses-devel harfbuzz-devel ccache mesa-libGLU-devel -``` -#### On CentOS - -``` sh -sudo yum install curl libtool gcc-c++ libXi-devel \ - freetype-devel mesa-libGL-devel mesa-libEGL-devel glib2-devel libX11-devel libXrandr-devel gperf \ - fontconfig-devel cabextract ttmkfdir python python-virtualenv python-pip expat-devel \ - rpm-build openssl-devel cmake3 bzip2-devel libXcursor-devel libXmu-devel mesa-libOSMesa-devel \ - dbus-devel ncurses-devel python34 harfbuzz-devel ccache -``` -#### On openSUSE Linux -``` sh -sudo zypper install libX11-devel libexpat-devel libbz2-devel Mesa-libEGL-devel Mesa-libGL-devel cabextract cmake \ - dbus-1-devel fontconfig-devel freetype-devel gcc-c++ git glib2-devel gperf \ - harfbuzz-devel libOSMesa-devel libXcursor-devel libXi-devel libXmu-devel libXrandr-devel libopenssl-devel \ - python-pip python-virtualenv rpm-build glu-devel ccache -``` -#### On Arch Linux - -``` sh -sudo pacman -S --needed base-devel git python2 python2-virtualenv python2-pip mesa cmake bzip2 libxmu glu \ - pkg-config ttf-fira-sans harfbuzz ccache -``` -#### On Gentoo Linux - -```sh -sudo emerge net-misc/curl \ - media-libs/freetype media-libs/mesa dev-util/gperf \ - dev-python/virtualenv dev-python/pip dev-libs/openssl \ - x11-libs/libXmu media-libs/glu x11-base/xorg-server \ - media-libs/harfbuzz dev-util/ccache -``` -#### On Windows (MSVC) - -1. Install Python for Windows (https://www.python.org/downloads/release/python-2714/). The Windows x86-64 MSI installer is fine. -You should change the installation to install the "Add python.exe to Path" feature. - -2. Install virtualenv. - - In a normal Windows Shell (cmd.exe or "Command Prompt" from the start menu), do: - ``` -pip install virtualenv -``` - If this does not work, you may need to reboot for the changed PATH settings (by the python installer) to take effect. - -3. Install Git for Windows (https://git-scm.com/download/win). DO allow it to add git.exe to the PATH (default -settings for the installer are fine). - -4. Install Visual Studio Community 2017 (https://www.visualstudio.com/vs/community/). You MUST add "Visual C++" to the -list of installed components. It is not on by default. Visual Studio 2017 MUST installed to the default location or mach.bat will not find it. -> If you encountered errors with the environment above, do the following for a workaround: -> 1. Download and install [Build Tools for Visual Studio 2017](https://www.visualstudio.com/thank-you-downloading-visual-studio/?sku=BuildTools&rel=15) -> 2. Install `python2.7 x86-x64` and `virtualenv` -> 3. Run `mach.bat build -d`. - ->If you have troubles with `x64 type` prompt as `mach.bat` set by default: -> 1. you may need to choose and launch the type manually, such as `x86_x64 Cross Tools Command Prompt for VS 2017` in the Windows menu.) -> 2. `cd to/the/path/servo` -> 3. `python mach build -d` - -#### Cross-compilation for Android - -Pre-installed Android tools are needed. See wiki for -[details](https://github.com/servo/servo/wiki/Building-for-Android) - -## The Rust compiler - -Servo's build system uses rustup.rs to automatically download a Rust compiler. -This is a specific version of Rust Nightly determined by the -[`rust-toolchain`](https://github.com/servo/servo/blob/master/rust-toolchain) file. - -## Building - -Servo is built with [Cargo](https://crates.io/), the Rust package manager. We also use Mozilla's -Mach tools to orchestrate the build and other tasks. - -### Normal build - -To build Servo in development mode. This is useful for development, but -the resulting binary is very slow. - -``` sh -git clone https://github.com/servo/servo -cd servo -./mach build --dev -./mach run tests/html/about-mozilla.html -``` - -Or on Windows MSVC, in a normal Command Prompt (cmd.exe): -``` cmd -git clone https://github.com/servo/servo -cd servo -mach.bat build --dev -``` - -For benchmarking, performance testing, or -real-world use, add the `--release` flag to create an optimized build: - -``` sh -./mach build --release -./mach run --release tests/html/about-mozilla.html -``` - -### Checking for build errors, without building - -If you’re making changes to one crate that cause build errors in another crate, -consider this instead of a full build: - -```sh -./mach check -``` - -It will run `cargo check`, which runs the analysis phase of the compiler -(and so shows build errors if any) but skips the code generation phase. -This can be a lot faster than a full build, -though of course it doesn’t produce a binary you can run. - -### Building for Android target - -``` sh -git clone https://github.com/servo/servo -cd servo - -export ANDROID_SDK="/path/to/sdk" -export ANDROID_NDK="/path/to/ndk" -export ANDROID_TOOLCHAIN="/path/to/toolchain" -export PATH="$PATH:/path/to/toolchain/bin" - -./mach build --release --android -./mach package --release --android -``` - -Rather than setting the `ANDROID_*` environment variables every time, you can -also create a `.servobuild` file and then edit it to contain the correct paths -to the Android SDK/NDK tools: - -``` -cp servobuild.example .servobuild -# edit .servobuild -``` - -## Running - -Run Servo with the command: - -```sh -./servo [url] [arguments] # if you run with nightly build -./mach run [url] [arguments] # if you run with mach - -# For example -./mach run https://www.google.com -``` - -### Commandline Arguments - -- `-p INTERVAL` turns on the profiler and dumps info to the console every - `INTERVAL` seconds -- `-s SIZE` sets the tile size for painting; defaults to 512 -- `-z` disables all graphical output; useful for running JS / layout tests -- `-Z help` displays useful output to debug servo - -### Keyboard Shortcuts - -- `Ctrl`+`-` zooms out -- `Ctrl`+`=` zooms in -- `Alt`+`left arrow` goes backwards in the history -- `Alt`+`right arrow` goes forwards in the history -- `Esc` exits servo - -## Developing - -There are lots of mach commands you can use. You can list them with `./mach ---help`. - - -The generated documentation can be found on http://doc.servo.org/servo/index.html - diff --git a/servo/appveyor.yml b/servo/appveyor.yml deleted file mode 100644 index 445cd76bfe74..000000000000 --- a/servo/appveyor.yml +++ /dev/null @@ -1,66 +0,0 @@ -version: 1.0.{build} - -environment: - CCACHE_DIR: "%APPVEYOR_BUILD_FOLDER%\\.ccache" - CARGO_INCREMENTAL: 0 - RUST_BACKTRACE: 1 - RUSTFLAGS: -Dwarnings - # The appveyor image we use has a pretty huge set of things installed... we make the - # initial PATH something sane so we know what to expect - PATH: "C:\\windows\\system32;\ - C:\\windows;\ - C:\\windows\\System32\\Wbem;\ - C:\\windows\\System32\\WindowsPowerShell\\v1.0;\ - C:\\ProgramData\\chocolatey\\bin;\ - C:\\Python27;\ - C:\\Python27\\Scripts;\ - C:\\Tools\\PsTools;\ - C:\\Tools\\NuGet3;\ - C:\\Program Files\\Microsoft\\Web Platform Installer\\;\ - C:\\Program Files\\7-Zip;\ - C:\\Program Files\\Mercurial;\ - C:\\Program Files (x86)\\Subversion\\bin;\ - C:\\Program Files (x86)\\CMake\\bin;\ - C:\\Program Files (x86)\\Windows Kits\\10\\Windows Performance Toolkit\\;\ - C:\\Program Files (x86)\\MSBuild\\14.0\\Bin;\ - C:\\Program Files\\Amazon\\AWSCLI\\;\ - C:\\Program Files\\Microsoft Windows Performance Toolkit\\;\ - C:\\Program Files\\LLVM\\bin;\ - C:\\Program Files\\Git LFS;\ - C:\\Program Files\\Git\\cmd;\ - C:\\Program Files\\Git\\usr\\bin;\ - C:\\Program Files\\AppVeyor\\BuildAgent;" - matrix: - - TARGET: nightly-x86_64-pc-windows-msvc - -branches: - only: - - master - -cache: - - C:\Users\appveyor\.rustup -> rust-toolchain - - C:\Users\appveyor\.cargo -> rust-toolchain - - .servo -> rust-toolchain - - .ccache - -install: - - appveyor-retry appveyor DownloadFile https://win.rustup.rs/ -FileName rustup-init.exe - - rustup-init.exe -y --default-host x86_64-pc-windows-msvc --default-toolchain none - - set PATH=%PATH%;C:\Users\appveyor\.cargo\bin - - rustup -V - - mach rustc --version - - mach cargo --version - -# Uncomment these lines to expose RDP access information to the build machine in the build log. -#init: -# - ps: iex ((new-object net.webclient).DownloadString('https://raw.githubusercontent.com/appveyor/ci/master/scripts/enable-rdp.ps1')) -# -#on_finish: -# - ps: $blockRdp = $true; iex ((new-object net.webclient).DownloadString('https://raw.githubusercontent.com/appveyor/ci/master/scripts/enable-rdp.ps1')) - -build_script: - - mach clean-nightlies --keep 2 --force - - mach build -d -v - - mach test-unit - -test: off diff --git a/servo/components/allocator/Cargo.toml b/servo/components/allocator/Cargo.toml deleted file mode 100644 index 645815ba1f13..000000000000 --- a/servo/components/allocator/Cargo.toml +++ /dev/null @@ -1,21 +0,0 @@ -[package] -name = "servo_allocator" -version = "0.0.1" -authors = ["The Servo Project Developers"] -license = "MPL-2.0" -publish = false - -[lib] -path = "lib.rs" - -[features] -unstable = ["kernel32-sys", "jemallocator"] - -[dependencies] -libc = "0.2" # Only used when 'unstable' is disabled, but looks like Cargo cannot express that. - -[target.'cfg(not(windows))'.dependencies] -jemallocator = { version = "0.1.4", optional = true } - -[target.'cfg(windows)'.dependencies] -kernel32-sys = { version = "0.2.1", optional = true } diff --git a/servo/components/allocator/lib.rs b/servo/components/allocator/lib.rs deleted file mode 100644 index 6c248f08055d..000000000000 --- a/servo/components/allocator/lib.rs +++ /dev/null @@ -1,71 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -//! Selecting the default global allocator for Servo - -#![cfg_attr(all(feature = "unstable", windows), feature(alloc_system, allocator_api))] -#![cfg_attr(feature = "unstable", feature(global_allocator))] - -#[cfg(feature = "unstable")] -#[global_allocator] -static ALLOC: Allocator = Allocator; - -pub use platform::*; - - -#[cfg(all(feature = "unstable", not(windows)))] -mod platform { - extern crate jemallocator; - - pub use self::jemallocator::Jemalloc as Allocator; - use std::os::raw::c_void; - - /// Get the size of a heap block. - pub unsafe extern "C" fn usable_size(ptr: *const c_void) -> usize { - jemallocator::usable_size(ptr) - } - - /// Memory allocation APIs compatible with libc - pub mod libc_compat { - pub use super::jemallocator::ffi::{malloc, realloc, free}; - } -} - -#[cfg(all(feature = "unstable", windows))] -mod platform { - extern crate alloc_system; - extern crate kernel32; - - pub use self::alloc_system::System as Allocator; - use self::kernel32::{GetProcessHeap, HeapSize, HeapValidate}; - use std::os::raw::c_void; - - /// Get the size of a heap block. - pub unsafe extern "C" fn usable_size(mut ptr: *const c_void) -> usize { - let heap = GetProcessHeap(); - - if HeapValidate(heap, 0, ptr) == 0 { - ptr = *(ptr as *const *const c_void).offset(-1); - } - - HeapSize(heap, 0, ptr) as usize - } -} - -#[cfg(not(feature = "unstable"))] -mod platform { - use std::os::raw::c_void; - - /// Without `#[global_allocator]` we cannot be certain of what allocator is used - /// or how it is linked. We therefore disable memory reporting. (Return zero.) - pub unsafe extern "C" fn usable_size(_ptr: *const c_void) -> usize { - 0 - } - - /// Memory allocation APIs compatible with libc - pub mod libc_compat { - extern crate libc; - pub use self::libc::{malloc, realloc, free}; - } -} diff --git a/servo/components/atoms/Cargo.toml b/servo/components/atoms/Cargo.toml deleted file mode 100644 index 9e6e07899e6b..000000000000 --- a/servo/components/atoms/Cargo.toml +++ /dev/null @@ -1,16 +0,0 @@ -[package] -name = "servo_atoms" -version = "0.0.1" -authors = ["The Servo Project Developers"] -license = "MPL-2.0" -publish = false -build = "build.rs" - -[lib] -path = "lib.rs" - -[dependencies] -string_cache = {version = "0.7"} - -[build-dependencies] -string_cache_codegen = "0.4" diff --git a/servo/components/atoms/build.rs b/servo/components/atoms/build.rs deleted file mode 100644 index 8a6ba8fd9363..000000000000 --- a/servo/components/atoms/build.rs +++ /dev/null @@ -1,32 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -extern crate string_cache_codegen; - -use std::env; -use std::fs::File; -use std::io::{BufReader, BufRead}; -use std::path::Path; - -fn main() { - let static_atoms = Path::new(&env::var_os("CARGO_MANIFEST_DIR").unwrap()).join("static_atoms.txt"); - let static_atoms = BufReader::new(File::open(&static_atoms).unwrap()); - let mut atom_type = string_cache_codegen::AtomType::new("Atom", "atom!"); - - macro_rules! predefined { - ($($name: expr,)+) => { - { - $( - atom_type.atom($name); - )+ - } - } - } - include!("../style/counter_style/predefined.rs"); - - atom_type - .atoms(static_atoms.lines().map(Result::unwrap)) - .write_to_file(&Path::new(&env::var_os("OUT_DIR").unwrap()).join("atom.rs")) - .unwrap(); -} diff --git a/servo/components/atoms/lib.rs b/servo/components/atoms/lib.rs deleted file mode 100644 index c1da7167bde1..000000000000 --- a/servo/components/atoms/lib.rs +++ /dev/null @@ -1,7 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -extern crate string_cache; - -include!(concat!(env!("OUT_DIR"), "/atom.rs")); diff --git a/servo/components/atoms/static_atoms.txt b/servo/components/atoms/static_atoms.txt deleted file mode 100644 index e72e1e07b194..000000000000 --- a/servo/components/atoms/static_atoms.txt +++ /dev/null @@ -1,81 +0,0 @@ -DOMContentLoaded -abort -activate -beforeunload -button -canplay -canplaythrough -center -change -characteristicvaluechanged -checkbox -click -close -color -controllerchange -cursive -date -datetime-local -dir -email -emptied -error -fantasy -fetch -file -fullscreenchange -fullscreenerror -gattserverdisconnected -hidden -image -input -invalid -keydown -keypress -left -load -loadeddata -loadedmetadata -loadend -loadstart -message -message -monospace -month -mouseover -none -number -onchange -open -pageshow -password -pause -play -playing -print -progress -radio -range -readystatechange -reftest-wait -reset -right -sans-serif -screen -search -select -serif -statechange -storage -submit -suspend -tel -text -time -timeupdate -toggle -transitionend -url -waiting -webglcontextcreationerror -week diff --git a/servo/components/bluetooth/Cargo.toml b/servo/components/bluetooth/Cargo.toml deleted file mode 100644 index 53784d13e9c4..000000000000 --- a/servo/components/bluetooth/Cargo.toml +++ /dev/null @@ -1,22 +0,0 @@ -[package] -name = "bluetooth" -version = "0.0.1" -authors = ["The Servo Project Developers"] -license = "MPL-2.0" -publish = false - -[lib] -name = "bluetooth" -path = "lib.rs" - -[dependencies] -bitflags = "1.0" -bluetooth_traits = {path = "../bluetooth_traits"} -device = {git = "https://github.com/servo/devices", features = ["bluetooth-test"]} -ipc-channel = "0.10" -servo_config = {path = "../config"} -servo_rand = {path = "../rand"} -uuid = {version = "0.6", features = ["v4"]} - -[target.'cfg(target_os = "linux")'.dependencies] -tinyfiledialogs = "3.0" diff --git a/servo/components/bluetooth/lib.rs b/servo/components/bluetooth/lib.rs deleted file mode 100644 index a68b701d8836..000000000000 --- a/servo/components/bluetooth/lib.rs +++ /dev/null @@ -1,938 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -#[macro_use] -extern crate bitflags; -extern crate bluetooth_traits; -extern crate device; -extern crate ipc_channel; -extern crate servo_config; -extern crate servo_rand; -#[cfg(target_os = "linux")] -extern crate tinyfiledialogs; -extern crate uuid; - -pub mod test; - -use bluetooth_traits::{BluetoothCharacteristicMsg, BluetoothDescriptorMsg, BluetoothServiceMsg}; -use bluetooth_traits::{BluetoothDeviceMsg, BluetoothRequest, BluetoothResponse, GATTType}; -use bluetooth_traits::{BluetoothError, BluetoothResponseResult, BluetoothResult}; -use bluetooth_traits::blocklist::{uuid_is_blocklisted, Blocklist}; -use bluetooth_traits::scanfilter::{BluetoothScanfilter, BluetoothScanfilterSequence, RequestDeviceoptions}; -use device::bluetooth::{BluetoothAdapter, BluetoothDevice, BluetoothGATTCharacteristic}; -use device::bluetooth::{BluetoothGATTDescriptor, BluetoothGATTService}; -use ipc_channel::ipc::{self, IpcReceiver, IpcSender}; -#[cfg(target_os = "linux")] -use servo_config::opts; -use servo_config::prefs::PREFS; -use servo_rand::Rng; -use std::borrow::ToOwned; -use std::collections::{HashMap, HashSet}; -use std::string::String; -use std::thread; -use std::time::Duration; - -// A transaction not completed within 30 seconds shall time out. Such a transaction shall be considered to have failed. -// https://www.bluetooth.org/DocMan/handlers/DownloadDoc.ashx?doc_id=286439 (Vol. 3, page 480) -const MAXIMUM_TRANSACTION_TIME: u8 = 30; -const CONNECTION_TIMEOUT_MS: u64 = 1000; -// The discovery session needs some time to find any nearby devices -const DISCOVERY_TIMEOUT_MS: u64 = 1500; -#[cfg(target_os = "linux")] -const DIALOG_TITLE: &'static str = "Choose a device"; -#[cfg(target_os = "linux")] -const DIALOG_COLUMN_ID: &'static str = "Id"; -#[cfg(target_os = "linux")] -const DIALOG_COLUMN_NAME: &'static str = "Name"; - -bitflags! { - struct Flags: u32 { - const BROADCAST = 0b000000001; - const READ = 0b000000010; - const WRITE_WITHOUT_RESPONSE = 0b000000100; - const WRITE = 0b000001000; - const NOTIFY = 0b000010000; - const INDICATE = 0b000100000; - const AUTHENTICATED_SIGNED_WRITES = 0b001000000; - const RELIABLE_WRITE = 0b010000000; - const WRITABLE_AUXILIARIES = 0b100000000; - } -} - -macro_rules! return_if_cached( - ($cache:expr, $key:expr) => ( - if $cache.contains_key($key) { - return $cache.get($key); - } - ); -); - -pub trait BluetoothThreadFactory { - fn new() -> Self; -} - -impl BluetoothThreadFactory for IpcSender { - fn new() -> IpcSender { - let (sender, receiver) = ipc::channel().unwrap(); - let adapter = if Some(true) == PREFS.get("dom.bluetooth.enabled").as_boolean() { - BluetoothAdapter::init() - } else { - BluetoothAdapter::init_mock() - }.ok(); - thread::Builder::new().name("BluetoothThread".to_owned()).spawn(move || { - BluetoothManager::new(receiver, adapter).start(); - }).expect("Thread spawning failed"); - sender - } -} - -// https://webbluetoothcg.github.io/web-bluetooth/#matches-a-filter -fn matches_filter(device: &BluetoothDevice, filter: &BluetoothScanfilter) -> bool { - if filter.is_empty_or_invalid() { - return false; - } - - // Step 1. - if let Some(name) = filter.get_name() { - if device.get_name().ok() != Some(name.to_string()) { - return false; - } - } - - // Step 2. - if !filter.get_name_prefix().is_empty() { - if let Ok(device_name) = device.get_name() { - if !device_name.starts_with(filter.get_name_prefix()) { - return false; - } - } else { - return false; - } - } - - // Step 3. - if !filter.get_services().is_empty() { - if let Ok(device_uuids) = device.get_uuids() { - for service in filter.get_services() { - if device_uuids.iter().find(|x| x == &service).is_none() { - return false; - } - } - } - } - - // Step 4. - if let Some(ref manufacturer_data) = filter.get_manufacturer_data() { - let advertised_manufacturer_data = match device.get_manufacturer_data() { - Ok(data) => data, - Err(_) => return false, - }; - for (ref id, &(ref prefix, ref mask)) in manufacturer_data.iter() { - if let Some(advertised_data) = advertised_manufacturer_data.get(id) { - if !data_filter_matches(advertised_data, prefix, mask) { - return false; - } - } else { - return false; - } - } - } - - // Step 5. - if let Some(ref service_data) = filter.get_service_data() { - let advertised_service_data = match device.get_service_data() { - Ok(data) => data, - Err(_) => return false, - }; - for (uuid, &(ref prefix, ref mask)) in service_data.iter() { - if let Some(advertised_data) = advertised_service_data.get(uuid.as_str()) { - if !data_filter_matches(advertised_data, prefix, mask) { - return false; - } - } else { - return false; - } - } - } - - // Step 6. - true -} - -// https://webbluetoothcg.github.io/web-bluetooth/#bluetoothdatafilterinit-matches -fn data_filter_matches(data: &[u8], prefix: &[u8], mask: &[u8]) -> bool { - // Step 1-2: No need to copy the bytes here. - // Step 3. - if data.len() < prefix.len() { - return false; - } - - // Step 4. - for ((data, mask), prefix) in data.iter().zip(mask.iter()).zip(prefix.iter()) { - if data & mask != prefix & mask { - return false; - } - } - - // Step 5. - true -} - -fn matches_filters(device: &BluetoothDevice, filters: &BluetoothScanfilterSequence) -> bool { - if filters.has_empty_or_invalid_filter() { - return false; - } - - return filters.iter().any(|f| matches_filter(device, f)) -} - -fn is_mock_adapter(adapter: &BluetoothAdapter) -> bool { - match adapter { - &BluetoothAdapter::Mock(_) => true, - _ => false, - } -} - -pub struct BluetoothManager { - receiver: IpcReceiver, - adapter: Option, - address_to_id: HashMap, - service_to_device: HashMap, - characteristic_to_service: HashMap, - descriptor_to_characteristic: HashMap, - cached_devices: HashMap, - cached_services: HashMap, - cached_characteristics: HashMap, - cached_descriptors: HashMap, - allowed_services: HashMap>, -} - -impl BluetoothManager { - pub fn new(receiver: IpcReceiver, adapter: Option) -> BluetoothManager { - BluetoothManager { - receiver: receiver, - adapter: adapter, - address_to_id: HashMap::new(), - service_to_device: HashMap::new(), - characteristic_to_service: HashMap::new(), - descriptor_to_characteristic: HashMap::new(), - cached_devices: HashMap::new(), - cached_services: HashMap::new(), - cached_characteristics: HashMap::new(), - cached_descriptors: HashMap::new(), - allowed_services: HashMap::new(), - } - } - - fn start(&mut self) { - while let Ok(msg) = self.receiver.recv() { - match msg { - BluetoothRequest::RequestDevice(options, sender) => { - let _ = sender.send(self.request_device(options)); - }, - BluetoothRequest::GATTServerConnect(device_id, sender) => { - let _ = sender.send(self.gatt_server_connect(device_id)); - }, - BluetoothRequest::GATTServerDisconnect(device_id, sender) => { - let _ = sender.send(self.gatt_server_disconnect(device_id)); - }, - BluetoothRequest::GetGATTChildren(id, uuid, single, child_type, sender) => { - let _ = sender.send(self.get_gatt_children(id, uuid, single, child_type)); - }, - BluetoothRequest::ReadValue(id, sender) => { - let _ = sender.send(self.read_value(id)); - }, - BluetoothRequest::WriteValue(id, value, sender) => { - let _ = sender.send(self.write_value(id, value)); - }, - BluetoothRequest::EnableNotification(id, enable, sender) => { - let _ = sender.send(self.enable_notification(id, enable)); - }, - BluetoothRequest::WatchAdvertisements(id, sender) => { - let _ = sender.send(self.watch_advertisements(id)); - }, - BluetoothRequest::Test(data_set_name, sender) => { - let _ = sender.send(self.test(data_set_name)); - }, - BluetoothRequest::SetRepresentedToNull(service_ids, characteristic_ids, descriptor_ids) => { - self.remove_ids_from_caches(service_ids, characteristic_ids, descriptor_ids) - }, - BluetoothRequest::IsRepresentedDeviceNull(id, sender) => { - let _ = sender.send(!self.device_is_cached(&id)); - }, - BluetoothRequest::GetAvailability(sender) => { - let _ = sender.send(self.get_availability()); - }, - BluetoothRequest::MatchesFilter(id, filters, sender) => { - let _ = sender.send(self.device_matches_filter(&id, &filters)); - }, - BluetoothRequest::Exit => { - break - }, - } - } - } - - // Test - - fn test(&mut self, data_set_name: String) -> BluetoothResult<()> { - self.address_to_id.clear(); - self.service_to_device.clear(); - self.characteristic_to_service.clear(); - self.descriptor_to_characteristic.clear(); - self.cached_devices.clear(); - self.cached_services.clear(); - self.cached_characteristics.clear(); - self.cached_descriptors.clear(); - self.allowed_services.clear(); - self.adapter = BluetoothAdapter::init_mock().ok(); - match test::test(self, data_set_name) { - Ok(_) => return Ok(()), - Err(error) => Err(BluetoothError::Type(error.description().to_owned())), - } - } - - fn remove_ids_from_caches(&mut self, - service_ids: Vec, - characteristic_ids: Vec, - descriptor_ids: Vec) { - for id in service_ids { - self.cached_services.remove(&id); - self.service_to_device.remove(&id); - } - - for id in characteristic_ids { - self.cached_characteristics.remove(&id); - self.characteristic_to_service.remove(&id); - } - - for id in descriptor_ids { - self.cached_descriptors.remove(&id); - self.descriptor_to_characteristic.remove(&id); - } - } - - // Adapter - - pub fn get_or_create_adapter(&mut self) -> Option { - let adapter_valid = self.adapter.as_ref().map_or(false, |a| a.get_address().is_ok()); - if !adapter_valid { - self.adapter = BluetoothAdapter::init().ok(); - } - - let adapter = self.adapter.as_ref()?; - - if is_mock_adapter(adapter) && !adapter.is_present().unwrap_or(false) { - return None; - } - - self.adapter.clone() - } - - fn get_adapter(&mut self) -> BluetoothResult { - match self.get_or_create_adapter() { - Some(adapter) => { - if !adapter.is_powered().unwrap_or(false) { - return Err(BluetoothError::NotFound); - } - return Ok(adapter); - }, - None => return Err(BluetoothError::NotFound), - } - } - - // Device - - fn get_and_cache_devices(&mut self, adapter: &mut BluetoothAdapter) -> Vec { - let devices = adapter.get_devices().unwrap_or(vec!()); - for device in &devices { - if let Ok(address) = device.get_address() { - if !self.address_to_id.contains_key(&address) { - let generated_id = self.generate_device_id(); - self.address_to_id.insert(address, generated_id.clone()); - self.cached_devices.insert(generated_id.clone(), device.clone()); - self.allowed_services.insert(generated_id, HashSet::new()); - } - } - } - self.cached_devices.iter().map(|(_, d)| d.clone()).collect() - } - - fn get_device(&mut self, adapter: &mut BluetoothAdapter, device_id: &str) -> Option<&BluetoothDevice> { - return_if_cached!(self.cached_devices, device_id); - self.get_and_cache_devices(adapter); - return_if_cached!(self.cached_devices, device_id); - None - } - - #[cfg(target_os = "linux")] - fn select_device(&mut self, devices: Vec, adapter: &BluetoothAdapter) -> Option { - if is_mock_adapter(adapter) || opts::get().headless { - for device in devices { - if let Ok(address) = device.get_address() { - return Some(address); - } - } - return None; - } - - let mut dialog_rows: Vec = vec!(); - for device in devices { - dialog_rows.extend_from_slice(&[device.get_address().unwrap_or("".to_string()), - device.get_name().unwrap_or("".to_string())]); - } - let dialog_rows: Vec<&str> = dialog_rows.iter() - .map(|s| s.as_ref()) - .collect(); - let dialog_rows: &[&str] = dialog_rows.as_slice(); - - if let Some(device) = tinyfiledialogs::list_dialog(DIALOG_TITLE, - &[DIALOG_COLUMN_ID, DIALOG_COLUMN_NAME], - Some(dialog_rows)) { - // The device string format will be "Address|Name". We need the first part of it. - return device.split("|").next().map(|s| s.to_string()); - } - None - } - - #[cfg(not(target_os = "linux"))] - fn select_device(&mut self, devices: Vec, _adapter: &BluetoothAdapter) -> Option { - for device in devices { - if let Ok(address) = device.get_address() { - return Some(address); - } - } - None - } - - fn generate_device_id(&mut self) -> String { - let mut device_id; - let mut rng = servo_rand::thread_rng(); - loop { - device_id = rng.gen::().to_string(); - if !self.cached_devices.contains_key(&device_id) { - break; - } - } - device_id - } - - fn device_from_service_id(&self, service_id: &str) -> Option { - let device_id = self.service_to_device.get(service_id)?; - self.cached_devices.get(device_id).cloned() - } - - fn device_is_cached(&self, device_id: &str) -> bool { - self.cached_devices.contains_key(device_id) && self.address_to_id.values().any(|v| v == device_id) - } - - fn device_matches_filter(&mut self, - device_id: &str, - filters: &BluetoothScanfilterSequence) - -> BluetoothResult { - let mut adapter = self.get_adapter()?; - match self.get_device(&mut adapter, device_id) { - Some(ref device) => Ok(matches_filters(device, filters)), - None => Ok(false), - } - } - - // Service - - fn get_and_cache_gatt_services(&mut self, - adapter: &mut BluetoothAdapter, - device_id: &str) - -> Vec { - let mut services = match self.get_device(adapter, device_id) { - Some(d) => d.get_gatt_services().unwrap_or(vec!()), - None => vec!(), - }; - - services.retain(|s| !uuid_is_blocklisted(&s.get_uuid().unwrap_or(String::new()), Blocklist::All) && - self.allowed_services - .get(device_id) - .map_or(false, |uuids| uuids.contains(&s.get_uuid().unwrap_or(String::new())))); - for service in &services { - self.cached_services.insert(service.get_id(), service.clone()); - self.service_to_device.insert(service.get_id(), device_id.to_owned()); - } - services - } - - fn get_gatt_service(&mut self, adapter: &mut BluetoothAdapter, service_id: &str) -> Option<&BluetoothGATTService> { - return_if_cached!(self.cached_services, service_id); - let device_id = self.service_to_device.get(service_id)?.clone(); - self.get_and_cache_gatt_services(adapter, &device_id); - return_if_cached!(self.cached_services, service_id); - None - } - - fn service_is_cached(&self, service_id: &str) -> bool { - self.cached_services.contains_key(service_id) && self.service_to_device.contains_key(service_id) - } - - // Characteristic - - fn get_and_cache_gatt_characteristics(&mut self, - adapter: &mut BluetoothAdapter, - service_id: &str) - -> Vec { - let mut characteristics = match self.get_gatt_service(adapter, service_id) { - Some(s) => s.get_gatt_characteristics().unwrap_or(vec!()), - None => vec!(), - }; - - characteristics.retain(|c| !uuid_is_blocklisted(&c.get_uuid().unwrap_or(String::new()), Blocklist::All)); - for characteristic in &characteristics { - self.cached_characteristics.insert(characteristic.get_id(), characteristic.clone()); - self.characteristic_to_service.insert(characteristic.get_id(), service_id.to_owned()); - } - characteristics - } - - fn get_gatt_characteristic(&mut self, - adapter: &mut BluetoothAdapter, - characteristic_id: &str) - -> Option<&BluetoothGATTCharacteristic> { - return_if_cached!(self.cached_characteristics, characteristic_id); - let service_id = self.characteristic_to_service.get(characteristic_id)?.clone(); - self.get_and_cache_gatt_characteristics(adapter, &service_id); - return_if_cached!(self.cached_characteristics, characteristic_id); - None - } - - fn get_characteristic_properties(&self, characteristic: &BluetoothGATTCharacteristic) -> Flags { - let mut props: Flags = Flags::empty(); - let flags = characteristic.get_flags().unwrap_or(vec!()); - for flag in flags { - match flag.as_ref() { - "broadcast" => props.insert(Flags::BROADCAST), - "read" => props.insert(Flags::READ), - "write-without-response" => props.insert(Flags::WRITE_WITHOUT_RESPONSE), - "write" => props.insert(Flags::WRITE), - "notify" => props.insert(Flags::NOTIFY), - "indicate" => props.insert(Flags::INDICATE), - "authenticated-signed-writes" => props.insert(Flags::AUTHENTICATED_SIGNED_WRITES), - "reliable-write" => props.insert(Flags::RELIABLE_WRITE), - "writable-auxiliaries" => props.insert(Flags::WRITABLE_AUXILIARIES), - _ => (), - } - } - props - } - - fn characteristic_is_cached(&self, characteristic_id: &str) -> bool { - self.cached_characteristics.contains_key(characteristic_id) && - self.characteristic_to_service.contains_key(characteristic_id) - } - - // Descriptor - - fn get_and_cache_gatt_descriptors(&mut self, - adapter: &mut BluetoothAdapter, - characteristic_id: &str) - -> Vec { - let mut descriptors = match self.get_gatt_characteristic(adapter, characteristic_id) { - Some(c) => c.get_gatt_descriptors().unwrap_or(vec!()), - None => vec!(), - }; - - descriptors.retain(|d| !uuid_is_blocklisted(&d.get_uuid().unwrap_or(String::new()), Blocklist::All)); - for descriptor in &descriptors { - self.cached_descriptors.insert(descriptor.get_id(), descriptor.clone()); - self.descriptor_to_characteristic.insert(descriptor.get_id(), characteristic_id.to_owned()); - } - descriptors - } - - fn get_gatt_descriptor(&mut self, - adapter: &mut BluetoothAdapter, - descriptor_id: &str) - -> Option<&BluetoothGATTDescriptor> { - return_if_cached!(self.cached_descriptors, descriptor_id); - let characteristic_id = self.descriptor_to_characteristic.get(descriptor_id)?.clone(); - self.get_and_cache_gatt_descriptors(adapter, &characteristic_id); - return_if_cached!(self.cached_descriptors, descriptor_id); - None - } - - // Methods - - // https://webbluetoothcg.github.io/web-bluetooth/#request-bluetooth-devices - fn request_device(&mut self, - options: RequestDeviceoptions) - -> BluetoothResponseResult { - // Step 6. - let mut adapter = self.get_adapter()?; - - // Step 7. - // Note: There are no requiredServiceUUIDS, we scan for all devices. - if let Ok(ref session) = adapter.create_discovery_session() { - if session.start_discovery().is_ok() { - if !is_mock_adapter(&adapter) { - thread::sleep(Duration::from_millis(DISCOVERY_TIMEOUT_MS)); - } - } - let _ = session.stop_discovery(); - } - - let mut matched_devices = self.get_and_cache_devices(&mut adapter); - - // Step 8. - if !options.is_accepting_all_devices() { - matched_devices = matched_devices.into_iter() - .filter(|d| matches_filters(d, options.get_filters())) - .collect(); - } - - // Step 9. - if let Some(address) = self.select_device(matched_devices, &adapter) { - let device_id = match self.address_to_id.get(&address) { - Some(id) => id.clone(), - None => return Err(BluetoothError::NotFound), - }; - let mut services = options.get_services_set(); - if let Some(services_set) = self.allowed_services.get(&device_id) { - services = services_set | &services; - } - self.allowed_services.insert(device_id.clone(), services); - if let Some(device) = self.get_device(&mut adapter, &device_id) { - let message = BluetoothDeviceMsg { - id: device_id, - name: device.get_name().ok(), - }; - return Ok(BluetoothResponse::RequestDevice(message)); - } - } - // Step 10. - return Err(BluetoothError::NotFound); - // Step 12: Missing, because it is optional. - } - - // https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetoothremotegattserver-connect - fn gatt_server_connect(&mut self, device_id: String) -> BluetoothResponseResult { - // Step 2. - if !self.device_is_cached(&device_id) { - return Err(BluetoothError::Network); - } - let mut adapter = self.get_adapter()?; - - // Step 5.1.1. - match self.get_device(&mut adapter, &device_id) { - Some(d) => { - if d.is_connected().unwrap_or(false) { - return Ok(BluetoothResponse::GATTServerConnect(true)); - } - let _ = d.connect(); - for _ in 0..MAXIMUM_TRANSACTION_TIME { - match d.is_connected().unwrap_or(false) { - true => return Ok(BluetoothResponse::GATTServerConnect(true)), - false => { - if is_mock_adapter(&adapter) { - break; - } - thread::sleep(Duration::from_millis(CONNECTION_TIMEOUT_MS)); - }, - } - // TODO: Step 5.1.4: Use the exchange MTU procedure. - } - // Step 5.1.3. - return Err(BluetoothError::Network); - }, - None => return Err(BluetoothError::NotFound), - } - } - - // https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetoothremotegattserver-disconnect - fn gatt_server_disconnect(&mut self, device_id: String) -> BluetoothResult<()> { - let mut adapter = self.get_adapter()?; - match self.get_device(&mut adapter, &device_id) { - Some(d) => { - // Step 2. - if !d.is_connected().unwrap_or(true) { - return Ok(()); - } - let _ = d.disconnect(); - for _ in 0..MAXIMUM_TRANSACTION_TIME { - match d.is_connected().unwrap_or(true) { - true => thread::sleep(Duration::from_millis(CONNECTION_TIMEOUT_MS)), - false => return Ok(()), - } - } - return Err(BluetoothError::Network); - }, - None => return Err(BluetoothError::NotFound), - } - } - - // https://webbluetoothcg.github.io/web-bluetooth/#getgattchildren - fn get_gatt_children(&mut self, - id: String, - uuid: Option, - single: bool, - child_type: GATTType) - -> BluetoothResponseResult { - let mut adapter = self.get_adapter()?; - match child_type { - GATTType::PrimaryService => { - // Step 5. - if !self.device_is_cached(&id) { - return Err(BluetoothError::InvalidState); - } - // Step 6. - if let Some(ref uuid) = uuid { - if !self.allowed_services.get(&id).map_or(false, |s| s.contains(uuid)) { - return Err(BluetoothError::Security); - } - } - let mut services = self.get_and_cache_gatt_services(&mut adapter, &id); - if let Some(uuid) = uuid { - services.retain(|ref e| e.get_uuid().unwrap_or(String::new()) == uuid); - } - let mut services_vec = vec!(); - for service in services { - if service.is_primary().unwrap_or(false) { - if let Ok(uuid) = service.get_uuid() { - services_vec.push( - BluetoothServiceMsg { - uuid: uuid, - is_primary: true, - instance_id: service.get_id(), - } - ); - } - } - } - // Step 7. - if services_vec.is_empty() { - return Err(BluetoothError::NotFound); - } - - return Ok(BluetoothResponse::GetPrimaryServices(services_vec, single)); - }, - GATTType::Characteristic => { - // Step 5. - if !self.service_is_cached(&id) { - return Err(BluetoothError::InvalidState); - } - // Step 6. - let mut characteristics = self.get_and_cache_gatt_characteristics(&mut adapter, &id); - if let Some(uuid) = uuid { - characteristics.retain(|ref e| e.get_uuid().unwrap_or(String::new()) == uuid); - } - let mut characteristics_vec = vec!(); - for characteristic in characteristics { - if let Ok(uuid) = characteristic.get_uuid() { - let properties = self.get_characteristic_properties(&characteristic); - characteristics_vec.push( - BluetoothCharacteristicMsg { - uuid: uuid, - instance_id: characteristic.get_id(), - broadcast: properties.contains(Flags::BROADCAST), - read: properties.contains(Flags::READ), - write_without_response: properties.contains(Flags::WRITE_WITHOUT_RESPONSE), - write: properties.contains(Flags::WRITE), - notify: properties.contains(Flags::NOTIFY), - indicate: properties.contains(Flags::INDICATE), - authenticated_signed_writes: properties.contains(Flags::AUTHENTICATED_SIGNED_WRITES), - reliable_write: properties.contains(Flags::RELIABLE_WRITE), - writable_auxiliaries: properties.contains(Flags::WRITABLE_AUXILIARIES), - } - ); - } - } - - // Step 7. - if characteristics_vec.is_empty() { - return Err(BluetoothError::NotFound); - } - - return Ok(BluetoothResponse::GetCharacteristics(characteristics_vec, single)); - }, - GATTType::IncludedService => { - // Step 5. - if !self.service_is_cached(&id) { - return Err(BluetoothError::InvalidState); - } - // Step 6. - let device = match self.device_from_service_id(&id) { - Some(device) => device, - None => return Err(BluetoothError::NotFound), - }; - let primary_service = match self.get_gatt_service(&mut adapter, &id) { - Some(s) => s, - None => return Err(BluetoothError::NotFound), - }; - let services = primary_service.get_includes(device).unwrap_or(vec!()); - let mut services_vec = vec!(); - for service in services { - if let Ok(service_uuid) = service.get_uuid() { - services_vec.push( - BluetoothServiceMsg { - uuid: service_uuid, - is_primary: service.is_primary().unwrap_or(false), - instance_id: service.get_id(), - } - ); - } - } - if let Some(uuid) = uuid { - services_vec.retain(|ref s| s.uuid == uuid); - } - services_vec.retain(|s| !uuid_is_blocklisted(&s.uuid, Blocklist::All)); - - // Step 7. - if services_vec.is_empty() { - return Err(BluetoothError::NotFound); - } - - return Ok(BluetoothResponse::GetIncludedServices(services_vec, single)); - }, - GATTType::Descriptor => { - // Step 5. - if !self.characteristic_is_cached(&id) { - return Err(BluetoothError::InvalidState); - } - // Step 6. - let mut descriptors = self.get_and_cache_gatt_descriptors(&mut adapter, &id); - if let Some(uuid) = uuid { - descriptors.retain(|ref e| e.get_uuid().unwrap_or(String::new()) == uuid); - } - let mut descriptors_vec = vec!(); - for descriptor in descriptors { - if let Ok(uuid) = descriptor.get_uuid() { - descriptors_vec.push( - BluetoothDescriptorMsg { - uuid: uuid, - instance_id: descriptor.get_id(), - } - ); - } - } - - // Step 7. - if descriptors_vec.is_empty() { - return Err(BluetoothError::NotFound); - } - return Ok(BluetoothResponse::GetDescriptors(descriptors_vec, single)); - }, - } - } - - // https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetoothremotegattcharacteristic-readvalue - // https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetoothremotegattdescriptor-readvalue - fn read_value(&mut self, id: String) -> BluetoothResponseResult { - // (Characteristic) Step 5.2: Missing because it is optional. - // (Descriptor) Step 5.1: Missing because it is optional. - let mut adapter = self.get_adapter()?; - - // (Characteristic) Step 5.3. - let mut value = self.get_gatt_characteristic(&mut adapter, &id) - .map(|c| c.read_value().unwrap_or(vec![])); - - // (Characteristic) TODO: Step 5.4: Handle all the errors returned from the read_value call. - - // (Descriptor) Step 5.2. - if value.is_none() { - value = self.get_gatt_descriptor(&mut adapter, &id) - .map(|d| d.read_value().unwrap_or(vec![])); - } - - // (Descriptor) TODO: Step 5.3: Handle all the errors returned from the read_value call. - - match value { - // (Characteristic) Step 5.5.4. - // (Descriptor) Step 5.4.3. - Some(v) => return Ok(BluetoothResponse::ReadValue(v)), - - // (Characteristic) Step 4. - // (Descriptor) Step 4. - None => return Err(BluetoothError::InvalidState), - } - } - - // https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetoothremotegattcharacteristic-writevalue - // https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetoothremotegattdescriptor-writevalue - fn write_value(&mut self, id: String, value: Vec) -> BluetoothResponseResult { - // (Characteristic) Step 7.2: Missing because it is optional. - // (Descriptor) Step 7.1: Missing because it is optional. - let mut adapter = self.get_adapter()?; - - // (Characteristic) Step 7.3. - let mut result = self.get_gatt_characteristic(&mut adapter, &id) - .map(|c| c.write_value(value.clone())); - - // (Characteristic) TODO: Step 7.4: Handle all the errors returned from the write_value call. - - // (Descriptor) Step 7.2. - if result.is_none() { - result = self.get_gatt_descriptor(&mut adapter, &id) - .map(|d| d.write_value(value.clone())); - } - - // (Descriptor) TODO: Step 7.3: Handle all the errors returned from the write_value call. - - match result { - Some(v) => match v { - // (Characteristic) Step 7.5.3. - // (Descriptor) Step 7.4.3. - Ok(_) => return Ok(BluetoothResponse::WriteValue(value)), - - // (Characteristic) Step 7.1. - Err(_) => return Err(BluetoothError::NotSupported), - }, - - // (Characteristic) Step 6. - // (Descriptor) Step 6. - None => return Err(BluetoothError::InvalidState), - } - } - - // https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetoothremotegattcharacteristic-startnotifications - // https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetoothremotegattcharacteristic-stopnotifications - fn enable_notification(&mut self, id: String, enable: bool) -> BluetoothResponseResult { - // (StartNotifications) Step 3 - 4. - // (StopNotifications) Step 1 - 2. - if !self.characteristic_is_cached(&id) { - return Err(BluetoothError::InvalidState); - } - - // (StartNotification) TODO: Step 7: Missing because it is optional. - let mut adapter = self.get_adapter()?; - match self.get_gatt_characteristic(&mut adapter, &id) { - Some(c) => { - let result = match enable { - // (StartNotification) Step 8. - // TODO: Handle all the errors returned from the start_notify call. - true => c.start_notify(), - - // (StopNotification) Step 4. - false => c.stop_notify(), - }; - match result { - // (StartNotification) Step 11. - // (StopNotification) Step 5. - Ok(_) => return Ok(BluetoothResponse::EnableNotification(())), - - // (StartNotification) Step 5. - Err(_) => return Err(BluetoothError::NotSupported), - } - }, - // (StartNotification) Step 4. - None => return Err(BluetoothError::InvalidState), - } - } - - // https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetoothdevice-watchadvertisements - fn watch_advertisements(&mut self, _device_id: String) -> BluetoothResponseResult { - // Step 2. - // TODO: Implement this when supported in lower level - return Err(BluetoothError::NotSupported); - } - - // https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetooth-getavailability - fn get_availability(&mut self) -> BluetoothResponseResult { - Ok(BluetoothResponse::GetAvailability(self.get_adapter().is_ok())) - } -} diff --git a/servo/components/bluetooth/test.rs b/servo/components/bluetooth/test.rs deleted file mode 100644 index 29541123d4a1..000000000000 --- a/servo/components/bluetooth/test.rs +++ /dev/null @@ -1,522 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -use BluetoothManager; -use device::bluetooth::{BluetoothAdapter, BluetoothDevice}; -use device::bluetooth::{BluetoothGATTCharacteristic, BluetoothGATTDescriptor, BluetoothGATTService}; -use std::borrow::ToOwned; -use std::cell::RefCell; -use std::collections::{HashSet, HashMap}; -use std::error::Error; -use std::string::String; -use uuid::Uuid; - -thread_local!(pub static CACHED_IDS: RefCell> = RefCell::new(HashSet::new())); - -const ADAPTER_ERROR: &'static str = "No adapter found"; -const WRONG_DATA_SET_ERROR: &'static str = "Wrong data set name was provided"; -const READ_FLAG: &'static str = "read"; -const WRITE_FLAG: &'static str = "write"; -const NOTIFY_FLAG: &'static str = "notify"; - -// Adapter names -// https://cs.chromium.org/chromium/src/content/shell/browser/layout_test/layout_test_bluetooth_adapter_provider.h?l=65 -const NOT_PRESENT_ADAPTER: &'static str = "NotPresentAdapter"; -// https://cs.chromium.org/chromium/src/content/shell/browser/layout_test/layout_test_bluetooth_adapter_provider.h?l=83 -const NOT_POWERED_ADAPTER: &'static str = "NotPoweredAdapter"; -// https://cs.chromium.org/chromium/src/content/shell/browser/layout_test/layout_test_bluetooth_adapter_provider.h?l=118 -const EMPTY_ADAPTER: &'static str = "EmptyAdapter"; -// https://cs.chromium.org/chromium/src/content/shell/browser/layout_test/layout_test_bluetooth_adapter_provider.h?l=126 -const GLUCOSE_HEART_RATE_ADAPTER: &'static str = "GlucoseHeartRateAdapter"; -// https://cs.chromium.org/chromium/src/content/shell/browser/layout_test/layout_test_bluetooth_adapter_provider.h?l=135 -const UNICODE_DEVICE_ADAPTER: &'static str = "UnicodeDeviceAdapter"; -// https://cs.chromium.org/chromium/src/content/shell/browser/layout_test/layout_test_bluetooth_adapter_provider.h?l=205 -const MISSING_SERVICE_HEART_RATE_ADAPTER: &'static str = "MissingServiceHeartRateAdapter"; -// https://cs.chromium.org/chromium/src/content/shell/browser/layout_test/layout_test_bluetooth_adapter_provider.h?l=219 -const MISSING_CHARACTERISTIC_HEART_RATE_ADAPTER: &'static str = "MissingCharacteristicHeartRateAdapter"; -const MISSING_DESCRIPTOR_HEART_RATE_ADAPTER: &'static str = "MissingDescriptorHeartRateAdapter"; -// https://cs.chromium.org/chromium/src/content/shell/browser/layout_test/layout_test_bluetooth_adapter_provider.h?l=234 -const HEART_RATE_ADAPTER: &'static str = "HeartRateAdapter"; -// https://cs.chromium.org/chromium/src/content/shell/browser/layout_test/layout_test_bluetooth_adapter_provider.h?l=250 -const EMPTY_NAME_HEART_RATE_ADAPTER: &'static str = "EmptyNameHeartRateAdapter"; -// https://cs.chromium.org/chromium/src/content/shell/browser/layout_test/layout_test_bluetooth_adapter_provider.h?l=267 -const NO_NAME_HEART_RATE_ADAPTER: &'static str = "NoNameHeartRateAdapter"; -// https://cs.chromium.org/chromium/src/content/shell/browser/layout_test/layout_test_bluetooth_adapter_provider.h?l=284 -const TWO_HEART_RATE_SERVICES_ADAPTER: &'static str = "TwoHeartRateServicesAdapter"; -const BLOCKLIST_TEST_ADAPTER: &'static str = "BlocklistTestAdapter"; - -// Device names -const CONNECTABLE_DEVICE_NAME: &'static str = "Connectable Device"; -const EMPTY_DEVICE_NAME: &'static str = ""; -// https://webbluetoothcg.github.io/web-bluetooth/tests.html#glucosedevice -const GLUCOSE_DEVICE_NAME: &'static str = "Glucose Device"; -// https://webbluetoothcg.github.io/web-bluetooth/tests.html#heartratedevice -const HEART_RATE_DEVICE_NAME: &'static str = "Heart Rate Device"; -const UNICODE_DEVICE_NAME: &'static str = "❤❤❤❤❤❤❤❤❤"; - -// Device addresses -const CONNECTABLE_DEVICE_ADDRESS: &'static str = "00:00:00:00:00:04"; -// https://webbluetoothcg.github.io/web-bluetooth/tests.html#glucosedevice -const GLUCOSE_DEVICE_ADDRESS: &'static str = "00:00:00:00:00:02"; -// https://webbluetoothcg.github.io/web-bluetooth/tests.html#heartratedevice -const HEART_RATE_DEVICE_ADDRESS: &'static str = "00:00:00:00:00:03"; -const UNICODE_DEVICE_ADDRESS: &'static str = "00:00:00:00:00:01"; - -// Service UUIDs -const BLOCKLIST_TEST_SERVICE_UUID: &'static str = "611c954a-263b-4f4a-aab6-01ddb953f985"; -// https://www.bluetooth.com/specifications/gatt/viewer?attributeXmlFile=org.bluetooth.service.device_information.xml -const DEVICE_INFORMATION_UUID: &'static str = "0000180a-0000-1000-8000-00805f9b34fb"; -// https://www.bluetooth.com/specifications/gatt/viewer?attributeXmlFile=org.bluetooth.service.generic_access.xml -const GENERIC_ACCESS_SERVICE_UUID: &'static str = "00001800-0000-1000-8000-00805f9b34fb"; -// https://www.bluetooth.com/specifications/gatt/viewer?attributeXmlFile=org.bluetooth.service.glucose.xml -const GLUCOSE_SERVICE_UUID: &'static str = "00001808-0000-1000-8000-00805f9b34fb"; -// https://www.bluetooth.com/specifications/gatt/viewer?attributeXmlFile=org.bluetooth.service.heart_rate.xml -const HEART_RATE_SERVICE_UUID: &'static str = "0000180d-0000-1000-8000-00805f9b34fb"; -// https://www.bluetooth.com/specifications/gatt/ -// viewer?attributeXmlFile=org.bluetooth.service.human_interface_device.xml -const HUMAN_INTERFACE_DEVICE_SERVICE_UUID: &'static str = "00001812-0000-1000-8000-00805f9b34fb"; -// https://www.bluetooth.com/specifications/gatt/viewer?attributeXmlFile=org.bluetooth.service.tx_power.xml -const TX_POWER_SERVICE_UUID: &'static str = "00001804-0000-1000-8000-00805f9b34fb"; - -// Characteristic UUIDs -const BLOCKLIST_EXCLUDE_READS_CHARACTERISTIC_UUID: &'static str = "bad1c9a2-9a5b-4015-8b60-1579bbbf2135"; -// https://www.bluetooth.com/specifications/gatt/ -// viewer?attributeXmlFile=org.bluetooth.characteristic.body_sensor_location.xml -const BODY_SENSOR_LOCATION_CHARACTERISTIC_UUID: &'static str = "00002a38-0000-1000-8000-00805f9b34fb"; -// https://www.bluetooth.com/specifications/gatt/ -// viewer?attributeXmlFile=org.bluetooth.characteristic.gap.device_name.xml -const DEVICE_NAME_CHARACTERISTIC_UUID: &'static str = "00002a00-0000-1000-8000-00805f9b34fb"; -// https://www.bluetooth.com/specifications/gatt/ -// viewer?attributeXmlFile=org.bluetooth.characteristic.heart_rate_measurement.xml -const HEART_RATE_MEASUREMENT_CHARACTERISTIC_UUID: &'static str = "00002a37-0000-1000-8000-00805f9b34fb"; -// https://www.bluetooth.com/specifications/gatt/ -// viewer?attributeXmlFile=org.bluetooth.characteristic.gap.peripheral_privacy_flag.xml -const PERIPHERAL_PRIVACY_FLAG_CHARACTERISTIC_UUID: &'static str = "00002a02-0000-1000-8000-00805f9b34fb"; -// https://www.bluetooth.com/specifications/gatt/ -// viewer?attributeXmlFile=org.bluetooth.characteristic.serial_number_string.xml -const SERIAL_NUMBER_STRING_UUID: &'static str = "00002a25-0000-1000-8000-00805f9b34fb"; - -// Descriptor UUIDs -const BLOCKLIST_EXCLUDE_READS_DESCRIPTOR_UUID: &'static str = "aaaaaaaa-aaaa-1181-0510-810819516110"; -const BLOCKLIST_DESCRIPTOR_UUID: &'static str = "07711111-6104-0970-7011-1107105110aa"; -// https://www.bluetooth.com/specifications/gatt/ -// viewer?attributeXmlFile=org.bluetooth.descriptor.gatt.characteristic_user_description.xml -const CHARACTERISTIC_USER_DESCRIPTION_UUID: &'static str = "00002901-0000-1000-8000-00805f9b34fb"; -// https://www.bluetooth.com/specifications/gatt/ -// viewer?attributeXmlFile=org.bluetooth.descriptor.gatt.client_characteristic_configuration.xml -const CLIENT_CHARACTERISTIC_CONFIGURATION_UUID: &'static str = "00002902-0000-1000-8000-00805f9b34fb"; -// https://www.bluetooth.com/specifications/gatt/ -// viewer?attributeXmlFile=org.bluetooth.descriptor.number_of_digitals.xml -const NUMBER_OF_DIGITALS_UUID: &'static str = "00002909-0000-1000-8000-00805f9b34fb"; - -const HEART_RATE_DEVICE_NAME_DESCRIPTION: &'static str = "The name of this device."; - -fn generate_id() -> Uuid { - let mut id = Uuid::nil(); - let mut generated = false; - while !generated { - id = Uuid::new_v4(); - CACHED_IDS.with(|cache| - if !cache.borrow().contains(&id) { - cache.borrow_mut().insert(id.clone()); - generated = true; - } - ); - } - id -} - -// Set the adapter's name, is_powered and is_discoverable attributes -fn set_adapter(adapter: &BluetoothAdapter, adapter_name: String) -> Result<(), Box> { - adapter.set_name(adapter_name)?; - adapter.set_powered(true)?; - adapter.set_discoverable(true)?; - Ok(()) -} - -// Create Device -fn create_device(adapter: &BluetoothAdapter, - name: String, - address: String) - -> Result> { - let device = BluetoothDevice::create_mock_device(adapter.clone(), generate_id().to_string())?; - device.set_name(Some(name))?; - device.set_address(address)?; - device.set_connectable(true)?; - Ok(device) -} - -// Create Device with UUIDs -fn create_device_with_uuids(adapter: &BluetoothAdapter, - name: String, - address: String, - uuids: Vec) - -> Result> { - let device = create_device(adapter, name, address)?; - device.set_uuids(uuids)?; - Ok(device) -} - -// Create Service -fn create_service(device: &BluetoothDevice, - uuid: String) - -> Result> { - let service = BluetoothGATTService::create_mock_service(device.clone(), generate_id().to_string())?; - service.set_uuid(uuid)?; - Ok(service) -} - -// Create Characteristic -fn create_characteristic(service: &BluetoothGATTService, - uuid: String) - -> Result> { - let characteristic = - BluetoothGATTCharacteristic::create_mock_characteristic(service.clone(), generate_id().to_string())?; - characteristic.set_uuid(uuid)?; - Ok(characteristic) -} - -// Create Characteristic with value -fn create_characteristic_with_value(service: &BluetoothGATTService, - uuid: String, - value: Vec) - -> Result> { - let characteristic = create_characteristic(service, uuid)?; - characteristic.set_value(value)?; - Ok(characteristic) -} - -// Create Descriptor -fn create_descriptor(characteristic: &BluetoothGATTCharacteristic, - uuid: String) - -> Result> { - let descriptor = - BluetoothGATTDescriptor::create_mock_descriptor(characteristic.clone(), generate_id().to_string())?; - descriptor.set_uuid(uuid)?; - Ok(descriptor) -} - -// Create Descriptor with value -fn create_descriptor_with_value(characteristic: &BluetoothGATTCharacteristic, - uuid: String, - value: Vec) - -> Result> { - let descriptor = create_descriptor(characteristic, uuid)?; - descriptor.set_value(value)?; - Ok(descriptor) -} - -fn create_heart_rate_service(device: &BluetoothDevice, - empty: bool) - -> Result> { - // Heart Rate Service - let heart_rate_service = create_service(device, HEART_RATE_SERVICE_UUID.to_owned())?; - - if empty { - return Ok(heart_rate_service) - } - - // Heart Rate Measurement Characteristic - let heart_rate_measurement_characteristic = - create_characteristic_with_value(&heart_rate_service, - HEART_RATE_MEASUREMENT_CHARACTERISTIC_UUID.to_owned(), - vec![0])?; - heart_rate_measurement_characteristic.set_flags(vec![NOTIFY_FLAG.to_string(), - READ_FLAG.to_string(), - WRITE_FLAG.to_string()])?; - - // Body Sensor Location Characteristic 1 - let body_sensor_location_characteristic_1 = - create_characteristic_with_value(&heart_rate_service, - BODY_SENSOR_LOCATION_CHARACTERISTIC_UUID.to_owned(), - vec![49])?; - body_sensor_location_characteristic_1.set_flags(vec![READ_FLAG.to_string(), WRITE_FLAG.to_string()])?; - - // Body Sensor Location Characteristic 2 - let body_sensor_location_characteristic_2 = - create_characteristic_with_value(&heart_rate_service, - BODY_SENSOR_LOCATION_CHARACTERISTIC_UUID.to_owned(), - vec![50])?; - body_sensor_location_characteristic_2.set_flags(vec![READ_FLAG.to_string(), WRITE_FLAG.to_string()])?; - Ok(heart_rate_service) -} - -fn create_generic_access_service(device: &BluetoothDevice, - empty: bool) - -> Result> { - // Generic Access Service - let generic_access_service = - create_service(device, GENERIC_ACCESS_SERVICE_UUID.to_owned())?; - - if empty { - return Ok(generic_access_service) - } - - // Device Name Characteristic - let device_name_characteristic = - create_characteristic_with_value(&generic_access_service, - DEVICE_NAME_CHARACTERISTIC_UUID.to_owned(), - HEART_RATE_DEVICE_NAME.as_bytes().to_vec())?; - device_name_characteristic.set_flags(vec![READ_FLAG.to_string(), WRITE_FLAG.to_string()])?; - - // Number of Digitals descriptor - let number_of_digitals_descriptor_1 = - create_descriptor_with_value(&device_name_characteristic, - NUMBER_OF_DIGITALS_UUID.to_owned(), - vec![49])?; - number_of_digitals_descriptor_1.set_flags(vec![READ_FLAG.to_string(), WRITE_FLAG.to_string()])?; - - let number_of_digitals_descriptor_2 = - create_descriptor_with_value(&device_name_characteristic, - NUMBER_OF_DIGITALS_UUID.to_owned(), - vec![50])?; - number_of_digitals_descriptor_2.set_flags(vec![READ_FLAG.to_string(), WRITE_FLAG.to_string()])?; - - // Characteristic User Description Descriptor - let _characteristic_user_description = - create_descriptor_with_value(&device_name_characteristic, - CHARACTERISTIC_USER_DESCRIPTION_UUID.to_owned(), - HEART_RATE_DEVICE_NAME_DESCRIPTION.as_bytes().to_vec())?; - - // Client Characteristic Configuration descriptor - let _client_characteristic_configuration = - create_descriptor_with_value(&device_name_characteristic, - CLIENT_CHARACTERISTIC_CONFIGURATION_UUID.to_owned(), - vec![0])?; - - // Peripheral Privacy Flag Characteristic - let peripheral_privacy_flag_characteristic = - create_characteristic(&generic_access_service, PERIPHERAL_PRIVACY_FLAG_CHARACTERISTIC_UUID.to_owned())?; - peripheral_privacy_flag_characteristic - .set_flags(vec![READ_FLAG.to_string(), WRITE_FLAG.to_string()])?; - Ok(generic_access_service) -} - -// Create Heart Rate Device -fn create_heart_rate_device(adapter: &BluetoothAdapter, - empty: bool) - -> Result> { - // Heart Rate Device - let heart_rate_device = - create_device_with_uuids(adapter, - HEART_RATE_DEVICE_NAME.to_owned(), - HEART_RATE_DEVICE_ADDRESS.to_owned(), - vec![GENERIC_ACCESS_SERVICE_UUID.to_owned(), - HEART_RATE_SERVICE_UUID.to_owned()])?; - - if empty { - return Ok(heart_rate_device); - } - - // Generic Access Service - let _generic_access_service = create_generic_access_service(&heart_rate_device, false)?; - - // Heart Rate Service - let _heart_rate_service = create_heart_rate_service(&heart_rate_device, false)?; - - Ok(heart_rate_device) -} - -fn create_missing_characterisitc_heart_rate_device(adapter: &BluetoothAdapter) -> Result<(), Box> { - let heart_rate_device_empty = create_heart_rate_device(adapter, true)?; - - let _generic_access_service_empty = create_generic_access_service(&heart_rate_device_empty, true)?; - - let _heart_rate_service_empty = create_heart_rate_service(&heart_rate_device_empty, true)?; - - Ok(()) -} - -fn create_missing_descriptor_heart_rate_device(adapter: &BluetoothAdapter) -> Result<(), Box> { - let heart_rate_device_empty = create_heart_rate_device(adapter, true)?; - - let generic_access_service_empty = create_generic_access_service(&heart_rate_device_empty, true)?; - - let _device_name_characteristic = - create_characteristic_with_value(&generic_access_service_empty, - DEVICE_NAME_CHARACTERISTIC_UUID.to_owned(), - HEART_RATE_DEVICE_NAME.as_bytes().to_vec())?; - - let peripheral_privacy_flag_characteristic = - create_characteristic(&generic_access_service_empty, - PERIPHERAL_PRIVACY_FLAG_CHARACTERISTIC_UUID.to_owned())?; - peripheral_privacy_flag_characteristic.set_flags(vec![READ_FLAG.to_string(), WRITE_FLAG.to_string()])?; - - let _heart_rate_service = create_heart_rate_service(&heart_rate_device_empty, false)?; - - Ok(()) -} - -fn create_two_heart_rate_services_device(adapter: &BluetoothAdapter) -> Result<(), Box> { - let heart_rate_device_empty = create_heart_rate_device(adapter, true)?; - - heart_rate_device_empty.set_uuids(vec![GENERIC_ACCESS_SERVICE_UUID.to_owned(), - HEART_RATE_SERVICE_UUID.to_owned(), - HEART_RATE_SERVICE_UUID.to_owned()])?; - - let _generic_access_service = create_generic_access_service(&heart_rate_device_empty, false)?; - - let heart_rate_service_empty_1 = create_heart_rate_service(&heart_rate_device_empty, true)?; - - let heart_rate_service_empty_2 = create_heart_rate_service(&heart_rate_device_empty, true)?; - - let heart_rate_measurement_characteristic = - create_characteristic_with_value(&heart_rate_service_empty_1, - HEART_RATE_MEASUREMENT_CHARACTERISTIC_UUID.to_owned(), - vec![0])?; - heart_rate_measurement_characteristic.set_flags(vec![NOTIFY_FLAG.to_string()])?; - - let _body_sensor_location_characteristic_1 = - create_characteristic_with_value(&heart_rate_service_empty_1, - BODY_SENSOR_LOCATION_CHARACTERISTIC_UUID.to_owned(), - vec![49])?; - - let _body_sensor_location_characteristic_2 = - create_characteristic_with_value(&heart_rate_service_empty_2, - BODY_SENSOR_LOCATION_CHARACTERISTIC_UUID.to_owned(), - vec![50])?; - Ok(()) -} - -fn create_blocklisted_device(adapter: &BluetoothAdapter) -> Result<(), Box> { - let connectable_device = - create_device_with_uuids(adapter, - CONNECTABLE_DEVICE_NAME.to_owned(), - CONNECTABLE_DEVICE_ADDRESS.to_owned(), - vec![BLOCKLIST_TEST_SERVICE_UUID.to_owned(), - DEVICE_INFORMATION_UUID.to_owned(), - GENERIC_ACCESS_SERVICE_UUID.to_owned(), - HEART_RATE_SERVICE_UUID.to_owned(), - HUMAN_INTERFACE_DEVICE_SERVICE_UUID.to_owned()])?; - - let blocklist_test_service = create_service(&connectable_device, BLOCKLIST_TEST_SERVICE_UUID.to_owned())?; - - let blocklist_exclude_reads_characteristic = - create_characteristic(&blocklist_test_service, - BLOCKLIST_EXCLUDE_READS_CHARACTERISTIC_UUID.to_owned())?; - blocklist_exclude_reads_characteristic - .set_flags(vec![READ_FLAG.to_string(), WRITE_FLAG.to_string()])?; - - let _blocklist_exclude_reads_descriptor = - create_descriptor_with_value(&blocklist_exclude_reads_characteristic, - BLOCKLIST_EXCLUDE_READS_DESCRIPTOR_UUID.to_owned(), - vec![54; 3])?; - - let _blocklist_descriptor = - create_descriptor_with_value(&blocklist_exclude_reads_characteristic, - BLOCKLIST_DESCRIPTOR_UUID.to_owned(), - vec![54; 3])?; - - let device_information_service = create_service(&connectable_device, DEVICE_INFORMATION_UUID.to_owned())?; - - let _serial_number_string_characteristic = - create_characteristic(&device_information_service, SERIAL_NUMBER_STRING_UUID.to_owned())?; - - let _generic_access_service = create_generic_access_service(&connectable_device, false)?; - - let _heart_rate_service = create_heart_rate_service(&connectable_device, false)?; - - let _human_interface_device_service = - create_service(&connectable_device, HUMAN_INTERFACE_DEVICE_SERVICE_UUID.to_owned())?; - Ok(()) -} - -fn create_glucose_heart_rate_devices(adapter: &BluetoothAdapter) -> Result<(), Box> { - let glucose_devie = create_device_with_uuids(adapter, - GLUCOSE_DEVICE_NAME.to_owned(), - GLUCOSE_DEVICE_ADDRESS.to_owned(), - vec![GLUCOSE_SERVICE_UUID.to_owned(), - TX_POWER_SERVICE_UUID.to_owned()])?; - - let heart_rate_device_empty = create_heart_rate_device(adapter, true)?; - - let mut manufacturer_dta = HashMap::new(); - manufacturer_dta.insert(17, vec![1, 2, 3]); - glucose_devie.set_manufacturer_data(manufacturer_dta)?; - - let mut service_data = HashMap::new(); - service_data.insert(GLUCOSE_SERVICE_UUID.to_owned(), vec![1, 2, 3]); - glucose_devie.set_service_data(service_data)?; - - service_data = HashMap::new(); - service_data.insert(HEART_RATE_SERVICE_UUID.to_owned(), vec![1, 2, 3]); - heart_rate_device_empty.set_service_data(service_data)?; - Ok(()) -} - -pub fn test(manager: &mut BluetoothManager, data_set_name: String) -> Result<(), Box> { - let may_existing_adapter = manager.get_or_create_adapter(); - let adapter = match may_existing_adapter.as_ref() { - Some(adapter) => adapter, - None => return Err(Box::from(ADAPTER_ERROR.to_string())), - }; - match data_set_name.as_str() { - NOT_PRESENT_ADAPTER => { - set_adapter(adapter, NOT_PRESENT_ADAPTER.to_owned())?; - adapter.set_present(false)?; - }, - NOT_POWERED_ADAPTER => { - set_adapter(adapter, NOT_POWERED_ADAPTER.to_owned())?; - adapter.set_powered(false)?; - }, - EMPTY_ADAPTER => { - set_adapter(adapter, EMPTY_ADAPTER.to_owned())?; - }, - GLUCOSE_HEART_RATE_ADAPTER => { - set_adapter(adapter, GLUCOSE_HEART_RATE_ADAPTER.to_owned())?; - let _ = create_glucose_heart_rate_devices(adapter)?; - }, - UNICODE_DEVICE_ADAPTER => { - set_adapter(adapter, UNICODE_DEVICE_ADAPTER.to_owned())?; - - let _unicode_device = create_device(adapter, - UNICODE_DEVICE_NAME.to_owned(), - UNICODE_DEVICE_ADDRESS.to_owned())?; - }, - MISSING_SERVICE_HEART_RATE_ADAPTER => { - set_adapter(adapter, MISSING_SERVICE_HEART_RATE_ADAPTER.to_owned())?; - - let _heart_rate_device_empty = create_heart_rate_device(adapter, true)?; - }, - MISSING_CHARACTERISTIC_HEART_RATE_ADAPTER => { - set_adapter(adapter, MISSING_CHARACTERISTIC_HEART_RATE_ADAPTER.to_owned())?; - - let _ = create_missing_characterisitc_heart_rate_device(adapter)?; - }, - MISSING_DESCRIPTOR_HEART_RATE_ADAPTER => { - set_adapter(adapter, MISSING_DESCRIPTOR_HEART_RATE_ADAPTER.to_owned())?; - - let _ = create_missing_descriptor_heart_rate_device(adapter)?; - }, - HEART_RATE_ADAPTER => { - set_adapter(adapter, HEART_RATE_ADAPTER.to_owned())?; - - let _heart_rate_device = create_heart_rate_device(adapter, false)?; - }, - EMPTY_NAME_HEART_RATE_ADAPTER => { - set_adapter(adapter, EMPTY_NAME_HEART_RATE_ADAPTER.to_owned())?; - - let heart_rate_device = create_heart_rate_device(adapter, false)?; - heart_rate_device.set_name(Some(EMPTY_DEVICE_NAME.to_owned()))?; - }, - NO_NAME_HEART_RATE_ADAPTER => { - set_adapter(adapter, NO_NAME_HEART_RATE_ADAPTER.to_owned())?; - - let heart_rate_device = create_heart_rate_device(adapter, false)?; - heart_rate_device.set_name(None)?; - }, - TWO_HEART_RATE_SERVICES_ADAPTER => { - set_adapter(adapter, TWO_HEART_RATE_SERVICES_ADAPTER.to_owned())?; - - let _ = create_two_heart_rate_services_device(adapter)?; - }, - BLOCKLIST_TEST_ADAPTER => { - set_adapter(adapter, BLOCKLIST_TEST_ADAPTER.to_owned())?; - - let _ = create_blocklisted_device(adapter)?; - }, - _ => return Err(Box::from(WRONG_DATA_SET_ERROR.to_string())), - } - return Ok(()); -} diff --git a/servo/components/bluetooth_traits/Cargo.toml b/servo/components/bluetooth_traits/Cargo.toml deleted file mode 100644 index 52b01c33c673..000000000000 --- a/servo/components/bluetooth_traits/Cargo.toml +++ /dev/null @@ -1,16 +0,0 @@ -[package] -name = "bluetooth_traits" -version = "0.0.1" -authors = ["The Servo Project Developers"] -license = "MPL-2.0" -publish = false - -[lib] -name = "bluetooth_traits" -path = "lib.rs" - -[dependencies] -ipc-channel = "0.10" -regex = "0.2" -serde = "1.0" -servo_config = {path = "../config"} diff --git a/servo/components/bluetooth_traits/blocklist.rs b/servo/components/bluetooth_traits/blocklist.rs deleted file mode 100644 index 26df3413c108..000000000000 --- a/servo/components/bluetooth_traits/blocklist.rs +++ /dev/null @@ -1,124 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -use regex::Regex; -use servo_config::resource_files::read_resource_file; -use std::cell::RefCell; -use std::collections::HashMap; -use std::io::BufRead; -use std::string::String; - -const BLOCKLIST_FILE: &'static str = "gatt_blocklist.txt"; -const BLOCKLIST_FILE_NOT_FOUND: &'static str = "Could not find gatt_blocklist.txt file"; -const EXCLUDE_READS: &'static str = "exclude-reads"; -const EXCLUDE_WRITES: &'static str = "exclude-writes"; -const VALID_UUID_REGEX: &'static str = "^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}"; - -thread_local!(pub static BLUETOOTH_BLOCKLIST: RefCell = - RefCell::new(BluetoothBlocklist(parse_blocklist()))); - -pub fn uuid_is_blocklisted(uuid: &str, exclude_type: Blocklist) -> bool { - BLUETOOTH_BLOCKLIST.with(|blist| { - match exclude_type { - Blocklist::All => { - blist.borrow().is_blocklisted(uuid) - }, - Blocklist::Reads => { - blist.borrow().is_blocklisted_for_reads(uuid) - } - Blocklist::Writes => { - blist.borrow().is_blocklisted_for_writes(uuid) - } - } - }) -} - -pub struct BluetoothBlocklist(Option>); - -#[derive(Eq, PartialEq)] -pub enum Blocklist { - All, // Read and Write - Reads, - Writes, -} - -impl BluetoothBlocklist { - // https://webbluetoothcg.github.io/web-bluetooth/#blocklisted - pub fn is_blocklisted(&self, uuid: &str) -> bool { - match self.0 { - Some(ref map) => map.get(uuid).map_or(false, |et| et.eq(&Blocklist::All)), - None => false, - } - } - - // https://webbluetoothcg.github.io/web-bluetooth/#blocklisted-for-reads - pub fn is_blocklisted_for_reads(&self, uuid: &str) -> bool { - match self.0 { - Some(ref map) => map.get(uuid).map_or(false, |et| et.eq(&Blocklist::All) || - et.eq(&Blocklist::Reads)), - None => false, - } - } - - // https://webbluetoothcg.github.io/web-bluetooth/#blocklisted-for-writes - pub fn is_blocklisted_for_writes(&self, uuid: &str) -> bool { - match self.0 { - Some(ref map) => map.get(uuid).map_or(false, |et| et.eq(&Blocklist::All) || - et.eq(&Blocklist::Writes)), - None => false, - } - } -} - -// https://webbluetoothcg.github.io/web-bluetooth/#parsing-the-blocklist -fn parse_blocklist() -> Option> { - // Step 1 missing, currently we parse ./resources/gatt_blocklist.txt. - let valid_uuid_regex = Regex::new(VALID_UUID_REGEX).unwrap(); - let content = read_resource_file(BLOCKLIST_FILE).expect(BLOCKLIST_FILE_NOT_FOUND); - // Step 3 - let mut result = HashMap::new(); - // Step 2 and 4 - for line in content.lines() { - let line = match line { - Ok(l) => l, - Err(_) => return None, - }; - // Step 4.1 - if line.is_empty() || line.starts_with('#') { - continue; - } - let mut exclude_type = Blocklist::All; - let mut words = line.split_whitespace(); - let uuid = match words.next() { - Some(uuid) => uuid, - None => continue, - }; - if !valid_uuid_regex.is_match(uuid) { - return None; - } - match words.next() { - // Step 4.2 We already have an initialized exclude_type variable with Blocklist::All. - None => {}, - // Step 4.3 - Some(EXCLUDE_READS) => { - exclude_type = Blocklist::Reads; - }, - Some(EXCLUDE_WRITES) => { - exclude_type = Blocklist::Writes; - }, - // Step 4.4 - _ => { - return None; - }, - } - // Step 4.5 - if result.contains_key(uuid) { - return None; - } - // Step 4.6 - result.insert(uuid.to_string(), exclude_type); - } - // Step 5 - return Some(result); -} diff --git a/servo/components/bluetooth_traits/lib.rs b/servo/components/bluetooth_traits/lib.rs deleted file mode 100644 index 31e644bd863f..000000000000 --- a/servo/components/bluetooth_traits/lib.rs +++ /dev/null @@ -1,112 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -extern crate ipc_channel; -extern crate regex; -#[macro_use] extern crate serde; -extern crate servo_config; - -pub mod blocklist; -pub mod scanfilter; - -use ipc_channel::ipc::IpcSender; -use scanfilter::{BluetoothScanfilterSequence, RequestDeviceoptions}; - -#[derive(Deserialize, Serialize)] -pub enum BluetoothError { - Type(String), - Network, - NotFound, - NotSupported, - Security, - InvalidState, -} - -#[derive(Deserialize, Serialize)] -pub enum GATTType { - PrimaryService, - Characteristic, - IncludedService, - Descriptor, -} - -#[derive(Deserialize, Serialize)] -pub struct BluetoothDeviceMsg { - // Bluetooth Device properties - pub id: String, - pub name: Option, -} - -#[derive(Deserialize, Serialize)] -pub struct BluetoothServiceMsg { - pub uuid: String, - pub is_primary: bool, - pub instance_id: String, -} - -#[derive(Deserialize, Serialize)] -pub struct BluetoothCharacteristicMsg { - // Characteristic - pub uuid: String, - pub instance_id: String, - // Characteristic properties - pub broadcast: bool, - pub read: bool, - pub write_without_response: bool, - pub write: bool, - pub notify: bool, - pub indicate: bool, - pub authenticated_signed_writes: bool, - pub reliable_write: bool, - pub writable_auxiliaries: bool, -} - -#[derive(Deserialize, Serialize)] -pub struct BluetoothDescriptorMsg { - pub uuid: String, - pub instance_id: String, -} - -pub type BluetoothServicesMsg = Vec; - -pub type BluetoothCharacteristicsMsg = Vec; - -pub type BluetoothDescriptorsMsg = Vec; - -pub type BluetoothResult = Result; - -pub type BluetoothResponseResult = Result; - -#[derive(Deserialize, Serialize)] -pub enum BluetoothRequest { - RequestDevice(RequestDeviceoptions, IpcSender), - GATTServerConnect(String, IpcSender), - GATTServerDisconnect(String, IpcSender>), - GetGATTChildren(String, Option, bool, GATTType, IpcSender), - ReadValue(String, IpcSender), - WriteValue(String, Vec, IpcSender), - EnableNotification(String, bool, IpcSender), - WatchAdvertisements(String, IpcSender), - SetRepresentedToNull(Vec, Vec, Vec), - IsRepresentedDeviceNull(String, IpcSender), - GetAvailability(IpcSender), - MatchesFilter(String, BluetoothScanfilterSequence, IpcSender>), - Test(String, IpcSender>), - Exit, -} - -#[derive(Deserialize, Serialize)] -pub enum BluetoothResponse { - RequestDevice(BluetoothDeviceMsg), - GATTServerConnect(bool), - GetPrimaryServices(BluetoothServicesMsg, bool), - GetIncludedServices(BluetoothServicesMsg, bool), - GetCharacteristics(BluetoothCharacteristicsMsg, bool), - GetDescriptors(BluetoothDescriptorsMsg, bool), - ReadValue(Vec), - WriteValue(Vec), - EnableNotification(()), - WatchAdvertisements(()), - GetAvailability(bool), -} diff --git a/servo/components/bluetooth_traits/scanfilter.rs b/servo/components/bluetooth_traits/scanfilter.rs deleted file mode 100644 index a3b33f684c9f..000000000000 --- a/servo/components/bluetooth_traits/scanfilter.rs +++ /dev/null @@ -1,137 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -use std::collections::{HashMap, HashSet}; -use std::slice::Iter; - -// A device name can never be longer than 29 bytes. An adv packet is at most -// 31 bytes long. The length and identifier of the length field take 2 bytes. -// That leaves 29 bytes for the name. -const MAX_NAME_LENGTH: usize = 29; - -#[derive(Deserialize, Serialize)] -pub struct ServiceUUIDSequence(Vec); - -impl ServiceUUIDSequence { - pub fn new(vec: Vec) -> ServiceUUIDSequence { - ServiceUUIDSequence(vec) - } - - fn get_services_set(&self) -> HashSet { - self.0.iter().map(String::clone).collect() - } -} - -type ManufacturerData = HashMap, Vec)>; -type ServiceData = HashMap, Vec)>; - -#[derive(Deserialize, Serialize)] -pub struct BluetoothScanfilter { - name: Option, - name_prefix: String, - services: ServiceUUIDSequence, - manufacturer_data: Option, - service_data: Option, -} - -impl BluetoothScanfilter { - pub fn new(name: Option, - name_prefix: String, - services: Vec, - manufacturer_data: Option, - service_data: Option) - -> BluetoothScanfilter { - BluetoothScanfilter { - name: name, - name_prefix: name_prefix, - services: ServiceUUIDSequence::new(services), - manufacturer_data: manufacturer_data, - service_data: service_data, - } - } - - pub fn get_name(&self) -> Option<&str> { - self.name.as_ref().map(|s| s.as_str()) - } - - pub fn get_name_prefix(&self) -> &str { - &self.name_prefix - } - - pub fn get_services(&self) -> &[String] { - &self.services.0 - } - - pub fn get_manufacturer_data(&self) -> Option<&ManufacturerData> { - self.manufacturer_data.as_ref() - } - - pub fn get_service_data(&self) -> Option<&ServiceData> { - self.service_data.as_ref() - } - - pub fn is_empty_or_invalid(&self) -> bool { - (self.name.is_none() && - self.name_prefix.is_empty() && - self.get_services().is_empty() && - self.manufacturer_data.is_none() && - self.service_data.is_none()) || - self.get_name().unwrap_or("").len() > MAX_NAME_LENGTH || - self.name_prefix.len() > MAX_NAME_LENGTH - } -} - -#[derive(Deserialize, Serialize)] -pub struct BluetoothScanfilterSequence(Vec); - -impl BluetoothScanfilterSequence { - pub fn new(vec: Vec) -> BluetoothScanfilterSequence { - BluetoothScanfilterSequence(vec) - } - - pub fn has_empty_or_invalid_filter(&self) -> bool { - self.0.iter().any(BluetoothScanfilter::is_empty_or_invalid) - } - - pub fn iter(&self) -> Iter { - self.0.iter() - } - - fn get_services_set(&self) -> HashSet { - self.iter().flat_map(|filter| filter.services.get_services_set()).collect() - } - - fn is_empty(&self) -> bool { - self.0.is_empty() - } -} - -#[derive(Deserialize, Serialize)] -pub struct RequestDeviceoptions { - filters: BluetoothScanfilterSequence, - optional_services: ServiceUUIDSequence, -} - -impl RequestDeviceoptions { - pub fn new(filters: BluetoothScanfilterSequence, - services: ServiceUUIDSequence) - -> RequestDeviceoptions { - RequestDeviceoptions { - filters: filters, - optional_services: services, - } - } - - pub fn get_filters(&self) -> &BluetoothScanfilterSequence { - &self.filters - } - - pub fn get_services_set(&self) -> HashSet { - &self.filters.get_services_set() | &self.optional_services.get_services_set() - } - - pub fn is_accepting_all_devices(&self) -> bool { - self.filters.is_empty() - } -} diff --git a/servo/components/canvas/Cargo.toml b/servo/components/canvas/Cargo.toml deleted file mode 100644 index b673e430da9b..000000000000 --- a/servo/components/canvas/Cargo.toml +++ /dev/null @@ -1,27 +0,0 @@ -[package] -name = "canvas" -version = "0.0.1" -authors = ["The Servo Project Developers"] -license = "MPL-2.0" -publish = false - -[lib] -name = "canvas" -path = "lib.rs" - -[dependencies] -azure = {git = "https://github.com/servo/rust-azure"} -canvas_traits = {path = "../canvas_traits"} -compositing = {path = "../compositing"} -cssparser = "0.23.0" -euclid = "0.17" -fnv = "1.0" -gleam = "0.4.29" -ipc-channel = "0.10" -log = "0.4" -num-traits = "0.1.32" -offscreen_gl_context = { version = "0.15", features = ["serde", "osmesa"] } -serde_bytes = "0.10" -servo_config = {path = "../config"} -webrender = {git = "https://github.com/servo/webrender"} -webrender_api = {git = "https://github.com/servo/webrender", features = ["ipc"]} diff --git a/servo/components/canvas/canvas_paint_thread.rs b/servo/components/canvas/canvas_paint_thread.rs deleted file mode 100644 index cf1e3a79b62d..000000000000 --- a/servo/components/canvas/canvas_paint_thread.rs +++ /dev/null @@ -1,1138 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -use azure::azure::AzFloat; -use azure::azure_hl::{AntialiasMode, CapStyle, CompositionOp, JoinStyle}; -use azure::azure_hl::{BackendType, DrawOptions, DrawTarget, Pattern, StrokeOptions, SurfaceFormat}; -use azure::azure_hl::{Color, ColorPattern, DrawSurfaceOptions, Filter, PathBuilder}; -use azure::azure_hl::{ExtendMode, GradientStop, LinearGradientPattern, RadialGradientPattern}; -use azure::azure_hl::SurfacePattern; -use canvas_traits::canvas::*; -use cssparser::RGBA; -use euclid::{Transform2D, Point2D, Vector2D, Rect, Size2D}; -use ipc_channel::ipc::{self, IpcSender}; -use num_traits::ToPrimitive; -use serde_bytes::ByteBuf; -use std::borrow::ToOwned; -use std::mem; -use std::sync::Arc; -use std::thread; -use webrender_api; - -impl<'a> CanvasPaintThread<'a> { - /// It reads image data from the canvas - /// canvas_size: The size of the canvas we're reading from - /// read_rect: The area of the canvas we want to read from - fn read_pixels(&self, read_rect: Rect, canvas_size: Size2D) -> Vec{ - let canvas_size = canvas_size.to_i32(); - let canvas_rect = Rect::new(Point2D::new(0i32, 0i32), canvas_size); - let src_read_rect = canvas_rect.intersection(&read_rect).unwrap_or(Rect::zero()); - - let mut image_data = vec![]; - if src_read_rect.is_empty() || canvas_size.width <= 0 && canvas_size.height <= 0 { - return image_data; - } - - let data_surface = self.drawtarget.snapshot().get_data_surface(); - let mut src_data = Vec::new(); - data_surface.with_data(|element| { src_data = element.to_vec(); }); - let stride = data_surface.stride(); - - //start offset of the copyable rectangle - let mut src = (src_read_rect.origin.y * stride + src_read_rect.origin.x * 4) as usize; - //copy the data to the destination vector - for _ in 0..src_read_rect.size.height { - let row = &src_data[src .. src + (4 * src_read_rect.size.width) as usize]; - image_data.extend_from_slice(row); - src += stride as usize; - } - - image_data - } -} - -pub struct CanvasPaintThread<'a> { - drawtarget: DrawTarget, - /// TODO(pcwalton): Support multiple paths. - path_builder: PathBuilder, - state: CanvasPaintState<'a>, - saved_states: Vec>, - webrender_api: webrender_api::RenderApi, - image_key: Option, - /// An old webrender image key that can be deleted when the next epoch ends. - old_image_key: Option, - /// An old webrender image key that can be deleted when the current epoch ends. - very_old_image_key: Option, - canvas_id: CanvasId, -} - -#[derive(Clone)] -struct CanvasPaintState<'a> { - draw_options: DrawOptions, - fill_style: Pattern, - stroke_style: Pattern, - stroke_opts: StrokeOptions<'a>, - /// The current 2D transform matrix. - transform: Transform2D, - shadow_offset_x: f64, - shadow_offset_y: f64, - shadow_blur: f64, - shadow_color: Color, -} - -impl<'a> CanvasPaintState<'a> { - fn new(antialias: AntialiasMode) -> CanvasPaintState<'a> { - CanvasPaintState { - draw_options: DrawOptions::new(1.0, CompositionOp::Over, antialias), - fill_style: Pattern::Color(ColorPattern::new(Color::black())), - stroke_style: Pattern::Color(ColorPattern::new(Color::black())), - stroke_opts: StrokeOptions::new(1.0, JoinStyle::MiterOrBevel, CapStyle::Butt, 10.0, &[]), - transform: Transform2D::identity(), - shadow_offset_x: 0.0, - shadow_offset_y: 0.0, - shadow_blur: 0.0, - shadow_color: Color::transparent(), - } - } -} - -impl<'a> CanvasPaintThread<'a> { - fn new(size: Size2D, - webrender_api_sender: webrender_api::RenderApiSender, - antialias: AntialiasMode, - canvas_id: CanvasId) -> CanvasPaintThread<'a> { - let draw_target = CanvasPaintThread::create(size); - let path_builder = draw_target.create_path_builder(); - let webrender_api = webrender_api_sender.create_api(); - CanvasPaintThread { - drawtarget: draw_target, - path_builder: path_builder, - state: CanvasPaintState::new(antialias), - saved_states: vec![], - webrender_api: webrender_api, - image_key: None, - old_image_key: None, - very_old_image_key: None, - canvas_id: canvas_id, - } - } - - /// Creates a new `CanvasPaintThread` and returns an `IpcSender` to - /// communicate with it. - pub fn start(size: Size2D, - webrender_api_sender: webrender_api::RenderApiSender, - antialias: bool, - canvas_id: CanvasId) - -> IpcSender { - let (sender, receiver) = ipc::channel::().unwrap(); - let antialias = if antialias { - AntialiasMode::Default - } else { - AntialiasMode::None - }; - thread::Builder::new().name("CanvasThread".to_owned()).spawn(move || { - let mut painter = CanvasPaintThread::new(size, webrender_api_sender, antialias, canvas_id); - loop { - let msg = receiver.recv(); - match msg.unwrap() { - CanvasMsg::Canvas2d(message, canvas_id) => { - assert!(canvas_id == painter.canvas_id); - match message { - Canvas2dMsg::FillText(text, x, y, max_width) => painter.fill_text(text, x, y, max_width), - Canvas2dMsg::FillRect(ref rect) => painter.fill_rect(rect), - Canvas2dMsg::StrokeRect(ref rect) => painter.stroke_rect(rect), - Canvas2dMsg::ClearRect(ref rect) => painter.clear_rect(rect), - Canvas2dMsg::BeginPath => painter.begin_path(), - Canvas2dMsg::ClosePath => painter.close_path(), - Canvas2dMsg::Fill => painter.fill(), - Canvas2dMsg::Stroke => painter.stroke(), - Canvas2dMsg::Clip => painter.clip(), - Canvas2dMsg::IsPointInPath(x, y, fill_rule, chan) => { - painter.is_point_in_path(x, y, fill_rule, chan) - }, - Canvas2dMsg::DrawImage( - imagedata, - image_size, - dest_rect, - source_rect, - smoothing_enabled, - ) => { - painter.draw_image( - imagedata.into(), - image_size, - dest_rect, - source_rect, - smoothing_enabled, - ) - } - Canvas2dMsg::DrawImageSelf(image_size, dest_rect, source_rect, smoothing_enabled) => { - painter.draw_image_self(image_size, dest_rect, source_rect, smoothing_enabled) - } - Canvas2dMsg::DrawImageInOther( - renderer, other_canvas_id, image_size, dest_rect, source_rect, smoothing, sender - ) => { - painter.draw_image_in_other( - renderer, other_canvas_id, image_size, dest_rect, source_rect, smoothing, sender) - } - Canvas2dMsg::MoveTo(ref point) => painter.move_to(point), - Canvas2dMsg::LineTo(ref point) => painter.line_to(point), - Canvas2dMsg::Rect(ref rect) => painter.rect(rect), - Canvas2dMsg::QuadraticCurveTo(ref cp, ref pt) => { - painter.quadratic_curve_to(cp, pt) - } - Canvas2dMsg::BezierCurveTo(ref cp1, ref cp2, ref pt) => { - painter.bezier_curve_to(cp1, cp2, pt) - } - Canvas2dMsg::Arc(ref center, radius, start, end, ccw) => { - painter.arc(center, radius, start, end, ccw) - } - Canvas2dMsg::ArcTo(ref cp1, ref cp2, radius) => { - painter.arc_to(cp1, cp2, radius) - } - Canvas2dMsg::Ellipse(ref center, radius_x, radius_y, rotation, start, end, ccw) => { - painter.ellipse(center, radius_x, radius_y, rotation, start, end, ccw) - } - Canvas2dMsg::RestoreContext => painter.restore_context_state(), - Canvas2dMsg::SaveContext => painter.save_context_state(), - Canvas2dMsg::SetFillStyle(style) => painter.set_fill_style(style), - Canvas2dMsg::SetStrokeStyle(style) => painter.set_stroke_style(style), - Canvas2dMsg::SetLineWidth(width) => painter.set_line_width(width), - Canvas2dMsg::SetLineCap(cap) => painter.set_line_cap(cap), - Canvas2dMsg::SetLineJoin(join) => painter.set_line_join(join), - Canvas2dMsg::SetMiterLimit(limit) => painter.set_miter_limit(limit), - Canvas2dMsg::SetTransform(ref matrix) => painter.set_transform(matrix), - Canvas2dMsg::SetGlobalAlpha(alpha) => painter.set_global_alpha(alpha), - Canvas2dMsg::SetGlobalComposition(op) => painter.set_global_composition(op), - Canvas2dMsg::GetImageData(dest_rect, canvas_size, chan) - => painter.image_data(dest_rect, canvas_size, chan), - Canvas2dMsg::PutImageData( - imagedata, - offset, - image_data_size, - dirty_rect, - ) => { - painter.put_image_data( - imagedata.into(), - offset, - image_data_size, - dirty_rect, - ) - } - Canvas2dMsg::SetShadowOffsetX(value) => painter.set_shadow_offset_x(value), - Canvas2dMsg::SetShadowOffsetY(value) => painter.set_shadow_offset_y(value), - Canvas2dMsg::SetShadowBlur(value) => painter.set_shadow_blur(value), - Canvas2dMsg::SetShadowColor(ref color) => painter.set_shadow_color(color.to_azure_style()), - } - }, - CanvasMsg::Close(canvas_id) =>{ - assert!(canvas_id == painter.canvas_id); - break; - }, - CanvasMsg::Recreate(size, canvas_id) =>{ - assert!(canvas_id == painter.canvas_id); - painter.recreate(size); - }, - CanvasMsg::FromScript(message, canvas_id) => { - assert!(canvas_id == painter.canvas_id); - match message { - FromScriptMsg::SendPixels(chan) => { - painter.send_pixels(chan) - } - } - }, - CanvasMsg::FromLayout(message, canvas_id) => { - assert!(canvas_id == painter.canvas_id); - match message { - FromLayoutMsg::SendData(chan) => { - painter.send_data(chan) - } - } - }, - } - } - }).expect("Thread spawning failed"); - - sender - } - - fn save_context_state(&mut self) { - self.saved_states.push(self.state.clone()); - } - - fn restore_context_state(&mut self) { - if let Some(state) = self.saved_states.pop() { - mem::replace(&mut self.state, state); - self.drawtarget.set_transform(&self.state.transform); - self.drawtarget.pop_clip(); - } - } - - fn fill_text(&self, text: String, x: f64, y: f64, max_width: Option) { - error!("Unimplemented canvas2d.fillText. Values received: {}, {}, {}, {:?}.", text, x, y, max_width); - } - - fn fill_rect(&self, rect: &Rect) { - if is_zero_size_gradient(&self.state.fill_style) { - return; // Paint nothing if gradient size is zero. - } - - let draw_rect = Rect::new(rect.origin, - match self.state.fill_style { - Pattern::Surface(ref surface) => { - let surface_size = surface.size(); - match (surface.repeat_x, surface.repeat_y) { - (true, true) => rect.size, - (true, false) => Size2D::new(rect.size.width, surface_size.height as f32), - (false, true) => Size2D::new(surface_size.width as f32, rect.size.height), - (false, false) => Size2D::new(surface_size.width as f32, surface_size.height as f32), - } - }, - _ => rect.size, - } - ); - - if self.need_to_draw_shadow() { - self.draw_with_shadow(&draw_rect, |new_draw_target: &DrawTarget| { - new_draw_target.fill_rect(&draw_rect, self.state.fill_style.to_pattern_ref(), - Some(&self.state.draw_options)); - }); - } else { - self.drawtarget.fill_rect(&draw_rect, self.state.fill_style.to_pattern_ref(), - Some(&self.state.draw_options)); - } - } - - fn clear_rect(&self, rect: &Rect) { - self.drawtarget.clear_rect(rect); - } - - fn stroke_rect(&self, rect: &Rect) { - if is_zero_size_gradient(&self.state.stroke_style) { - return; // Paint nothing if gradient size is zero. - } - - if self.need_to_draw_shadow() { - self.draw_with_shadow(&rect, |new_draw_target: &DrawTarget| { - new_draw_target.stroke_rect(rect, self.state.stroke_style.to_pattern_ref(), - &self.state.stroke_opts, &self.state.draw_options); - }); - } else if rect.size.width == 0. || rect.size.height == 0. { - let cap = match self.state.stroke_opts.line_join { - JoinStyle::Round => CapStyle::Round, - _ => CapStyle::Butt - }; - - let stroke_opts = - StrokeOptions::new(self.state.stroke_opts.line_width, - self.state.stroke_opts.line_join, - cap, - self.state.stroke_opts.miter_limit, - self.state.stroke_opts.mDashPattern); - self.drawtarget.stroke_line(rect.origin, rect.bottom_right(), - self.state.stroke_style.to_pattern_ref(), - &stroke_opts, &self.state.draw_options); - } else { - self.drawtarget.stroke_rect(rect, self.state.stroke_style.to_pattern_ref(), - &self.state.stroke_opts, &self.state.draw_options); - } - } - - fn begin_path(&mut self) { - self.path_builder = self.drawtarget.create_path_builder() - } - - fn close_path(&self) { - self.path_builder.close() - } - - fn fill(&self) { - if is_zero_size_gradient(&self.state.fill_style) { - return; // Paint nothing if gradient size is zero. - } - - self.drawtarget.fill(&self.path_builder.finish(), - self.state.fill_style.to_pattern_ref(), - &self.state.draw_options); - } - - fn stroke(&self) { - if is_zero_size_gradient(&self.state.stroke_style) { - return; // Paint nothing if gradient size is zero. - } - - self.drawtarget.stroke(&self.path_builder.finish(), - self.state.stroke_style.to_pattern_ref(), - &self.state.stroke_opts, - &self.state.draw_options); - } - - fn clip(&self) { - self.drawtarget.push_clip(&self.path_builder.finish()); - } - - fn is_point_in_path(&mut self, x: f64, y: f64, - _fill_rule: FillRule, chan: IpcSender) { - let path = self.path_builder.finish(); - let result = path.contains_point(x, y, &self.state.transform); - self.path_builder = path.copy_to_builder(); - chan.send(result).unwrap(); - } - - fn draw_image(&self, image_data: Vec, image_size: Size2D, - dest_rect: Rect, source_rect: Rect, smoothing_enabled: bool) { - // We round up the floating pixel values to draw the pixels - let source_rect = source_rect.ceil(); - // It discards the extra pixels (if any) that won't be painted - let image_data = crop_image(image_data, image_size, source_rect); - - if self.need_to_draw_shadow() { - let rect = Rect::new(Point2D::new(dest_rect.origin.x as f32, dest_rect.origin.y as f32), - Size2D::new(dest_rect.size.width as f32, dest_rect.size.height as f32)); - - self.draw_with_shadow(&rect, |new_draw_target: &DrawTarget| { - write_image(&new_draw_target, image_data, source_rect.size, dest_rect, - smoothing_enabled, self.state.draw_options.composition, - self.state.draw_options.alpha); - }); - } else { - write_image(&self.drawtarget, image_data, source_rect.size, dest_rect, - smoothing_enabled, self.state.draw_options.composition, - self.state.draw_options.alpha); - } - } - - fn draw_image_self(&self, image_size: Size2D, - dest_rect: Rect, source_rect: Rect, - smoothing_enabled: bool) { - // Reads pixels from source image - // In this case source and target are the same canvas - let image_data = self.read_pixels(source_rect.to_i32(), image_size); - - if self.need_to_draw_shadow() { - let rect = Rect::new(Point2D::new(dest_rect.origin.x as f32, dest_rect.origin.y as f32), - Size2D::new(dest_rect.size.width as f32, dest_rect.size.height as f32)); - - self.draw_with_shadow(&rect, |new_draw_target: &DrawTarget| { - write_image(&new_draw_target, image_data, source_rect.size, dest_rect, - smoothing_enabled, self.state.draw_options.composition, - self.state.draw_options.alpha); - }); - } else { - // Writes on target canvas - write_image(&self.drawtarget, image_data, image_size, dest_rect, - smoothing_enabled, self.state.draw_options.composition, - self.state.draw_options.alpha); - } - } - - fn draw_image_in_other(&self, - renderer: IpcSender, - other_canvas_id: CanvasId, - image_size: Size2D, - dest_rect: Rect, - source_rect: Rect, - smoothing_enabled: bool, - sender: IpcSender<()>) { - let mut image_data = self.read_pixels(source_rect.to_i32(), image_size); - // TODO: avoid double byte_swap. - byte_swap(&mut image_data); - - let msg = CanvasMsg::Canvas2d(Canvas2dMsg::DrawImage( - image_data.into(), - source_rect.size, - dest_rect, - source_rect, - smoothing_enabled, - ), - other_canvas_id, - ); - renderer.send(msg).unwrap(); - // We acknowledge to the caller here that the data was sent to the - // other canvas so that if JS immediately afterwards try to get the - // pixels of the other one, it won't retrieve the other values. - sender.send(()).unwrap(); - } - - fn move_to(&self, point: &Point2D) { - self.path_builder.move_to(*point) - } - - fn line_to(&self, point: &Point2D) { - self.path_builder.line_to(*point) - } - - fn rect(&self, rect: &Rect) { - self.path_builder.move_to(Point2D::new(rect.origin.x, rect.origin.y)); - self.path_builder.line_to(Point2D::new(rect.origin.x + rect.size.width, rect.origin.y)); - self.path_builder.line_to(Point2D::new(rect.origin.x + rect.size.width, - rect.origin.y + rect.size.height)); - self.path_builder.line_to(Point2D::new(rect.origin.x, rect.origin.y + rect.size.height)); - self.path_builder.close(); - } - - fn quadratic_curve_to(&self, - cp: &Point2D, - endpoint: &Point2D) { - self.path_builder.quadratic_curve_to(cp, endpoint) - } - - fn bezier_curve_to(&self, - cp1: &Point2D, - cp2: &Point2D, - endpoint: &Point2D) { - self.path_builder.bezier_curve_to(cp1, cp2, endpoint) - } - - fn arc(&self, - center: &Point2D, - radius: AzFloat, - start_angle: AzFloat, - end_angle: AzFloat, - ccw: bool) { - self.path_builder.arc(*center, radius, start_angle, end_angle, ccw) - } - - fn arc_to(&self, - cp1: &Point2D, - cp2: &Point2D, - radius: AzFloat) { - let cp0 = self.path_builder.get_current_point(); - let cp1 = *cp1; - let cp2 = *cp2; - - if (cp0.x == cp1.x && cp0.y == cp1.y) || cp1 == cp2 || radius == 0.0 { - self.line_to(&cp1); - return; - } - - // if all three control points lie on a single straight line, - // connect the first two by a straight line - let direction = (cp2.x - cp1.x) * (cp0.y - cp1.y) + (cp2.y - cp1.y) * (cp1.x - cp0.x); - if direction == 0.0 { - self.line_to(&cp1); - return; - } - - // otherwise, draw the Arc - let a2 = (cp0.x - cp1.x).powi(2) + (cp0.y - cp1.y).powi(2); - let b2 = (cp1.x - cp2.x).powi(2) + (cp1.y - cp2.y).powi(2); - let d = { - let c2 = (cp0.x - cp2.x).powi(2) + (cp0.y - cp2.y).powi(2); - let cosx = (a2 + b2 - c2) / (2.0 * (a2 * b2).sqrt()); - let sinx = (1.0 - cosx.powi(2)).sqrt(); - radius / ((1.0 - cosx) / sinx) - }; - - // first tangent point - let anx = (cp1.x - cp0.x) / a2.sqrt(); - let any = (cp1.y - cp0.y) / a2.sqrt(); - let tp1 = Point2D::new(cp1.x - anx * d, cp1.y - any * d); - - // second tangent point - let bnx = (cp1.x - cp2.x) / b2.sqrt(); - let bny = (cp1.y - cp2.y) / b2.sqrt(); - let tp2 = Point2D::new(cp1.x - bnx * d, cp1.y - bny * d); - - // arc center and angles - let anticlockwise = direction < 0.0; - let cx = tp1.x + any * radius * if anticlockwise { 1.0 } else { -1.0 }; - let cy = tp1.y - anx * radius * if anticlockwise { 1.0 } else { -1.0 }; - let angle_start = (tp1.y - cy).atan2(tp1.x - cx); - let angle_end = (tp2.y - cy).atan2(tp2.x - cx); - - self.line_to(&tp1); - if [cx, cy, angle_start, angle_end].iter().all(|x| x.is_finite()) { - self.arc(&Point2D::new(cx, cy), radius, - angle_start, angle_end, anticlockwise); - } - } - - fn ellipse(&mut self, - center: &Point2D, - radius_x: AzFloat, - radius_y: AzFloat, - rotation_angle: AzFloat, - start_angle: AzFloat, - end_angle: AzFloat, - ccw: bool) { - self.path_builder.ellipse(*center, radius_x, radius_y, rotation_angle, start_angle, end_angle, ccw); - } - - fn set_fill_style(&mut self, style: FillOrStrokeStyle) { - if let Some(pattern) = style.to_azure_pattern(&self.drawtarget) { - self.state.fill_style = pattern - } - } - - fn set_stroke_style(&mut self, style: FillOrStrokeStyle) { - if let Some(pattern) = style.to_azure_pattern(&self.drawtarget) { - self.state.stroke_style = pattern - } - } - - fn set_line_width(&mut self, width: f32) { - self.state.stroke_opts.line_width = width; - } - - fn set_line_cap(&mut self, cap: LineCapStyle) { - self.state.stroke_opts.line_cap = cap.to_azure_style(); - } - - fn set_line_join(&mut self, join: LineJoinStyle) { - self.state.stroke_opts.line_join = join.to_azure_style(); - } - - fn set_miter_limit(&mut self, limit: f32) { - self.state.stroke_opts.miter_limit = limit; - } - - fn set_transform(&mut self, transform: &Transform2D) { - self.state.transform = transform.clone(); - self.drawtarget.set_transform(transform) - } - - fn set_global_alpha(&mut self, alpha: f32) { - self.state.draw_options.alpha = alpha; - } - - fn set_global_composition(&mut self, op: CompositionOrBlending) { - self.state.draw_options.set_composition_op(op.to_azure_style()); - } - - fn create(size: Size2D) -> DrawTarget { - DrawTarget::new(BackendType::Skia, size, SurfaceFormat::B8G8R8A8) - } - - fn recreate(&mut self, size: Size2D) { - // TODO: clear the thread state. https://github.com/servo/servo/issues/17533 - self.drawtarget = CanvasPaintThread::create(size); - self.state = CanvasPaintState::new(self.state.draw_options.antialias); - self.saved_states.clear(); - // Webrender doesn't let images change size, so we clear the webrender image key. - // TODO: there is an annying race condition here: the display list builder - // might still be using the old image key. Really, we should be scheduling the image - // for later deletion, not deleting it immediately. - // https://github.com/servo/servo/issues/17534 - if let Some(image_key) = self.image_key.take() { - // If this executes, then we are in a new epoch since we last recreated the canvas, - // so `old_image_key` must be `None`. - debug_assert!(self.old_image_key.is_none()); - self.old_image_key = Some(image_key); - } - } - - fn send_pixels(&mut self, chan: IpcSender>) { - self.drawtarget.snapshot().get_data_surface().with_data(|element| { - chan.send(Some(Vec::from(element).into())).unwrap(); - }) - } - - fn send_data(&mut self, chan: IpcSender) { - self.drawtarget.snapshot().get_data_surface().with_data(|element| { - let size = self.drawtarget.get_size(); - - let descriptor = webrender_api::ImageDescriptor { - width: size.width as u32, - height: size.height as u32, - stride: None, - format: webrender_api::ImageFormat::BGRA8, - offset: 0, - is_opaque: false, - allow_mipmaps: false, - }; - let data = webrender_api::ImageData::Raw(Arc::new(element.into())); - - let mut updates = webrender_api::ResourceUpdates::new(); - - match self.image_key { - Some(image_key) => { - debug!("Updating image {:?}.", image_key); - updates.update_image(image_key, - descriptor, - data, - None); - } - None => { - self.image_key = Some(self.webrender_api.generate_image_key()); - debug!("New image {:?}.", self.image_key); - updates.add_image(self.image_key.unwrap(), - descriptor, - data, - None); - } - } - - if let Some(image_key) = mem::replace(&mut self.very_old_image_key, self.old_image_key.take()) { - updates.delete_image(image_key); - } - - self.webrender_api.update_resources(updates); - - let data = CanvasImageData { - image_key: self.image_key.unwrap(), - }; - chan.send(data).unwrap(); - }) - } - - fn image_data( - &self, - dest_rect: Rect, - canvas_size: Size2D, - chan: IpcSender, - ) { - let mut dest_data = self.read_pixels(dest_rect, canvas_size); - - // bgra -> rgba - byte_swap(&mut dest_data); - chan.send(dest_data.into()).unwrap(); - } - - // https://html.spec.whatwg.org/multipage/#dom-context-2d-putimagedata - fn put_image_data(&mut self, imagedata: Vec, - offset: Vector2D, - image_data_size: Size2D, - mut dirty_rect: Rect) { - if image_data_size.width <= 0.0 || image_data_size.height <= 0.0 { - return - } - - assert_eq!(image_data_size.width * image_data_size.height * 4.0, imagedata.len() as f64); - - // Step 1. TODO (neutered data) - - // Step 2. - if dirty_rect.size.width < 0.0f64 { - dirty_rect.origin.x += dirty_rect.size.width; - dirty_rect.size.width = -dirty_rect.size.width; - } - - if dirty_rect.size.height < 0.0f64 { - dirty_rect.origin.y += dirty_rect.size.height; - dirty_rect.size.height = -dirty_rect.size.height; - } - - // Step 3. - if dirty_rect.origin.x < 0.0f64 { - dirty_rect.size.width += dirty_rect.origin.x; - dirty_rect.origin.x = 0.0f64; - } - - if dirty_rect.origin.y < 0.0f64 { - dirty_rect.size.height += dirty_rect.origin.y; - dirty_rect.origin.y = 0.0f64; - } - - // Step 4. - if dirty_rect.max_x() > image_data_size.width { - dirty_rect.size.width = image_data_size.width - dirty_rect.origin.x; - } - - if dirty_rect.max_y() > image_data_size.height { - dirty_rect.size.height = image_data_size.height - dirty_rect.origin.y; - } - - // 5) If either dirtyWidth or dirtyHeight is negative or zero, - // stop without affecting any bitmaps - if dirty_rect.size.width <= 0.0 || dirty_rect.size.height <= 0.0 { - return - } - - // Step 6. - let dest_rect = dirty_rect.translate(&offset).to_i32(); - - // azure_hl operates with integers. We need to cast the image size - let image_size = image_data_size.to_i32(); - - let first_pixel = dest_rect.origin - offset.to_i32(); - let mut src_line = (first_pixel.y * (image_size.width * 4) + first_pixel.x * 4) as usize; - - let mut dest = - Vec::with_capacity((dest_rect.size.width * dest_rect.size.height * 4) as usize); - - for _ in 0 .. dest_rect.size.height { - let mut src_offset = src_line; - for _ in 0 .. dest_rect.size.width { - let alpha = imagedata[src_offset + 3] as u16; - // add 127 before dividing for more accurate rounding - let premultiply_channel = |channel: u8| (((channel as u16 * alpha) + 127) / 255) as u8; - dest.push(premultiply_channel(imagedata[src_offset + 2])); - dest.push(premultiply_channel(imagedata[src_offset + 1])); - dest.push(premultiply_channel(imagedata[src_offset + 0])); - dest.push(imagedata[src_offset + 3]); - src_offset += 4; - } - src_line += (image_size.width * 4) as usize; - } - - if let Some(source_surface) = self.drawtarget.create_source_surface_from_data( - &dest, - dest_rect.size, - dest_rect.size.width * 4, - SurfaceFormat::B8G8R8A8) { - self.drawtarget.copy_surface(source_surface, - Rect::new(Point2D::new(0, 0), dest_rect.size), - dest_rect.origin); - } - } - - fn set_shadow_offset_x(&mut self, value: f64) { - self.state.shadow_offset_x = value; - } - - fn set_shadow_offset_y(&mut self, value: f64) { - self.state.shadow_offset_y = value; - } - - fn set_shadow_blur(&mut self, value: f64) { - self.state.shadow_blur = value; - } - - fn set_shadow_color(&mut self, value: Color) { - self.state.shadow_color = value; - } - - // https://html.spec.whatwg.org/multipage/#when-shadows-are-drawn - fn need_to_draw_shadow(&self) -> bool { - self.state.shadow_color.a != 0.0f32 && - (self.state.shadow_offset_x != 0.0f64 || - self.state.shadow_offset_y != 0.0f64 || - self.state.shadow_blur != 0.0f64) - } - - fn create_draw_target_for_shadow(&self, source_rect: &Rect) -> DrawTarget { - let draw_target = self.drawtarget.create_similar_draw_target(&Size2D::new(source_rect.size.width as i32, - source_rect.size.height as i32), - self.drawtarget.get_format()); - let matrix = Transform2D::identity() - .pre_translate(-source_rect.origin.to_vector().cast().unwrap()) - .pre_mul(&self.state.transform); - draw_target.set_transform(&matrix); - draw_target - } - - fn draw_with_shadow(&self, rect: &Rect, draw_shadow_source: F) - where F: FnOnce(&DrawTarget) - { - let shadow_src_rect = self.state.transform.transform_rect(rect); - let new_draw_target = self.create_draw_target_for_shadow(&shadow_src_rect); - draw_shadow_source(&new_draw_target); - self.drawtarget.draw_surface_with_shadow(new_draw_target.snapshot(), - &Point2D::new(shadow_src_rect.origin.x as AzFloat, - shadow_src_rect.origin.y as AzFloat), - &self.state.shadow_color, - &Vector2D::new(self.state.shadow_offset_x as AzFloat, - self.state.shadow_offset_y as AzFloat), - (self.state.shadow_blur / 2.0f64) as AzFloat, - self.state.draw_options.composition); - } -} - -impl<'a> Drop for CanvasPaintThread<'a> { - fn drop(&mut self) { - let mut updates = webrender_api::ResourceUpdates::new(); - - if let Some(image_key) = self.old_image_key.take() { - updates.delete_image(image_key); - } - if let Some(image_key) = self.very_old_image_key.take() { - updates.delete_image(image_key); - } - - self.webrender_api.update_resources(updates); - } -} - -/// Used by drawImage to get rid of the extra pixels of the image data that -/// won't be copied to the canvas -/// image_data: Color pixel data of the image -/// image_size: Image dimensions -/// crop_rect: It determines the area of the image we want to keep -fn crop_image(image_data: Vec, - image_size: Size2D, - crop_rect: Rect) -> Vec{ - // We're going to iterate over a pixel values array so we need integers - let crop_rect = crop_rect.to_i32(); - let image_size = image_size.to_i32(); - // Assuming 4 bytes per pixel and row-major order for storage - // (consecutive elements in a pixel row of the image are contiguous in memory) - let stride = image_size.width * 4; - let image_bytes_length = image_size.height * image_size.width * 4; - let crop_area_bytes_length = crop_rect.size.height * crop_rect.size.width * 4; - // If the image size is less or equal than the crop area we do nothing - if image_bytes_length <= crop_area_bytes_length { - return image_data; - } - - let mut new_image_data = Vec::new(); - let mut src = (crop_rect.origin.y * stride + crop_rect.origin.x * 4) as usize; - for _ in 0..crop_rect.size.height { - let row = &image_data[src .. src + (4 * crop_rect.size.width) as usize]; - new_image_data.extend_from_slice(row); - src += stride as usize; - } - new_image_data -} - -/// It writes an image to the destination target -/// draw_target: the destination target where the image_data will be copied -/// image_data: Pixel information of the image to be written. It takes RGBA8 -/// image_size: The size of the image to be written -/// dest_rect: Area of the destination target where the pixels will be copied -/// smoothing_enabled: It determines if smoothing is applied to the image result -fn write_image(draw_target: &DrawTarget, - mut image_data: Vec, - image_size: Size2D, - dest_rect: Rect, - smoothing_enabled: bool, - composition_op: CompositionOp, - global_alpha: f32) { - if image_data.is_empty() { - return - } - let image_rect = Rect::new(Point2D::zero(), image_size); - // rgba -> bgra - byte_swap(&mut image_data); - - // From spec https://html.spec.whatwg.org/multipage/#dom-context-2d-drawimage - // When scaling up, if the imageSmoothingEnabled attribute is set to true, the user agent should attempt - // to apply a smoothing algorithm to the image data when it is scaled. - // Otherwise, the image must be rendered using nearest-neighbor interpolation. - let filter = if smoothing_enabled { - Filter::Linear - } else { - Filter::Point - }; - // azure_hl operates with integers. We need to cast the image size - let image_size = image_size.to_i32(); - - if let Some(source_surface) = - draw_target.create_source_surface_from_data(&image_data, - image_size, - image_size.width * 4, - SurfaceFormat::B8G8R8A8) { - let draw_surface_options = DrawSurfaceOptions::new(filter, true); - let draw_options = DrawOptions::new(global_alpha, composition_op, AntialiasMode::None); - - draw_target.draw_surface(source_surface, - dest_rect.to_azure_style(), - image_rect.to_azure_style(), - draw_surface_options, - draw_options); - } -} - -fn is_zero_size_gradient(pattern: &Pattern) -> bool { - if let &Pattern::LinearGradient(ref gradient) = pattern { - if gradient.is_zero_size() { - return true; - } - } - false -} - -pub trait PointToi32 { - fn to_i32(&self) -> Point2D; -} - -impl PointToi32 for Point2D { - fn to_i32(&self) -> Point2D { - Point2D::new(self.x.to_i32().unwrap(), - self.y.to_i32().unwrap()) - } -} - -pub trait SizeToi32 { - fn to_i32(&self) -> Size2D; -} - -impl SizeToi32 for Size2D { - fn to_i32(&self) -> Size2D { - Size2D::new(self.width.to_i32().unwrap(), - self.height.to_i32().unwrap()) - } -} - -pub trait RectToi32 { - fn to_i32(&self) -> Rect; - fn ceil(&self) -> Rect; -} - -impl RectToi32 for Rect { - fn to_i32(&self) -> Rect { - Rect::new(Point2D::new(self.origin.x.to_i32().unwrap(), - self.origin.y.to_i32().unwrap()), - Size2D::new(self.size.width.to_i32().unwrap(), - self.size.height.to_i32().unwrap())) - } - - fn ceil(&self) -> Rect { - Rect::new(Point2D::new(self.origin.x.ceil(), - self.origin.y.ceil()), - Size2D::new(self.size.width.ceil(), - self.size.height.ceil())) - } - -} - -pub trait ToAzureStyle { - type Target; - fn to_azure_style(self) -> Self::Target; -} - -impl ToAzureStyle for Rect { - type Target = Rect; - - fn to_azure_style(self) -> Rect { - Rect::new(Point2D::new(self.origin.x as AzFloat, self.origin.y as AzFloat), - Size2D::new(self.size.width as AzFloat, self.size.height as AzFloat)) - } -} - - -impl ToAzureStyle for LineCapStyle { - type Target = CapStyle; - - fn to_azure_style(self) -> CapStyle { - match self { - LineCapStyle::Butt => CapStyle::Butt, - LineCapStyle::Round => CapStyle::Round, - LineCapStyle::Square => CapStyle::Square, - } - } -} - -impl ToAzureStyle for LineJoinStyle { - type Target = JoinStyle; - - fn to_azure_style(self) -> JoinStyle { - match self { - LineJoinStyle::Round => JoinStyle::Round, - LineJoinStyle::Bevel => JoinStyle::Bevel, - LineJoinStyle::Miter => JoinStyle::Miter, - } - } -} - -impl ToAzureStyle for CompositionStyle { - type Target = CompositionOp; - - fn to_azure_style(self) -> CompositionOp { - match self { - CompositionStyle::SrcIn => CompositionOp::In, - CompositionStyle::SrcOut => CompositionOp::Out, - CompositionStyle::SrcOver => CompositionOp::Over, - CompositionStyle::SrcAtop => CompositionOp::Atop, - CompositionStyle::DestIn => CompositionOp::DestIn, - CompositionStyle::DestOut => CompositionOp::DestOut, - CompositionStyle::DestOver => CompositionOp::DestOver, - CompositionStyle::DestAtop => CompositionOp::DestAtop, - CompositionStyle::Copy => CompositionOp::Source, - CompositionStyle::Lighter => CompositionOp::Add, - CompositionStyle::Xor => CompositionOp::Xor, - } - } -} - -impl ToAzureStyle for BlendingStyle { - type Target = CompositionOp; - - fn to_azure_style(self) -> CompositionOp { - match self { - BlendingStyle::Multiply => CompositionOp::Multiply, - BlendingStyle::Screen => CompositionOp::Screen, - BlendingStyle::Overlay => CompositionOp::Overlay, - BlendingStyle::Darken => CompositionOp::Darken, - BlendingStyle::Lighten => CompositionOp::Lighten, - BlendingStyle::ColorDodge => CompositionOp::ColorDodge, - BlendingStyle::ColorBurn => CompositionOp::ColorBurn, - BlendingStyle::HardLight => CompositionOp::HardLight, - BlendingStyle::SoftLight => CompositionOp::SoftLight, - BlendingStyle::Difference => CompositionOp::Difference, - BlendingStyle::Exclusion => CompositionOp::Exclusion, - BlendingStyle::Hue => CompositionOp::Hue, - BlendingStyle::Saturation => CompositionOp::Saturation, - BlendingStyle::Color => CompositionOp::Color, - BlendingStyle::Luminosity => CompositionOp::Luminosity, - } - } -} - -impl ToAzureStyle for CompositionOrBlending { - type Target = CompositionOp; - - fn to_azure_style(self) -> CompositionOp { - match self { - CompositionOrBlending::Composition(op) => op.to_azure_style(), - CompositionOrBlending::Blending(op) => op.to_azure_style(), - } - } -} - -pub trait ToAzurePattern { - fn to_azure_pattern(&self, drawtarget: &DrawTarget) -> Option; -} - -impl ToAzurePattern for FillOrStrokeStyle { - fn to_azure_pattern(&self, drawtarget: &DrawTarget) -> Option { - match *self { - FillOrStrokeStyle::Color(ref color) => { - Some(Pattern::Color(ColorPattern::new(color.to_azure_style()))) - }, - FillOrStrokeStyle::LinearGradient(ref linear_gradient_style) => { - let gradient_stops: Vec = linear_gradient_style.stops.iter().map(|s| { - GradientStop { - offset: s.offset as AzFloat, - color: s.color.to_azure_style() - } - }).collect(); - - Some(Pattern::LinearGradient(LinearGradientPattern::new( - &Point2D::new(linear_gradient_style.x0 as AzFloat, linear_gradient_style.y0 as AzFloat), - &Point2D::new(linear_gradient_style.x1 as AzFloat, linear_gradient_style.y1 as AzFloat), - drawtarget.create_gradient_stops(&gradient_stops, ExtendMode::Clamp), - &Transform2D::identity()))) - }, - FillOrStrokeStyle::RadialGradient(ref radial_gradient_style) => { - let gradient_stops: Vec = radial_gradient_style.stops.iter().map(|s| { - GradientStop { - offset: s.offset as AzFloat, - color: s.color.to_azure_style() - } - }).collect(); - - Some(Pattern::RadialGradient(RadialGradientPattern::new( - &Point2D::new(radial_gradient_style.x0 as AzFloat, radial_gradient_style.y0 as AzFloat), - &Point2D::new(radial_gradient_style.x1 as AzFloat, radial_gradient_style.y1 as AzFloat), - radial_gradient_style.r0 as AzFloat, radial_gradient_style.r1 as AzFloat, - drawtarget.create_gradient_stops(&gradient_stops, ExtendMode::Clamp), - &Transform2D::identity()))) - }, - FillOrStrokeStyle::Surface(ref surface_style) => { - drawtarget.create_source_surface_from_data(&surface_style.surface_data, - surface_style.surface_size, - surface_style.surface_size.width * 4, - SurfaceFormat::B8G8R8A8) - .map(|source_surface| { - Pattern::Surface(SurfacePattern::new( - source_surface.azure_source_surface, - surface_style.repeat_x, - surface_style.repeat_y, - &Transform2D::identity())) - }) - } - } - } -} - -impl ToAzureStyle for RGBA { - type Target = Color; - - fn to_azure_style(self) -> Color { - Color::rgba(self.red_f32() as AzFloat, - self.green_f32() as AzFloat, - self.blue_f32() as AzFloat, - self.alpha_f32() as AzFloat) - } -} diff --git a/servo/components/canvas/gl_context.rs b/servo/components/canvas/gl_context.rs deleted file mode 100644 index 7720f8f678a4..000000000000 --- a/servo/components/canvas/gl_context.rs +++ /dev/null @@ -1,224 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -use canvas_traits::webgl::{WebGLCommand, WebGLVersion}; -use compositing::compositor_thread::{CompositorProxy, self}; -use euclid::Size2D; -use gleam::gl; -use offscreen_gl_context::{ColorAttachmentType, GLContext, GLContextAttributes, GLContextDispatcher}; -use offscreen_gl_context::{GLLimits, GLVersion}; -use offscreen_gl_context::{NativeGLContext, NativeGLContextHandle, NativeGLContextMethods}; -use offscreen_gl_context::{OSMesaContext, OSMesaContextHandle}; -use std::sync::{Arc, Mutex}; -use super::webgl_thread::WebGLImpl; - -/// The GLContextFactory is used to create shared GL contexts with the main thread GL context. -/// Currently, shared textures are used to render WebGL textures into the WR compositor. -/// In order to create a shared context, the GLContextFactory stores the handle of the main GL context. -pub enum GLContextFactory { - Native(NativeGLContextHandle, Option), - OSMesa(OSMesaContextHandle), -} - -impl GLContextFactory { - /// Creates a new GLContextFactory that uses the currently bound GL context to create shared contexts. - pub fn current_native_handle(proxy: &CompositorProxy) -> Option { - // FIXME(emilio): This assumes a single GL backend per platform which is - // not true on Linux, we probably need a third `Egl` variant or abstract - // it a bit more... - NativeGLContext::current_handle().map(|handle| { - if cfg!(target_os = "windows") { - // Used to dispatch functions from the GLContext thread to the main thread's event loop. - // Required to allow WGL GLContext sharing in Windows. - GLContextFactory::Native(handle, Some(MainThreadDispatcher::new(proxy.clone()))) - } else { - GLContextFactory::Native(handle, None) - } - }) - } - - /// Creates a new GLContextFactory that uses the currently bound OSMesa context to create shared contexts. - pub fn current_osmesa_handle() -> Option { - OSMesaContext::current_handle().map(GLContextFactory::OSMesa) - } - - /// Creates a new shared GLContext with the main GLContext - pub fn new_shared_context( - &self, - webgl_version: WebGLVersion, - size: Size2D, - attributes: GLContextAttributes - ) -> Result { - match *self { - GLContextFactory::Native(ref handle, ref dispatcher) => { - let dispatcher = dispatcher.as_ref().map(|d| Box::new(d.clone()) as Box<_>); - let ctx = GLContext::::new_shared_with_dispatcher(size, - attributes, - ColorAttachmentType::Texture, - gl::GlType::default(), - Self::gl_version(webgl_version), - Some(handle), - dispatcher); - ctx.map(GLContextWrapper::Native) - } - GLContextFactory::OSMesa(ref handle) => { - let ctx = GLContext::::new_shared_with_dispatcher(size.to_untyped(), - attributes, - ColorAttachmentType::Texture, - gl::GlType::default(), - Self::gl_version(webgl_version), - Some(handle), - None); - ctx.map(GLContextWrapper::OSMesa) - } - } - } - - /// Creates a new non-shared GLContext - pub fn new_context( - &self, - webgl_version: WebGLVersion, - size: Size2D, - attributes: GLContextAttributes - ) -> Result { - match *self { - GLContextFactory::Native(..) => { - let ctx = GLContext::::new_shared_with_dispatcher(size, - attributes, - ColorAttachmentType::Texture, - gl::GlType::default(), - Self::gl_version(webgl_version), - None, - None); - ctx.map(GLContextWrapper::Native) - } - GLContextFactory::OSMesa(_) => { - let ctx = GLContext::::new_shared_with_dispatcher(size.to_untyped(), - attributes, - ColorAttachmentType::Texture, - gl::GlType::default(), - Self::gl_version(webgl_version), - None, - None); - ctx.map(GLContextWrapper::OSMesa) - } - } - } - - fn gl_version(webgl_version: WebGLVersion) -> GLVersion { - match webgl_version { - WebGLVersion::WebGL1 => GLVersion::Major(2), - WebGLVersion::WebGL2 => GLVersion::Major(3), - } - } -} - - -/// GLContextWrapper used to abstract NativeGLContext and OSMesaContext types -pub enum GLContextWrapper { - Native(GLContext), - OSMesa(GLContext), -} - -impl GLContextWrapper { - pub fn make_current(&self) { - match *self { - GLContextWrapper::Native(ref ctx) => { - ctx.make_current().unwrap(); - } - GLContextWrapper::OSMesa(ref ctx) => { - ctx.make_current().unwrap(); - } - } - } - - pub fn unbind(&self) { - match *self { - GLContextWrapper::Native(ref ctx) => { - ctx.unbind().unwrap(); - } - GLContextWrapper::OSMesa(ref ctx) => { - ctx.unbind().unwrap(); - } - } - } - - pub fn apply_command(&self, cmd: WebGLCommand) { - match *self { - GLContextWrapper::Native(ref ctx) => { - WebGLImpl::apply(ctx, cmd); - } - GLContextWrapper::OSMesa(ref ctx) => { - WebGLImpl::apply(ctx, cmd); - } - } - } - - pub fn gl(&self) -> &gl::Gl { - match *self { - GLContextWrapper::Native(ref ctx) => { - ctx.gl() - } - GLContextWrapper::OSMesa(ref ctx) => { - ctx.gl() - } - } - } - - pub fn get_info(&self) -> (Size2D, u32, GLLimits) { - match *self { - GLContextWrapper::Native(ref ctx) => { - let (real_size, texture_id) = { - let draw_buffer = ctx.borrow_draw_buffer().unwrap(); - (draw_buffer.size(), draw_buffer.get_bound_texture_id().unwrap()) - }; - - let limits = ctx.borrow_limits().clone(); - - (real_size, texture_id, limits) - } - GLContextWrapper::OSMesa(ref ctx) => { - let (real_size, texture_id) = { - let draw_buffer = ctx.borrow_draw_buffer().unwrap(); - (draw_buffer.size(), draw_buffer.get_bound_texture_id().unwrap()) - }; - - let limits = ctx.borrow_limits().clone(); - - (real_size, texture_id, limits) - } - } - } - - pub fn resize(&mut self, size: Size2D) -> Result<(), &'static str> { - match *self { - GLContextWrapper::Native(ref mut ctx) => { - ctx.resize(size) - } - GLContextWrapper::OSMesa(ref mut ctx) => { - ctx.resize(size) - } - } - } -} - -/// Implements GLContextDispatcher to dispatch functions from GLContext threads to the main thread's event loop. -/// It's used in Windows to allow WGL GLContext sharing. -#[derive(Clone)] -pub struct MainThreadDispatcher { - compositor_proxy: Arc> -} - -impl MainThreadDispatcher { - fn new(proxy: CompositorProxy) -> Self { - Self { - compositor_proxy: Arc::new(Mutex::new(proxy)), - } - } -} -impl GLContextDispatcher for MainThreadDispatcher { - fn dispatch(&self, f: Box) { - self.compositor_proxy.lock().unwrap().send(compositor_thread::Msg::Dispatch(f)); - } -} diff --git a/servo/components/canvas/lib.rs b/servo/components/canvas/lib.rs deleted file mode 100644 index f6806f533cfd..000000000000 --- a/servo/components/canvas/lib.rs +++ /dev/null @@ -1,26 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -#![deny(unsafe_code)] - -extern crate azure; -extern crate canvas_traits; -extern crate compositing; -extern crate cssparser; -extern crate euclid; -extern crate fnv; -extern crate gleam; -extern crate ipc_channel; -#[macro_use] extern crate log; -extern crate num_traits; -extern crate offscreen_gl_context; -extern crate serde_bytes; -extern crate servo_config; -extern crate webrender; -extern crate webrender_api; - -pub mod canvas_paint_thread; -pub mod gl_context; -mod webgl_mode; -pub mod webgl_thread; diff --git a/servo/components/canvas/webgl_mode/inprocess.rs b/servo/components/canvas/webgl_mode/inprocess.rs deleted file mode 100644 index d8d4b4656f1d..000000000000 --- a/servo/components/canvas/webgl_mode/inprocess.rs +++ /dev/null @@ -1,159 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -use ::gl_context::GLContextFactory; -use ::webgl_thread::{WebGLExternalImageApi, WebGLExternalImageHandler, WebGLThreadObserver, WebGLThread}; -use canvas_traits::webgl::{WebGLChan, WebGLContextId, WebGLMsg, WebGLPipeline, WebGLReceiver}; -use canvas_traits::webgl::{WebGLSender, WebVRCommand, WebVRRenderHandler}; -use canvas_traits::webgl::DOMToTextureCommand; -use canvas_traits::webgl::webgl_channel; -use euclid::Size2D; -use fnv::FnvHashMap; -use gleam::gl; -use servo_config::prefs::PREFS; -use std::marker::PhantomData; -use std::rc::Rc; -use webrender; -use webrender_api; - -/// WebGL Threading API entry point that lives in the constellation. -pub struct WebGLThreads(WebGLSender); - -impl WebGLThreads { - /// Creates a new WebGLThreads object - pub fn new(gl_factory: GLContextFactory, - webrender_gl: Rc, - webrender_api_sender: webrender_api::RenderApiSender, - webvr_compositor: Option>) - -> (WebGLThreads, Box, Option>) { - // This implementation creates a single `WebGLThread` for all the pipelines. - let channel = WebGLThread::start(gl_factory, - webrender_api_sender, - webvr_compositor.map(|c| WebVRRenderWrapper(c)), - PhantomData); - let output_handler = if PREFS.is_dom_to_texture_enabled() { - Some(Box::new(OutputHandler::new(webrender_gl.clone(), channel.clone()))) - } else { - None - }; - let external = WebGLExternalImageHandler::new(WebGLExternalImages::new(webrender_gl, channel.clone())); - (WebGLThreads(channel), Box::new(external), output_handler.map(|b| b as Box<_>)) - } - - /// Gets the WebGLThread handle for each script pipeline. - pub fn pipeline(&self) -> WebGLPipeline { - // This mode creates a single thread, so the existing WebGLChan is just cloned. - WebGLPipeline(WebGLChan(self.0.clone())) - } - - /// Sends a exit message to close the WebGLThreads and release all WebGLContexts. - pub fn exit(&self) -> Result<(), &'static str> { - self.0.send(WebGLMsg::Exit).map_err(|_| "Failed to send Exit message") - } -} - -/// Bridge between the webrender::ExternalImage callbacks and the WebGLThreads. -struct WebGLExternalImages { - webrender_gl: Rc, - webgl_channel: WebGLSender, - // Used to avoid creating a new channel on each received WebRender request. - lock_channel: (WebGLSender<(u32, Size2D, usize)>, WebGLReceiver<(u32, Size2D, usize)>), -} - -impl WebGLExternalImages { - fn new(webrender_gl: Rc, channel: WebGLSender) -> Self { - Self { - webrender_gl, - webgl_channel: channel, - lock_channel: webgl_channel().unwrap(), - } - } -} - -impl WebGLExternalImageApi for WebGLExternalImages { - fn lock(&mut self, ctx_id: WebGLContextId) -> (u32, Size2D) { - // WebGL Thread has it's own GL command queue that we need to synchronize with the WR GL command queue. - // The WebGLMsg::Lock message inserts a fence in the WebGL command queue. - self.webgl_channel.send(WebGLMsg::Lock(ctx_id, self.lock_channel.0.clone())).unwrap(); - let (image_id, size, gl_sync) = self.lock_channel.1.recv().unwrap(); - // The next glWaitSync call is run on the WR thread and it's used to synchronize the two - // flows of OpenGL commands in order to avoid WR using a semi-ready WebGL texture. - // glWaitSync doesn't block WR thread, it affects only internal OpenGL subsystem. - self.webrender_gl.wait_sync(gl_sync as gl::GLsync, 0, gl::TIMEOUT_IGNORED); - (image_id, size) - } - - fn unlock(&mut self, ctx_id: WebGLContextId) { - self.webgl_channel.send(WebGLMsg::Unlock(ctx_id)).unwrap(); - } -} - -/// Custom observer used in a `WebGLThread`. -impl WebGLThreadObserver for PhantomData<()> { - fn on_context_create(&mut self, ctx_id: WebGLContextId, texture_id: u32, size: Size2D) { - debug!("WebGLContext created (ctx_id: {:?} texture_id: {:?} size: {:?}", ctx_id, texture_id, size); - } - - fn on_context_resize(&mut self, ctx_id: WebGLContextId, texture_id: u32, size: Size2D) { - debug!("WebGLContext resized (ctx_id: {:?} texture_id: {:?} size: {:?}", ctx_id, texture_id, size); - } - - fn on_context_delete(&mut self, ctx_id: WebGLContextId) { - debug!("WebGLContext deleted (ctx_id: {:?})", ctx_id); - } -} - - -/// Wrapper to send WebVR commands used in `WebGLThread`. -struct WebVRRenderWrapper(Box); - -impl WebVRRenderHandler for WebVRRenderWrapper { - fn handle(&mut self, command: WebVRCommand, texture: Option<(u32, Size2D)>) { - self.0.handle(command, texture); - } -} - -/// struct used to implement DOMToTexture feature and webrender::OutputImageHandler trait. -type OutputHandlerData = Option<(u32, Size2D)>; -struct OutputHandler { - webrender_gl: Rc, - webgl_channel: WebGLSender, - // Used to avoid creating a new channel on each received WebRender request. - lock_channel: (WebGLSender, WebGLReceiver), - sync_objects: FnvHashMap, -} - -impl OutputHandler { - fn new(webrender_gl: Rc, channel: WebGLSender) -> Self { - Self { - webrender_gl, - webgl_channel: channel, - lock_channel: webgl_channel().unwrap(), - sync_objects: Default::default(), - } - } -} - -/// Bridge between the WR frame outputs and WebGL to implement DOMToTexture synchronization. -impl webrender::OutputImageHandler for OutputHandler { - fn lock(&mut self, id: webrender_api::PipelineId) -> Option<(u32, webrender_api::DeviceIntSize)> { - // Insert a fence in the WR command queue - let gl_sync = self.webrender_gl.fence_sync(gl::SYNC_GPU_COMMANDS_COMPLETE, 0); - // The lock command adds a WaitSync call on the WebGL command flow. - let command = DOMToTextureCommand::Lock(id, gl_sync as usize, self.lock_channel.0.clone()); - self.webgl_channel.send(WebGLMsg::DOMToTextureCommand(command)).unwrap(); - self.lock_channel.1.recv().unwrap().map(|(tex_id, size)| { - (tex_id, webrender_api::DeviceIntSize::new(size.width, size.height)) - }) - } - - fn unlock(&mut self, id: webrender_api::PipelineId) { - if let Some(gl_sync) = self.sync_objects.remove(&id) { - // Flush the Sync object into the GPU's command queue to guarantee that it it's signaled. - self.webrender_gl.flush(); - // Mark the sync object for deletion. - self.webrender_gl.delete_sync(gl_sync); - } - } -} diff --git a/servo/components/canvas/webgl_mode/mod.rs b/servo/components/canvas/webgl_mode/mod.rs deleted file mode 100644 index 660818fb096d..000000000000 --- a/servo/components/canvas/webgl_mode/mod.rs +++ /dev/null @@ -1,6 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -mod inprocess; -pub use self::inprocess::WebGLThreads; diff --git a/servo/components/canvas/webgl_thread.rs b/servo/components/canvas/webgl_thread.rs deleted file mode 100644 index 7bcb303bbf1c..000000000000 --- a/servo/components/canvas/webgl_thread.rs +++ /dev/null @@ -1,1311 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -use canvas_traits::canvas::byte_swap; -use canvas_traits::webgl::*; -use euclid::Size2D; -use fnv::FnvHashMap; -use gleam::gl; -use offscreen_gl_context::{GLContext, GLContextAttributes, GLLimits, NativeGLContextMethods}; -use serde_bytes::ByteBuf; -use std::thread; -use super::gl_context::{GLContextFactory, GLContextWrapper}; -use webrender; -use webrender_api; - -/// WebGL Threading API entry point that lives in the constellation. -/// It allows to get a WebGLThread handle for each script pipeline. -pub use ::webgl_mode::WebGLThreads; - -/// A WebGLThread manages the life cycle and message multiplexing of -/// a set of WebGLContexts living in the same thread. -pub struct WebGLThread { - /// Factory used to create a new GLContext shared with the WR/Main thread. - gl_factory: GLContextFactory, - /// Channel used to generate/update or delete `webrender_api::ImageKey`s. - webrender_api: webrender_api::RenderApi, - /// Map of live WebGLContexts. - contexts: FnvHashMap, - /// Cached information for WebGLContexts. - cached_context_info: FnvHashMap, - /// Current bound context. - bound_context_id: Option, - /// Id generator for new WebGLContexts. - next_webgl_id: usize, - /// Handler user to send WebVR commands. - webvr_compositor: Option, - /// Generic observer that listens WebGLContext creation, resize or removal events. - observer: OB, - /// Texture ids and sizes used in DOM to texture outputs. - dom_outputs: FnvHashMap, -} - -impl WebGLThread { - pub fn new(gl_factory: GLContextFactory, - webrender_api_sender: webrender_api::RenderApiSender, - webvr_compositor: Option, - observer: OB) -> Self { - WebGLThread { - gl_factory, - webrender_api: webrender_api_sender.create_api(), - contexts: Default::default(), - cached_context_info: Default::default(), - bound_context_id: None, - next_webgl_id: 0, - webvr_compositor, - observer: observer, - dom_outputs: Default::default(), - } - } - - /// Creates a new `WebGLThread` and returns a Sender to - /// communicate with it. - pub fn start(gl_factory: GLContextFactory, - webrender_api_sender: webrender_api::RenderApiSender, - webvr_compositor: Option, - observer: OB) - -> WebGLSender { - let (sender, receiver) = webgl_channel::().unwrap(); - let result = sender.clone(); - thread::Builder::new().name("WebGLThread".to_owned()).spawn(move || { - let mut renderer = WebGLThread::new(gl_factory, - webrender_api_sender, - webvr_compositor, - observer); - let webgl_chan = WebGLChan(sender); - loop { - let msg = receiver.recv().unwrap(); - let exit = renderer.handle_msg(msg, &webgl_chan); - if exit { - return; - } - } - }).expect("Thread spawning failed"); - - result - } - - /// Handles a generic WebGLMsg message - #[inline] - fn handle_msg(&mut self, msg: WebGLMsg, webgl_chan: &WebGLChan) -> bool { - match msg { - WebGLMsg::CreateContext(version, size, attributes, result_sender) => { - let result = self.create_webgl_context(version, size, attributes); - result_sender.send(result.map(|(id, limits, share_mode)| { - let ctx = Self::make_current_if_needed(id, &self.contexts, &mut self.bound_context_id) - .expect("WebGLContext not found"); - let glsl_version = Self::get_glsl_version(ctx); - - WebGLCreateContextResult { - sender: WebGLMsgSender::new(id, webgl_chan.clone()), - limits, - share_mode, - glsl_version, - } - })).unwrap(); - }, - WebGLMsg::ResizeContext(ctx_id, size, sender) => { - self.resize_webgl_context(ctx_id, size, sender); - }, - WebGLMsg::RemoveContext(ctx_id) => { - self.remove_webgl_context(ctx_id); - }, - WebGLMsg::WebGLCommand(ctx_id, command) => { - self.handle_webgl_command(ctx_id, command); - }, - WebGLMsg::WebVRCommand(ctx_id, command) => { - self.handle_webvr_command(ctx_id, command); - }, - WebGLMsg::Lock(ctx_id, sender) => { - self.handle_lock(ctx_id, sender); - }, - WebGLMsg::Unlock(ctx_id) => { - self.handle_unlock(ctx_id); - }, - WebGLMsg::UpdateWebRenderImage(ctx_id, sender) => { - self.handle_update_wr_image(ctx_id, sender); - }, - WebGLMsg::DOMToTextureCommand(command) => { - self.handle_dom_to_texture(command); - }, - WebGLMsg::Exit => { - return true; - } - } - - false - } - - /// Handles a WebGLCommand for a specific WebGLContext - fn handle_webgl_command(&mut self, context_id: WebGLContextId, command: WebGLCommand) { - if let Some(ctx) = Self::make_current_if_needed(context_id, &self.contexts, &mut self.bound_context_id) { - ctx.apply_command(command); - } - } - - /// Handles a WebVRCommand for a specific WebGLContext - fn handle_webvr_command(&mut self, context_id: WebGLContextId, command: WebVRCommand) { - Self::make_current_if_needed(context_id, &self.contexts, &mut self.bound_context_id); - let texture = match command { - WebVRCommand::SubmitFrame(..) => { - self.cached_context_info.get(&context_id) - }, - _ => None - }; - self.webvr_compositor.as_mut().unwrap().handle(command, texture.map(|t| (t.texture_id, t.size))); - } - - /// Handles a lock external callback received from webrender::ExternalImageHandler - fn handle_lock(&mut self, context_id: WebGLContextId, sender: WebGLSender<(u32, Size2D, usize)>) { - let ctx = Self::make_current_if_needed(context_id, &self.contexts, &mut self.bound_context_id) - .expect("WebGLContext not found in a WebGLMsg::Lock message"); - let info = self.cached_context_info.get_mut(&context_id).unwrap(); - // Insert a OpenGL Fence sync object that sends a signal when all the WebGL commands are finished. - // The related gl().wait_sync call is performed in the WR thread. See WebGLExternalImageApi for mor details. - let gl_sync = ctx.gl().fence_sync(gl::SYNC_GPU_COMMANDS_COMPLETE, 0); - info.gl_sync = Some(gl_sync); - // It is important that the fence sync is properly flushed into the GPU's command queue. - // Without proper flushing, the sync object may never be signaled. - ctx.gl().flush(); - - sender.send((info.texture_id, info.size, gl_sync as usize)).unwrap(); - } - - /// Handles an unlock external callback received from webrender::ExternalImageHandler - fn handle_unlock(&mut self, context_id: WebGLContextId) { - let ctx = Self::make_current_if_needed(context_id, &self.contexts, &mut self.bound_context_id) - .expect("WebGLContext not found in a WebGLMsg::Unlock message"); - let info = self.cached_context_info.get_mut(&context_id).unwrap(); - if let Some(gl_sync) = info.gl_sync.take() { - // Release the GLSync object. - ctx.gl().delete_sync(gl_sync); - } - } - - /// Creates a new WebGLContext - fn create_webgl_context(&mut self, - version: WebGLVersion, - size: Size2D, - attributes: GLContextAttributes) - -> Result<(WebGLContextId, GLLimits, WebGLContextShareMode), String> { - // First try to create a shared context for the best performance. - // Fallback to readback mode if the shared context creation fails. - let result = self.gl_factory.new_shared_context(version, size, attributes) - .map(|r| (r, WebGLContextShareMode::SharedTexture)) - .or_else(|_| { - let ctx = self.gl_factory.new_context(version, size, attributes); - ctx.map(|r| (r, WebGLContextShareMode::Readback)) - }); - - // Creating a new GLContext may make the current bound context_id dirty. - // Clear it to ensure that make_current() is called in subsequent commands. - self.bound_context_id = None; - - match result { - Ok((ctx, share_mode)) => { - let id = WebGLContextId(self.next_webgl_id); - let (size, texture_id, limits) = ctx.get_info(); - self.next_webgl_id += 1; - self.contexts.insert(id, ctx); - self.cached_context_info.insert(id, WebGLContextInfo { - texture_id, - size, - alpha: attributes.alpha, - image_key: None, - share_mode, - gl_sync: None, - }); - - self.observer.on_context_create(id, texture_id, size); - - Ok((id, limits, share_mode)) - }, - Err(msg) => { - Err(msg.to_owned()) - } - } - } - - /// Resizes a WebGLContext - fn resize_webgl_context(&mut self, - context_id: WebGLContextId, - size: Size2D, - sender: WebGLSender>) { - let ctx = Self::make_current_if_needed_mut(context_id, &mut self.contexts, &mut self.bound_context_id); - match ctx.resize(size) { - Ok(_) => { - let (real_size, texture_id, _) = ctx.get_info(); - self.observer.on_context_resize(context_id, texture_id, real_size); - - let info = self.cached_context_info.get_mut(&context_id).unwrap(); - // Update webgl texture size. Texture id may change too. - info.texture_id = texture_id; - info.size = real_size; - // Update WR image if needed. Resize image updates are only required for SharedTexture mode. - // Readback mode already updates the image every frame to send the raw pixels. - // See `handle_update_wr_image`. - match (info.image_key, info.share_mode) { - (Some(image_key), WebGLContextShareMode::SharedTexture) => { - Self::update_wr_external_image(&self.webrender_api, - info.size, - info.alpha, - context_id, - image_key); - }, - _ => {} - } - - sender.send(Ok(())).unwrap(); - }, - Err(msg) => { - sender.send(Err(msg.into())).unwrap(); - } - } - } - - /// Removes a WebGLContext and releases attached resources. - fn remove_webgl_context(&mut self, context_id: WebGLContextId) { - // Release webrender image keys. - if let Some(info) = self.cached_context_info.remove(&context_id) { - let mut updates = webrender_api::ResourceUpdates::new(); - - if let Some(image_key) = info.image_key { - updates.delete_image(image_key); - } - - self.webrender_api.update_resources(updates) - } - - // Release GL context. - if self.contexts.remove(&context_id).is_some() { - self.observer.on_context_delete(context_id); - } - - // Removing a GLContext may make the current bound context_id dirty. - self.bound_context_id = None; - } - - /// Handles the creation/update of webrender_api::ImageKeys for a specific WebGLContext. - /// This method is invoked from a UpdateWebRenderImage message sent by the layout thread. - /// If SharedTexture is used the UpdateWebRenderImage message is sent only after a WebGLContext creation. - /// If Readback is used UpdateWebRenderImage message is sent always on each layout iteration in order to - /// submit the updated raw pixels. - fn handle_update_wr_image(&mut self, context_id: WebGLContextId, sender: WebGLSender) { - let info = self.cached_context_info.get_mut(&context_id).unwrap(); - let webrender_api = &self.webrender_api; - - let image_key = match info.share_mode { - WebGLContextShareMode::SharedTexture => { - let size = info.size; - let alpha = info.alpha; - // Reuse existing ImageKey or generate a new one. - // When using a shared texture ImageKeys are only generated after a WebGLContext creation. - *info.image_key.get_or_insert_with(|| { - Self::create_wr_external_image(webrender_api, size, alpha, context_id) - }) - }, - WebGLContextShareMode::Readback => { - let pixels = Self::raw_pixels(&self.contexts[&context_id], info.size); - match info.image_key.clone() { - Some(image_key) => { - // ImageKey was already created, but WR Images must - // be updated every frame in readback mode to send the new raw pixels. - Self::update_wr_readback_image(webrender_api, - info.size, - info.alpha, - image_key, - pixels); - - image_key - }, - None => { - // Generate a new ImageKey for Readback mode. - let image_key = Self::create_wr_readback_image(webrender_api, - info.size, - info.alpha, - pixels); - info.image_key = Some(image_key); - image_key - } - } - } - }; - - // Send the ImageKey to the Layout thread. - sender.send(image_key).unwrap(); - } - - fn handle_dom_to_texture(&mut self, command: DOMToTextureCommand) { - match command { - DOMToTextureCommand::Attach(context_id, texture_id, document_id, pipeline_id, size) => { - let ctx = Self::make_current_if_needed(context_id, &self.contexts, &mut self.bound_context_id) - .expect("WebGLContext not found in a WebGL DOMToTextureCommand::Attach command"); - // Initialize the texture that WR will use for frame outputs. - ctx.gl().tex_image_2d(gl::TEXTURE_2D, - 0, - gl::RGBA as gl::GLint, - size.width, - size.height, - 0, - gl::RGBA, - gl::UNSIGNED_BYTE, - None); - self.dom_outputs.insert(pipeline_id, DOMToTextureData { - context_id, texture_id, document_id, size - }); - let mut txn = webrender_api::Transaction::new(); - txn.enable_frame_output(pipeline_id, true); - self.webrender_api.send_transaction(document_id, txn); - }, - DOMToTextureCommand::Lock(pipeline_id, gl_sync, sender) => { - let contexts = &self.contexts; - let bound_context_id = &mut self.bound_context_id; - let result = self.dom_outputs.get(&pipeline_id).and_then(|data| { - let ctx = Self::make_current_if_needed(data.context_id, contexts, bound_context_id); - ctx.and_then(|ctx| { - // The next glWaitSync call is used to synchronize the two flows of - // OpenGL commands (WR and WebGL) in order to avoid using semi-ready WR textures. - // glWaitSync doesn't block WebGL CPU thread. - ctx.gl().wait_sync(gl_sync as gl::GLsync, 0, gl::TIMEOUT_IGNORED); - Some((data.texture_id.get(), data.size)) - }) - }); - - // Send the texture id and size to WR. - sender.send(result).unwrap(); - }, - DOMToTextureCommand::Detach(texture_id) => { - if let Some((pipeline_id, document_id)) = self.dom_outputs.iter() - .find(|&(_, v)| v.texture_id == texture_id) - .map(|(k, v)| (*k, v.document_id)) { - let mut txn = webrender_api::Transaction::new(); - txn.enable_frame_output(pipeline_id, false); - self.webrender_api.send_transaction(document_id, txn); - self.dom_outputs.remove(&pipeline_id); - } - }, - } - } - - /// Gets a reference to a GLContextWrapper for a given WebGLContextId and makes it current if required. - fn make_current_if_needed<'a>(context_id: WebGLContextId, - contexts: &'a FnvHashMap, - bound_id: &mut Option) -> Option<&'a GLContextWrapper> { - contexts.get(&context_id).and_then(|ctx| { - if Some(context_id) != *bound_id { - ctx.make_current(); - *bound_id = Some(context_id); - } - - Some(ctx) - }) - } - - /// Gets a mutable reference to a GLContextWrapper for a WebGLContextId and makes it current if required. - fn make_current_if_needed_mut<'a>(context_id: WebGLContextId, - contexts: &'a mut FnvHashMap, - bound_id: &mut Option) -> &'a mut GLContextWrapper { - let ctx = contexts.get_mut(&context_id).expect("WebGLContext not found!"); - if Some(context_id) != *bound_id { - ctx.make_current(); - *bound_id = Some(context_id); - } - ctx - } - - /// Creates a `webrender_api::ImageKey` that uses shared textures. - fn create_wr_external_image(webrender_api: &webrender_api::RenderApi, - size: Size2D, - alpha: bool, - context_id: WebGLContextId) -> webrender_api::ImageKey { - let descriptor = Self::image_descriptor(size, alpha); - let data = Self::external_image_data(context_id); - - let image_key = webrender_api.generate_image_key(); - let mut updates = webrender_api::ResourceUpdates::new(); - updates.add_image(image_key, - descriptor, - data, - None); - webrender_api.update_resources(updates); - - image_key - } - - /// Updates a `webrender_api::ImageKey` that uses shared textures. - fn update_wr_external_image(webrender_api: &webrender_api::RenderApi, - size: Size2D, - alpha: bool, - context_id: WebGLContextId, - image_key: webrender_api::ImageKey) { - let descriptor = Self::image_descriptor(size, alpha); - let data = Self::external_image_data(context_id); - - let mut updates = webrender_api::ResourceUpdates::new(); - updates.update_image(image_key, - descriptor, - data, - None); - webrender_api.update_resources(updates); - } - - /// Creates a `webrender_api::ImageKey` that uses raw pixels. - fn create_wr_readback_image(webrender_api: &webrender_api::RenderApi, - size: Size2D, - alpha: bool, - data: Vec) -> webrender_api::ImageKey { - let descriptor = Self::image_descriptor(size, alpha); - let data = webrender_api::ImageData::new(data); - - let image_key = webrender_api.generate_image_key(); - let mut updates = webrender_api::ResourceUpdates::new(); - updates.add_image(image_key, - descriptor, - data, - None); - webrender_api.update_resources(updates); - - image_key - } - - /// Updates a `webrender_api::ImageKey` that uses raw pixels. - fn update_wr_readback_image(webrender_api: &webrender_api::RenderApi, - size: Size2D, - alpha: bool, - image_key: webrender_api::ImageKey, - data: Vec) { - let descriptor = Self::image_descriptor(size, alpha); - let data = webrender_api::ImageData::new(data); - - let mut updates = webrender_api::ResourceUpdates::new(); - updates.update_image(image_key, - descriptor, - data, - None); - webrender_api.update_resources(updates); - } - - /// Helper function to create a `webrender_api::ImageDescriptor`. - fn image_descriptor(size: Size2D, alpha: bool) -> webrender_api::ImageDescriptor { - webrender_api::ImageDescriptor { - width: size.width as u32, - height: size.height as u32, - stride: None, - format: webrender_api::ImageFormat::BGRA8, - offset: 0, - is_opaque: !alpha, - allow_mipmaps: false, - } - } - - /// Helper function to create a `webrender_api::ImageData::External` instance. - fn external_image_data(context_id: WebGLContextId) -> webrender_api::ImageData { - let data = webrender_api::ExternalImageData { - id: webrender_api::ExternalImageId(context_id.0 as u64), - channel_index: 0, - image_type: webrender_api::ExternalImageType::TextureHandle( - webrender_api::TextureTarget::Default, - ), - }; - webrender_api::ImageData::External(data) - } - - /// Helper function to fetch the raw pixels used in readback mode. - fn raw_pixels(context: &GLContextWrapper, size: Size2D) -> Vec { - let width = size.width as usize; - let height = size.height as usize; - - let mut pixels = context.gl().read_pixels(0, 0, - size.width as gl::GLsizei, - size.height as gl::GLsizei, - gl::RGBA, gl::UNSIGNED_BYTE); - // flip image vertically (texture is upside down) - let orig_pixels = pixels.clone(); - let stride = width * 4; - for y in 0..height { - let dst_start = y * stride; - let src_start = (height - y - 1) * stride; - let src_slice = &orig_pixels[src_start .. src_start + stride]; - (&mut pixels[dst_start .. dst_start + stride]).clone_from_slice(&src_slice[..stride]); - } - byte_swap(&mut pixels); - pixels - } - - /// Gets the GLSL Version supported by a GLContext. - fn get_glsl_version(context: &GLContextWrapper) -> WebGLSLVersion { - let version = context.gl().get_string(gl::SHADING_LANGUAGE_VERSION); - // Fomat used by SHADING_LANGUAGE_VERSION query : major.minor[.release] [vendor info] - let mut values = version.split(&['.', ' '][..]); - let major = values.next().and_then(|v| v.parse::().ok()).unwrap_or(1); - let minor = values.next().and_then(|v| v.parse::().ok()).unwrap_or(20); - - WebGLSLVersion { - major, - minor, - } - } -} - -impl Drop for WebGLThread { - fn drop(&mut self) { - // Call remove_context functions in order to correctly delete WebRender image keys. - let context_ids: Vec = self.contexts.keys().map(|id| *id).collect(); - for id in context_ids { - self.remove_webgl_context(id); - } - } -} - -/// Helper struct to store cached WebGLContext information. -struct WebGLContextInfo { - /// Render to texture identifier used by the WebGLContext. - texture_id: u32, - /// Size of the WebGLContext. - size: Size2D, - /// True if the WebGLContext uses an alpha channel. - alpha: bool, - /// Currently used WebRender image key. - image_key: Option, - /// The sharing mode used to send the image to WebRender. - share_mode: WebGLContextShareMode, - /// GLSync Object used for a correct synchronization with Webrender external image callbacks. - gl_sync: Option, -} - -/// Trait used to observe events in a WebGL Thread. -/// Used in webrender::ExternalImageHandler when multiple WebGL threads are used. -pub trait WebGLThreadObserver: Send + 'static { - fn on_context_create(&mut self, ctx_id: WebGLContextId, texture_id: u32, size: Size2D); - fn on_context_resize(&mut self, ctx_id: WebGLContextId, texture_id: u32, size: Size2D); - fn on_context_delete(&mut self, ctx_id: WebGLContextId); -} - -/// This trait is used as a bridge between the `WebGLThreads` implementation and -/// the WR ExternalImageHandler API implemented in the `WebGLExternalImageHandler` struct. -/// `WebGLExternalImageHandler` takes care of type conversions between WR and WebGL info (e.g keys, uvs). -/// It uses this trait to notify lock/unlock messages and get the required info that WR needs. -/// `WebGLThreads` receives lock/unlock message notifications and takes care of sending -/// the unlock/lock messages to the appropiate `WebGLThread`. -pub trait WebGLExternalImageApi { - fn lock(&mut self, ctx_id: WebGLContextId) -> (u32, Size2D); - fn unlock(&mut self, ctx_id: WebGLContextId); -} - -/// WebRender External Image Handler implementation -pub struct WebGLExternalImageHandler { - handler: T, -} - -impl WebGLExternalImageHandler { - pub fn new(handler: T) -> Self { - Self { - handler: handler - } - } -} - -impl webrender::ExternalImageHandler for WebGLExternalImageHandler { - /// Lock the external image. Then, WR could start to read the image content. - /// The WR client should not change the image content until the unlock() call. - fn lock(&mut self, - key: webrender_api::ExternalImageId, - _channel_index: u8) -> webrender::ExternalImage { - let ctx_id = WebGLContextId(key.0 as _); - let (texture_id, size) = self.handler.lock(ctx_id); - - webrender::ExternalImage { - uv: webrender_api::TexelRect::new( - 0.0, - size.height as f32, - size.width as f32, - 0.0, - ), - source: webrender::ExternalImageSource::NativeTexture(texture_id), - } - - } - /// Unlock the external image. The WR should not read the image content - /// after this call. - fn unlock(&mut self, - key: webrender_api::ExternalImageId, - _channel_index: u8) { - let ctx_id = WebGLContextId(key.0 as _); - self.handler.unlock(ctx_id); - } -} - -/// Data about the linked DOM<->WebGLTexture elements. -struct DOMToTextureData { - context_id: WebGLContextId, - texture_id: WebGLTextureId, - document_id: webrender_api::DocumentId, - size: Size2D, -} - -/// WebGL Commands Implementation -pub struct WebGLImpl; - -impl WebGLImpl { - pub fn apply(ctx: &GLContext, command: WebGLCommand) { - match command { - WebGLCommand::GetContextAttributes(sender) => - sender.send(*ctx.borrow_attributes()).unwrap(), - WebGLCommand::ActiveTexture(target) => - ctx.gl().active_texture(target), - WebGLCommand::AttachShader(program_id, shader_id) => - ctx.gl().attach_shader(program_id.get(), shader_id.get()), - WebGLCommand::DetachShader(program_id, shader_id) => - ctx.gl().detach_shader(program_id.get(), shader_id.get()), - WebGLCommand::BindAttribLocation(program_id, index, name) => - ctx.gl().bind_attrib_location(program_id.get(), index, &name), - WebGLCommand::BlendColor(r, g, b, a) => - ctx.gl().blend_color(r, g, b, a), - WebGLCommand::BlendEquation(mode) => - ctx.gl().blend_equation(mode), - WebGLCommand::BlendEquationSeparate(mode_rgb, mode_alpha) => - ctx.gl().blend_equation_separate(mode_rgb, mode_alpha), - WebGLCommand::BlendFunc(src, dest) => - ctx.gl().blend_func(src, dest), - WebGLCommand::BlendFuncSeparate(src_rgb, dest_rgb, src_alpha, dest_alpha) => - ctx.gl().blend_func_separate(src_rgb, dest_rgb, src_alpha, dest_alpha), - WebGLCommand::BufferData(buffer_type, data, usage) => - gl::buffer_data(ctx.gl(), buffer_type, &data, usage), - WebGLCommand::BufferSubData(buffer_type, offset, data) => - gl::buffer_sub_data(ctx.gl(), buffer_type, offset, &data), - WebGLCommand::Clear(mask) => - ctx.gl().clear(mask), - WebGLCommand::ClearColor(r, g, b, a) => - ctx.gl().clear_color(r, g, b, a), - WebGLCommand::ClearDepth(depth) => { - ctx.gl().clear_depth(depth.max(0.).min(1.) as f64) - } - WebGLCommand::ClearStencil(stencil) => - ctx.gl().clear_stencil(stencil), - WebGLCommand::ColorMask(r, g, b, a) => - ctx.gl().color_mask(r, g, b, a), - WebGLCommand::CopyTexImage2D(target, level, internal_format, x, y, width, height, border) => - ctx.gl().copy_tex_image_2d(target, level, internal_format, x, y, width, height, border), - WebGLCommand::CopyTexSubImage2D(target, level, xoffset, yoffset, x, y, width, height) => - ctx.gl().copy_tex_sub_image_2d(target, level, xoffset, yoffset, x, y, width, height), - WebGLCommand::CullFace(mode) => - ctx.gl().cull_face(mode), - WebGLCommand::DepthFunc(func) => - ctx.gl().depth_func(func), - WebGLCommand::DepthMask(flag) => - ctx.gl().depth_mask(flag), - WebGLCommand::DepthRange(near, far) => { - ctx.gl().depth_range(near.max(0.).min(1.) as f64, far.max(0.).min(1.) as f64) - } - WebGLCommand::Disable(cap) => - ctx.gl().disable(cap), - WebGLCommand::Enable(cap) => - ctx.gl().enable(cap), - WebGLCommand::FramebufferRenderbuffer(target, attachment, renderbuffertarget, rb) => - ctx.gl().framebuffer_renderbuffer(target, attachment, renderbuffertarget, - rb.map_or(0, WebGLRenderbufferId::get)), - WebGLCommand::FramebufferTexture2D(target, attachment, textarget, texture, level) => - ctx.gl().framebuffer_texture_2d(target, attachment, textarget, - texture.map_or(0, WebGLTextureId::get), level), - WebGLCommand::FrontFace(mode) => - ctx.gl().front_face(mode), - WebGLCommand::DisableVertexAttribArray(attrib_id) => - ctx.gl().disable_vertex_attrib_array(attrib_id), - WebGLCommand::DrawArrays(mode, first, count) => - ctx.gl().draw_arrays(mode, first, count), - WebGLCommand::DrawElements(mode, count, type_, offset) => - ctx.gl().draw_elements(mode, count, type_, offset as u32), - WebGLCommand::EnableVertexAttribArray(attrib_id) => - ctx.gl().enable_vertex_attrib_array(attrib_id), - WebGLCommand::Hint(name, val) => - ctx.gl().hint(name, val), - WebGLCommand::IsEnabled(cap, chan) => - chan.send(ctx.gl().is_enabled(cap) != 0).unwrap(), - WebGLCommand::LineWidth(width) => - ctx.gl().line_width(width), - WebGLCommand::PixelStorei(name, val) => - ctx.gl().pixel_store_i(name, val), - WebGLCommand::PolygonOffset(factor, units) => - ctx.gl().polygon_offset(factor, units), - WebGLCommand::ReadPixels(x, y, width, height, format, pixel_type, chan) => - Self::read_pixels(ctx.gl(), x, y, width, height, format, pixel_type, chan), - WebGLCommand::RenderbufferStorage(target, format, width, height) => - ctx.gl().renderbuffer_storage(target, format, width, height), - WebGLCommand::SampleCoverage(value, invert) => - ctx.gl().sample_coverage(value, invert), - WebGLCommand::Scissor(x, y, width, height) => - ctx.gl().scissor(x, y, width, height), - WebGLCommand::StencilFunc(func, ref_, mask) => - ctx.gl().stencil_func(func, ref_, mask), - WebGLCommand::StencilFuncSeparate(face, func, ref_, mask) => - ctx.gl().stencil_func_separate(face, func, ref_, mask), - WebGLCommand::StencilMask(mask) => - ctx.gl().stencil_mask(mask), - WebGLCommand::StencilMaskSeparate(face, mask) => - ctx.gl().stencil_mask_separate(face, mask), - WebGLCommand::StencilOp(fail, zfail, zpass) => - ctx.gl().stencil_op(fail, zfail, zpass), - WebGLCommand::StencilOpSeparate(face, fail, zfail, zpass) => - ctx.gl().stencil_op_separate(face, fail, zfail, zpass), - WebGLCommand::GetActiveAttrib(program_id, index, chan) => - Self::active_attrib(ctx.gl(), program_id, index, chan), - WebGLCommand::GetActiveUniform(program_id, index, chan) => - Self::active_uniform(ctx.gl(), program_id, index, chan), - WebGLCommand::GetAttribLocation(program_id, name, chan) => - Self::attrib_location(ctx.gl(), program_id, name, chan), - WebGLCommand::GetFramebufferAttachmentParameter(target, attachment, pname, chan) => - Self::get_framebuffer_attachment_parameter(ctx.gl(), target, attachment, pname, chan), - WebGLCommand::GetVertexAttrib(index, pname, chan) => - Self::vertex_attrib(ctx.gl(), index, pname, chan), - WebGLCommand::GetVertexAttribOffset(index, pname, chan) => - Self::vertex_attrib_offset(ctx.gl(), index, pname, chan), - WebGLCommand::GetParameter(param_id, chan) => - Self::parameter(ctx.gl(), param_id, chan), - WebGLCommand::GetTexParameter(target, pname, chan) => - Self::get_tex_parameter(ctx.gl(), target, pname, chan), - WebGLCommand::GetProgramParameter(program_id, param_id, chan) => - Self::program_parameter(ctx.gl(), program_id, param_id, chan), - WebGLCommand::GetShaderParameter(shader_id, param_id, chan) => - Self::shader_parameter(ctx.gl(), shader_id, param_id, chan), - WebGLCommand::GetShaderPrecisionFormat(shader_type, precision_type, chan) => - Self::shader_precision_format(ctx.gl(), shader_type, precision_type, chan), - WebGLCommand::GetExtensions(chan) => - Self::get_extensions(ctx.gl(), chan), - WebGLCommand::GetUniformLocation(program_id, name, chan) => - Self::uniform_location(ctx.gl(), program_id, name, chan), - WebGLCommand::GetShaderInfoLog(shader_id, chan) => - Self::shader_info_log(ctx.gl(), shader_id, chan), - WebGLCommand::GetProgramInfoLog(program_id, chan) => - Self::program_info_log(ctx.gl(), program_id, chan), - WebGLCommand::CompileShader(shader_id, source) => - Self::compile_shader(ctx.gl(), shader_id, source), - WebGLCommand::CreateBuffer(chan) => - Self::create_buffer(ctx.gl(), chan), - WebGLCommand::CreateFramebuffer(chan) => - Self::create_framebuffer(ctx.gl(), chan), - WebGLCommand::CreateRenderbuffer(chan) => - Self::create_renderbuffer(ctx.gl(), chan), - WebGLCommand::CreateTexture(chan) => - Self::create_texture(ctx.gl(), chan), - WebGLCommand::CreateProgram(chan) => - Self::create_program(ctx.gl(), chan), - WebGLCommand::CreateShader(shader_type, chan) => - Self::create_shader(ctx.gl(), shader_type, chan), - WebGLCommand::DeleteBuffer(id) => - ctx.gl().delete_buffers(&[id.get()]), - WebGLCommand::DeleteFramebuffer(id) => - ctx.gl().delete_framebuffers(&[id.get()]), - WebGLCommand::DeleteRenderbuffer(id) => - ctx.gl().delete_renderbuffers(&[id.get()]), - WebGLCommand::DeleteTexture(id) => - ctx.gl().delete_textures(&[id.get()]), - WebGLCommand::DeleteProgram(id) => - ctx.gl().delete_program(id.get()), - WebGLCommand::DeleteShader(id) => - ctx.gl().delete_shader(id.get()), - WebGLCommand::BindBuffer(target, id) => - ctx.gl().bind_buffer(target, id.map_or(0, WebGLBufferId::get)), - WebGLCommand::BindFramebuffer(target, request) => - Self::bind_framebuffer(ctx.gl(), target, request, ctx), - WebGLCommand::BindRenderbuffer(target, id) => - ctx.gl().bind_renderbuffer(target, id.map_or(0, WebGLRenderbufferId::get)), - WebGLCommand::BindTexture(target, id) => - ctx.gl().bind_texture(target, id.map_or(0, WebGLTextureId::get)), - WebGLCommand::LinkProgram(program_id) => - ctx.gl().link_program(program_id.get()), - WebGLCommand::Uniform1f(uniform_id, v) => - ctx.gl().uniform_1f(uniform_id, v), - WebGLCommand::Uniform1fv(uniform_id, v) => - ctx.gl().uniform_1fv(uniform_id, &v), - WebGLCommand::Uniform1i(uniform_id, v) => - ctx.gl().uniform_1i(uniform_id, v), - WebGLCommand::Uniform1iv(uniform_id, v) => - ctx.gl().uniform_1iv(uniform_id, &v), - WebGLCommand::Uniform2f(uniform_id, x, y) => - ctx.gl().uniform_2f(uniform_id, x, y), - WebGLCommand::Uniform2fv(uniform_id, v) => - ctx.gl().uniform_2fv(uniform_id, &v), - WebGLCommand::Uniform2i(uniform_id, x, y) => - ctx.gl().uniform_2i(uniform_id, x, y), - WebGLCommand::Uniform2iv(uniform_id, v) => - ctx.gl().uniform_2iv(uniform_id, &v), - WebGLCommand::Uniform3f(uniform_id, x, y, z) => - ctx.gl().uniform_3f(uniform_id, x, y, z), - WebGLCommand::Uniform3fv(uniform_id, v) => - ctx.gl().uniform_3fv(uniform_id, &v), - WebGLCommand::Uniform3i(uniform_id, x, y, z) => - ctx.gl().uniform_3i(uniform_id, x, y, z), - WebGLCommand::Uniform3iv(uniform_id, v) => - ctx.gl().uniform_3iv(uniform_id, &v), - WebGLCommand::Uniform4f(uniform_id, x, y, z, w) => - ctx.gl().uniform_4f(uniform_id, x, y, z, w), - WebGLCommand::Uniform4fv(uniform_id, v) => - ctx.gl().uniform_4fv(uniform_id, &v), - WebGLCommand::Uniform4i(uniform_id, x, y, z, w) => - ctx.gl().uniform_4i(uniform_id, x, y, z, w), - WebGLCommand::Uniform4iv(uniform_id, v) => - ctx.gl().uniform_4iv(uniform_id, &v), - WebGLCommand::UniformMatrix2fv(uniform_id, transpose, v) => - ctx.gl().uniform_matrix_2fv(uniform_id, transpose, &v), - WebGLCommand::UniformMatrix3fv(uniform_id, transpose, v) => - ctx.gl().uniform_matrix_3fv(uniform_id, transpose, &v), - WebGLCommand::UniformMatrix4fv(uniform_id, transpose, v) => - ctx.gl().uniform_matrix_4fv(uniform_id, transpose, &v), - WebGLCommand::UseProgram(program_id) => - ctx.gl().use_program(program_id.get()), - WebGLCommand::ValidateProgram(program_id) => - ctx.gl().validate_program(program_id.get()), - WebGLCommand::VertexAttrib(attrib_id, x, y, z, w) => - ctx.gl().vertex_attrib_4f(attrib_id, x, y, z, w), - WebGLCommand::VertexAttribPointer2f(attrib_id, size, normalized, stride, offset) => - ctx.gl().vertex_attrib_pointer_f32(attrib_id, size, normalized, stride, offset), - WebGLCommand::VertexAttribPointer(attrib_id, size, data_type, normalized, stride, offset) => - ctx.gl().vertex_attrib_pointer(attrib_id, size, data_type, normalized, stride, offset), - WebGLCommand::GetViewport(sender) => { - sender.send(ctx.gl().get_viewport()).unwrap(); - } - WebGLCommand::SetViewport(x, y, width, height) => { - ctx.gl().viewport(x, y, width, height); - } - WebGLCommand::TexImage2D(target, level, internal, width, height, format, data_type, data) => - ctx.gl().tex_image_2d(target, level, internal, width, height, - /*border*/0, format, data_type, Some(&data)), - WebGLCommand::TexParameteri(target, name, value) => - ctx.gl().tex_parameter_i(target, name, value), - WebGLCommand::TexParameterf(target, name, value) => - ctx.gl().tex_parameter_f(target, name, value), - WebGLCommand::TexSubImage2D(target, level, xoffset, yoffset, x, y, width, height, data) => - ctx.gl().tex_sub_image_2d(target, level, xoffset, yoffset, x, y, width, height, &data), - WebGLCommand::DrawingBufferWidth(sender) => - sender.send(ctx.borrow_draw_buffer().unwrap().size().width).unwrap(), - WebGLCommand::DrawingBufferHeight(sender) => - sender.send(ctx.borrow_draw_buffer().unwrap().size().height).unwrap(), - WebGLCommand::Finish(sender) => - Self::finish(ctx.gl(), sender), - WebGLCommand::Flush => - ctx.gl().flush(), - WebGLCommand::GenerateMipmap(target) => - ctx.gl().generate_mipmap(target), - WebGLCommand::CreateVertexArray(chan) => - Self::create_vertex_array(ctx.gl(), chan), - WebGLCommand::DeleteVertexArray(id) => - ctx.gl().delete_vertex_arrays(&[id.get()]), - WebGLCommand::BindVertexArray(id) => - ctx.gl().bind_vertex_array(id.map_or(0, WebGLVertexArrayId::get)), - WebGLCommand::AliasedPointSizeRange(sender) => { - sender.send(ctx.gl().alias_point_size_range()).unwrap() - } - } - - // TODO: update test expectations in order to enable debug assertions - //if cfg!(debug_assertions) { - let error = ctx.gl().get_error(); - assert_eq!(error, gl::NO_ERROR, "Unexpected WebGL error: 0x{:x} ({})", error, error); - //} - } - - fn read_pixels( - gl: &gl::Gl, - x: i32, - y: i32, - width: i32, - height: i32, - format: u32, - pixel_type: u32, - chan: WebGLSender, - ) { - let result = gl.read_pixels(x, y, width, height, format, pixel_type); - chan.send(result.into()).unwrap() - } - - fn active_attrib(gl: &gl::Gl, - program_id: WebGLProgramId, - index: u32, - chan: WebGLSender>) { - let result = if index >= gl.get_program_iv(program_id.get(), gl::ACTIVE_ATTRIBUTES) as u32 { - Err(WebGLError::InvalidValue) - } else { - Ok(gl.get_active_attrib(program_id.get(), index)) - }; - chan.send(result).unwrap(); - } - - fn active_uniform(gl: &gl::Gl, - program_id: WebGLProgramId, - index: u32, - chan: WebGLSender>) { - let result = if index >= gl.get_program_iv(program_id.get(), gl::ACTIVE_UNIFORMS) as u32 { - Err(WebGLError::InvalidValue) - } else { - Ok(gl.get_active_uniform(program_id.get(), index)) - }; - chan.send(result).unwrap(); - } - - fn attrib_location(gl: &gl::Gl, - program_id: WebGLProgramId, - name: String, - chan: WebGLSender> ) { - let attrib_location = gl.get_attrib_location(program_id.get(), &name); - - let attrib_location = if attrib_location == -1 { - None - } else { - Some(attrib_location) - }; - - chan.send(attrib_location).unwrap(); - } - - fn parameter(gl: &gl::Gl, - param_id: u32, - chan: WebGLSender>) { - let result = match param_id { - gl::ACTIVE_TEXTURE | - gl::ALPHA_BITS | - gl::BLEND_DST_ALPHA | - gl::BLEND_DST_RGB | - gl::BLEND_EQUATION_ALPHA | - gl::BLEND_EQUATION_RGB | - gl::BLEND_SRC_ALPHA | - gl::BLEND_SRC_RGB | - gl::BLUE_BITS | - gl::CULL_FACE_MODE | - gl::DEPTH_BITS | - gl::DEPTH_FUNC | - gl::FRONT_FACE | - //gl::GENERATE_MIPMAP_HINT | - gl::GREEN_BITS | - //gl::IMPLEMENTATION_COLOR_READ_FORMAT | - //gl::IMPLEMENTATION_COLOR_READ_TYPE | - gl::MAX_COMBINED_TEXTURE_IMAGE_UNITS | - gl::MAX_CUBE_MAP_TEXTURE_SIZE | - //gl::MAX_FRAGMENT_UNIFORM_VECTORS | - gl::MAX_RENDERBUFFER_SIZE | - gl::MAX_TEXTURE_IMAGE_UNITS | - gl::MAX_TEXTURE_SIZE | - //gl::MAX_VARYING_VECTORS | - gl::MAX_VERTEX_ATTRIBS | - gl::MAX_VERTEX_TEXTURE_IMAGE_UNITS | - //gl::MAX_VERTEX_UNIFORM_VECTORS | - gl::PACK_ALIGNMENT | - gl::RED_BITS | - gl::SAMPLE_BUFFERS | - gl::SAMPLES | - gl::STENCIL_BACK_FAIL | - gl::STENCIL_BACK_FUNC | - gl::STENCIL_BACK_PASS_DEPTH_FAIL | - gl::STENCIL_BACK_PASS_DEPTH_PASS | - gl::STENCIL_BACK_REF | - gl::STENCIL_BACK_VALUE_MASK | - gl::STENCIL_BACK_WRITEMASK | - gl::STENCIL_BITS | - gl::STENCIL_CLEAR_VALUE | - gl::STENCIL_FAIL | - gl::STENCIL_FUNC | - gl::STENCIL_PASS_DEPTH_FAIL | - gl::STENCIL_PASS_DEPTH_PASS | - gl::STENCIL_REF | - gl::STENCIL_VALUE_MASK | - gl::STENCIL_WRITEMASK | - gl::SUBPIXEL_BITS | - gl::UNPACK_ALIGNMENT | - gl::FRAGMENT_SHADER_DERIVATIVE_HINT => - //gl::UNPACK_COLORSPACE_CONVERSION_WEBGL => - Ok(WebGLParameter::Int(gl.get_integer_v(param_id))), - - gl::BLEND | - gl::CULL_FACE | - gl::DEPTH_TEST | - gl::DEPTH_WRITEMASK | - gl::DITHER | - gl::POLYGON_OFFSET_FILL | - gl::SAMPLE_COVERAGE_INVERT | - gl::STENCIL_TEST => - //gl::UNPACK_FLIP_Y_WEBGL | - //gl::UNPACK_PREMULTIPLY_ALPHA_WEBGL => - Ok(WebGLParameter::Bool(gl.get_boolean_v(param_id) != 0)), - - gl::DEPTH_CLEAR_VALUE | - gl::LINE_WIDTH | - gl::POLYGON_OFFSET_FACTOR | - gl::POLYGON_OFFSET_UNITS | - gl::SAMPLE_COVERAGE_VALUE => - Ok(WebGLParameter::Float(gl.get_float_v(param_id))), - - gl::VERSION => Ok(WebGLParameter::String("WebGL 1.0".to_owned())), - gl::RENDERER | - gl::VENDOR => Ok(WebGLParameter::String("Mozilla/Servo".to_owned())), - gl::SHADING_LANGUAGE_VERSION => Ok(WebGLParameter::String("WebGL GLSL ES 1.0".to_owned())), - - // TODO(zbarsky, emilio): Implement support for the following valid parameters - // Float32Array - gl::ALIASED_LINE_WIDTH_RANGE | - //gl::ALIASED_POINT_SIZE_RANGE | - //gl::BLEND_COLOR | - gl::COLOR_CLEAR_VALUE | - gl::DEPTH_RANGE | - - // WebGLBuffer - gl::ARRAY_BUFFER_BINDING | - gl::ELEMENT_ARRAY_BUFFER_BINDING | - - // WebGLFrameBuffer - gl::FRAMEBUFFER_BINDING | - - // WebGLRenderBuffer - gl::RENDERBUFFER_BINDING | - - // WebGLProgram - gl::CURRENT_PROGRAM | - - // WebGLTexture - gl::TEXTURE_BINDING_2D | - gl::TEXTURE_BINDING_CUBE_MAP | - - // sequence - gl::COLOR_WRITEMASK | - - // Uint32Array - gl::COMPRESSED_TEXTURE_FORMATS | - - // Int32Array - gl::MAX_VIEWPORT_DIMS | - gl::SCISSOR_BOX => Err(WebGLError::InvalidEnum), - - // Invalid parameters - _ => Err(WebGLError::InvalidEnum) - }; - - chan.send(result).unwrap(); - } - - fn get_tex_parameter(gl: &gl::Gl, - target: u32, - pname: u32, - chan: WebGLSender ) { - let result = gl.get_tex_parameter_iv(target, pname); - chan.send(result).unwrap(); - } - - fn finish(gl: &gl::Gl, chan: WebGLSender<()>) { - gl.finish(); - chan.send(()).unwrap(); - } - - fn vertex_attrib(gl: &gl::Gl, - index: u32, - pname: u32, - chan: WebGLSender>) { - let result = if index >= gl.get_integer_v(gl::MAX_VERTEX_ATTRIBS) as u32 { - Err(WebGLError::InvalidValue) - } else { - match pname { - gl::VERTEX_ATTRIB_ARRAY_ENABLED | - gl::VERTEX_ATTRIB_ARRAY_NORMALIZED => - Ok(WebGLParameter::Bool(gl.get_vertex_attrib_iv(index, pname) != 0)), - gl::VERTEX_ATTRIB_ARRAY_SIZE | - gl::VERTEX_ATTRIB_ARRAY_STRIDE | - gl::VERTEX_ATTRIB_ARRAY_TYPE => - Ok(WebGLParameter::Int(gl.get_vertex_attrib_iv(index, pname))), - gl::CURRENT_VERTEX_ATTRIB => - Ok(WebGLParameter::FloatArray(gl.get_vertex_attrib_fv(index, pname))), - // gl::VERTEX_ATTRIB_ARRAY_BUFFER_BINDING should return WebGLBuffer - _ => Err(WebGLError::InvalidEnum), - } - }; - - chan.send(result).unwrap(); - } - - fn vertex_attrib_offset(gl: &gl::Gl, - index: u32, - pname: u32, - chan: WebGLSender) { - let result = gl.get_vertex_attrib_pointer_v(index, pname); - chan.send(result).unwrap(); - } - - fn program_parameter(gl: &gl::Gl, - program_id: WebGLProgramId, - param_id: u32, - chan: WebGLSender>) { - let result = match param_id { - gl::DELETE_STATUS | - gl::LINK_STATUS | - gl::VALIDATE_STATUS => - Ok(WebGLParameter::Bool(gl.get_program_iv(program_id.get(), param_id) != 0)), - gl::ATTACHED_SHADERS | - gl::ACTIVE_ATTRIBUTES | - gl::ACTIVE_UNIFORMS => - Ok(WebGLParameter::Int(gl.get_program_iv(program_id.get(), param_id))), - _ => Err(WebGLError::InvalidEnum), - }; - - chan.send(result).unwrap(); - } - - fn shader_parameter(gl: &gl::Gl, - shader_id: WebGLShaderId, - param_id: u32, - chan: WebGLSender>) { - let result = match param_id { - gl::SHADER_TYPE => - Ok(WebGLParameter::Int(gl.get_shader_iv(shader_id.get(), param_id))), - gl::DELETE_STATUS | - gl::COMPILE_STATUS => - Ok(WebGLParameter::Bool(gl.get_shader_iv(shader_id.get(), param_id) != 0)), - _ => Err(WebGLError::InvalidEnum), - }; - - chan.send(result).unwrap(); - } - - fn shader_precision_format(gl: &gl::Gl, - shader_type: u32, - precision_type: u32, - chan: WebGLSender<(i32, i32, i32)>) { - let result = gl.get_shader_precision_format(shader_type, precision_type); - chan.send(result).unwrap(); - } - - fn get_extensions(gl: &gl::Gl, chan: WebGLSender) { - chan.send(gl.get_string(gl::EXTENSIONS)).unwrap(); - } - - // https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.6 - fn get_framebuffer_attachment_parameter( - gl: &gl::Gl, - target: u32, - attachment: u32, - pname: u32, - chan: WebGLSender - ) { - let parameter = gl.get_framebuffer_attachment_parameter_iv(target, attachment, pname); - chan.send(parameter).unwrap(); - } - - fn uniform_location(gl: &gl::Gl, - program_id: WebGLProgramId, - name: String, - chan: WebGLSender>) { - let location = gl.get_uniform_location(program_id.get(), &name); - let location = if location == -1 { - None - } else { - Some(location) - }; - - chan.send(location).unwrap(); - } - - - fn shader_info_log(gl: &gl::Gl, shader_id: WebGLShaderId, chan: WebGLSender) { - let log = gl.get_shader_info_log(shader_id.get()); - chan.send(log).unwrap(); - } - - fn program_info_log(gl: &gl::Gl, program_id: WebGLProgramId, chan: WebGLSender) { - let log = gl.get_program_info_log(program_id.get()); - chan.send(log).unwrap(); - } - - #[allow(unsafe_code)] - fn create_buffer(gl: &gl::Gl, chan: WebGLSender>) { - let buffer = gl.gen_buffers(1)[0]; - let buffer = if buffer == 0 { - None - } else { - Some(unsafe { WebGLBufferId::new(buffer) }) - }; - chan.send(buffer).unwrap(); - } - - #[allow(unsafe_code)] - fn create_framebuffer(gl: &gl::Gl, chan: WebGLSender>) { - let framebuffer = gl.gen_framebuffers(1)[0]; - let framebuffer = if framebuffer == 0 { - None - } else { - Some(unsafe { WebGLFramebufferId::new(framebuffer) }) - }; - chan.send(framebuffer).unwrap(); - } - - #[allow(unsafe_code)] - fn create_renderbuffer(gl: &gl::Gl, chan: WebGLSender>) { - let renderbuffer = gl.gen_renderbuffers(1)[0]; - let renderbuffer = if renderbuffer == 0 { - None - } else { - Some(unsafe { WebGLRenderbufferId::new(renderbuffer) }) - }; - chan.send(renderbuffer).unwrap(); - } - - #[allow(unsafe_code)] - fn create_texture(gl: &gl::Gl, chan: WebGLSender>) { - let texture = gl.gen_textures(1)[0]; - let texture = if texture == 0 { - None - } else { - Some(unsafe { WebGLTextureId::new(texture) }) - }; - chan.send(texture).unwrap(); - } - - #[allow(unsafe_code)] - fn create_program(gl: &gl::Gl, chan: WebGLSender>) { - let program = gl.create_program(); - let program = if program == 0 { - None - } else { - Some(unsafe { WebGLProgramId::new(program) }) - }; - chan.send(program).unwrap(); - } - - #[allow(unsafe_code)] - fn create_shader(gl: &gl::Gl, shader_type: u32, chan: WebGLSender>) { - let shader = gl.create_shader(shader_type); - let shader = if shader == 0 { - None - } else { - Some(unsafe { WebGLShaderId::new(shader) }) - }; - chan.send(shader).unwrap(); - } - - #[allow(unsafe_code)] - fn create_vertex_array(gl: &gl::Gl, chan: WebGLSender>) { - let vao = gl.gen_vertex_arrays(1)[0]; - let vao = if vao == 0 { - None - } else { - Some(unsafe { WebGLVertexArrayId::new(vao) }) - }; - chan.send(vao).unwrap(); - } - - #[inline] - fn bind_framebuffer(gl: &gl::Gl, - target: u32, - request: WebGLFramebufferBindingRequest, - ctx: &GLContext) { - let id = match request { - WebGLFramebufferBindingRequest::Explicit(id) => id.get(), - WebGLFramebufferBindingRequest::Default => - ctx.borrow_draw_buffer().unwrap().get_framebuffer(), - }; - - gl.bind_framebuffer(target, id); - } - - - #[inline] - fn compile_shader(gl: &gl::Gl, shader_id: WebGLShaderId, source: String) { - gl.shader_source(shader_id.get(), &[source.as_bytes()]); - gl.compile_shader(shader_id.get()); - } -} diff --git a/servo/components/canvas_traits/Cargo.toml b/servo/components/canvas_traits/Cargo.toml deleted file mode 100644 index 3758e9205565..000000000000 --- a/servo/components/canvas_traits/Cargo.toml +++ /dev/null @@ -1,24 +0,0 @@ -[package] -name = "canvas_traits" -version = "0.0.1" -authors = ["The Servo Project Developers"] -license = "MPL-2.0" -publish = false - -[lib] -name = "canvas_traits" -path = "lib.rs" - -[dependencies] -cssparser = "0.23.0" -euclid = "0.17" -ipc-channel = "0.10" -lazy_static = "1" -malloc_size_of = { path = "../malloc_size_of" } -malloc_size_of_derive = { path = "../malloc_size_of_derive" } -nonzero = {path = "../nonzero"} -offscreen_gl_context = { version = "0.15", features = ["serde"] } -serde = "1.0" -serde_bytes = "0.10" -servo_config = {path = "../config"} -webrender_api = {git = "https://github.com/servo/webrender", features = ["ipc"]} diff --git a/servo/components/canvas_traits/canvas.rs b/servo/components/canvas_traits/canvas.rs deleted file mode 100644 index a8cd79cae325..000000000000 --- a/servo/components/canvas_traits/canvas.rs +++ /dev/null @@ -1,419 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -use cssparser::RGBA; -use euclid::{Transform2D, Point2D, Vector2D, Rect, Size2D}; -use ipc_channel::ipc::IpcSender; -use serde_bytes::ByteBuf; -use std::default::Default; -use std::str::FromStr; -use webrender_api; - -#[derive(Clone, Deserialize, Serialize)] -pub enum FillRule { - Nonzero, - Evenodd, -} - -#[derive(Clone, Deserialize, MallocSizeOf, PartialEq, Serialize)] -pub struct CanvasId(pub u64); - -#[derive(Clone, Deserialize, Serialize)] -pub enum CanvasMsg { - Canvas2d(Canvas2dMsg, CanvasId), - FromLayout(FromLayoutMsg, CanvasId), - FromScript(FromScriptMsg, CanvasId), - Recreate(Size2D, CanvasId), - Close(CanvasId), -} - -#[derive(Clone, Deserialize, Serialize)] -pub struct CanvasImageData { - pub image_key: webrender_api::ImageKey, -} - -#[derive(Clone, Deserialize, Serialize)] -pub enum Canvas2dMsg { - Arc(Point2D, f32, f32, f32, bool), - ArcTo(Point2D, Point2D, f32), - DrawImage(ByteBuf, Size2D, Rect, Rect, bool), - DrawImageSelf(Size2D, Rect, Rect, bool), - DrawImageInOther( - IpcSender, CanvasId, Size2D, Rect, Rect, bool, IpcSender<()>), - BeginPath, - BezierCurveTo(Point2D, Point2D, Point2D), - ClearRect(Rect), - Clip, - ClosePath, - Ellipse(Point2D, f32, f32, f32, f32, f32, bool), - Fill, - FillText(String, f64, f64, Option), - FillRect(Rect), - GetImageData(Rect, Size2D, IpcSender), - IsPointInPath(f64, f64, FillRule, IpcSender), - LineTo(Point2D), - MoveTo(Point2D), - PutImageData(ByteBuf, Vector2D, Size2D, Rect), - QuadraticCurveTo(Point2D, Point2D), - Rect(Rect), - RestoreContext, - SaveContext, - StrokeRect(Rect), - Stroke, - SetFillStyle(FillOrStrokeStyle), - SetStrokeStyle(FillOrStrokeStyle), - SetLineWidth(f32), - SetLineCap(LineCapStyle), - SetLineJoin(LineJoinStyle), - SetMiterLimit(f32), - SetGlobalAlpha(f32), - SetGlobalComposition(CompositionOrBlending), - SetTransform(Transform2D), - SetShadowOffsetX(f64), - SetShadowOffsetY(f64), - SetShadowBlur(f64), - SetShadowColor(RGBA), -} - -#[derive(Clone, Deserialize, Serialize)] -pub enum FromLayoutMsg { - SendData(IpcSender), -} - -#[derive(Clone, Deserialize, Serialize)] -pub enum FromScriptMsg { - SendPixels(IpcSender>), -} - -#[derive(Clone, Deserialize, MallocSizeOf, Serialize)] -pub struct CanvasGradientStop { - pub offset: f64, - pub color: RGBA, -} - -#[derive(Clone, Deserialize, MallocSizeOf, Serialize)] -pub struct LinearGradientStyle { - pub x0: f64, - pub y0: f64, - pub x1: f64, - pub y1: f64, - pub stops: Vec -} - -impl LinearGradientStyle { - pub fn new(x0: f64, y0: f64, x1: f64, y1: f64, stops: Vec) - -> LinearGradientStyle { - LinearGradientStyle { - x0: x0, - y0: y0, - x1: x1, - y1: y1, - stops: stops, - } - } -} - -#[derive(Clone, Deserialize, MallocSizeOf, Serialize)] -pub struct RadialGradientStyle { - pub x0: f64, - pub y0: f64, - pub r0: f64, - pub x1: f64, - pub y1: f64, - pub r1: f64, - pub stops: Vec -} - -impl RadialGradientStyle { - pub fn new(x0: f64, y0: f64, r0: f64, x1: f64, y1: f64, r1: f64, stops: Vec) - -> RadialGradientStyle { - RadialGradientStyle { - x0: x0, - y0: y0, - r0: r0, - x1: x1, - y1: y1, - r1: r1, - stops: stops, - } - } -} - -#[derive(Clone, Deserialize, Serialize)] -pub struct SurfaceStyle { - pub surface_data: ByteBuf, - pub surface_size: Size2D, - pub repeat_x: bool, - pub repeat_y: bool, -} - -impl SurfaceStyle { - pub fn new( - surface_data: Vec, - surface_size: Size2D, - repeat_x: bool, - repeat_y: bool, - ) -> Self { - Self { - surface_data: surface_data.into(), - surface_size, - repeat_x, - repeat_y, - } - } -} - - -#[derive(Clone, Deserialize, Serialize)] -pub enum FillOrStrokeStyle { - Color(RGBA), - LinearGradient(LinearGradientStyle), - RadialGradient(RadialGradientStyle), - Surface(SurfaceStyle), -} - -#[derive(Clone, Copy, Deserialize, MallocSizeOf, PartialEq, Serialize)] -pub enum LineCapStyle { - Butt = 0, - Round = 1, - Square = 2, -} - -impl FromStr for LineCapStyle { - type Err = (); - - fn from_str(string: &str) -> Result { - match string { - "butt" => Ok(LineCapStyle::Butt), - "round" => Ok(LineCapStyle::Round), - "square" => Ok(LineCapStyle::Square), - _ => Err(()), - } - } -} - -#[derive(Clone, Copy, Deserialize, MallocSizeOf, PartialEq, Serialize)] -pub enum LineJoinStyle { - Round = 0, - Bevel = 1, - Miter = 2, -} - -impl FromStr for LineJoinStyle { - type Err = (); - - fn from_str(string: &str) -> Result { - match string { - "round" => Ok(LineJoinStyle::Round), - "bevel" => Ok(LineJoinStyle::Bevel), - "miter" => Ok(LineJoinStyle::Miter), - _ => Err(()), - } - } -} - -#[derive(Clone, Copy, Deserialize, PartialEq, Serialize)] -pub enum RepetitionStyle { - Repeat, - RepeatX, - RepeatY, - NoRepeat, -} - -impl FromStr for RepetitionStyle { - type Err = (); - - fn from_str(string: &str) -> Result { - match string { - "repeat" => Ok(RepetitionStyle::Repeat), - "repeat-x" => Ok(RepetitionStyle::RepeatX), - "repeat-y" => Ok(RepetitionStyle::RepeatY), - "no-repeat" => Ok(RepetitionStyle::NoRepeat), - _ => Err(()), - } - } -} - -#[derive(Clone, Copy, Deserialize, MallocSizeOf, PartialEq, Serialize)] -pub enum CompositionStyle { - SrcIn, - SrcOut, - SrcOver, - SrcAtop, - DestIn, - DestOut, - DestOver, - DestAtop, - Copy, - Lighter, - Xor, -} - -impl FromStr for CompositionStyle { - type Err = (); - - fn from_str(string: &str) -> Result { - match string { - "source-in" => Ok(CompositionStyle::SrcIn), - "source-out" => Ok(CompositionStyle::SrcOut), - "source-over" => Ok(CompositionStyle::SrcOver), - "source-atop" => Ok(CompositionStyle::SrcAtop), - "destination-in" => Ok(CompositionStyle::DestIn), - "destination-out" => Ok(CompositionStyle::DestOut), - "destination-over" => Ok(CompositionStyle::DestOver), - "destination-atop" => Ok(CompositionStyle::DestAtop), - "copy" => Ok(CompositionStyle::Copy), - "lighter" => Ok(CompositionStyle::Lighter), - "xor" => Ok(CompositionStyle::Xor), - _ => Err(()) - } - } -} - -impl CompositionStyle { - pub fn to_str(&self) -> &str { - match *self { - CompositionStyle::SrcIn => "source-in", - CompositionStyle::SrcOut => "source-out", - CompositionStyle::SrcOver => "source-over", - CompositionStyle::SrcAtop => "source-atop", - CompositionStyle::DestIn => "destination-in", - CompositionStyle::DestOut => "destination-out", - CompositionStyle::DestOver => "destination-over", - CompositionStyle::DestAtop => "destination-atop", - CompositionStyle::Copy => "copy", - CompositionStyle::Lighter => "lighter", - CompositionStyle::Xor => "xor", - } - } -} - -#[derive(Clone, Copy, Deserialize, MallocSizeOf, PartialEq, Serialize)] -pub enum BlendingStyle { - Multiply, - Screen, - Overlay, - Darken, - Lighten, - ColorDodge, - ColorBurn, - HardLight, - SoftLight, - Difference, - Exclusion, - Hue, - Saturation, - Color, - Luminosity, -} - -impl FromStr for BlendingStyle { - type Err = (); - - fn from_str(string: &str) -> Result { - match string { - "multiply" => Ok(BlendingStyle::Multiply), - "screen" => Ok(BlendingStyle::Screen), - "overlay" => Ok(BlendingStyle::Overlay), - "darken" => Ok(BlendingStyle::Darken), - "lighten" => Ok(BlendingStyle::Lighten), - "color-dodge" => Ok(BlendingStyle::ColorDodge), - "color-burn" => Ok(BlendingStyle::ColorBurn), - "hard-light" => Ok(BlendingStyle::HardLight), - "soft-light" => Ok(BlendingStyle::SoftLight), - "difference" => Ok(BlendingStyle::Difference), - "exclusion" => Ok(BlendingStyle::Exclusion), - "hue" => Ok(BlendingStyle::Hue), - "saturation" => Ok(BlendingStyle::Saturation), - "color" => Ok(BlendingStyle::Color), - "luminosity" => Ok(BlendingStyle::Luminosity), - _ => Err(()) - } - } -} - -impl BlendingStyle { - pub fn to_str(&self) -> &str { - match *self { - BlendingStyle::Multiply => "multiply", - BlendingStyle::Screen => "screen", - BlendingStyle::Overlay => "overlay", - BlendingStyle::Darken => "darken", - BlendingStyle::Lighten => "lighten", - BlendingStyle::ColorDodge => "color-dodge", - BlendingStyle::ColorBurn => "color-burn", - BlendingStyle::HardLight => "hard-light", - BlendingStyle::SoftLight => "soft-light", - BlendingStyle::Difference => "difference", - BlendingStyle::Exclusion => "exclusion", - BlendingStyle::Hue => "hue", - BlendingStyle::Saturation => "saturation", - BlendingStyle::Color => "color", - BlendingStyle::Luminosity => "luminosity", - } - } -} - -#[derive(Clone, Copy, Deserialize, MallocSizeOf, PartialEq, Serialize)] -pub enum CompositionOrBlending { - Composition(CompositionStyle), - Blending(BlendingStyle), -} - -impl Default for CompositionOrBlending { - fn default() -> CompositionOrBlending { - CompositionOrBlending::Composition(CompositionStyle::SrcOver) - } -} - -impl FromStr for CompositionOrBlending { - type Err = (); - - fn from_str(string: &str) -> Result { - if let Ok(op) = CompositionStyle::from_str(string) { - return Ok(CompositionOrBlending::Composition(op)); - } - - if let Ok(op) = BlendingStyle::from_str(string) { - return Ok(CompositionOrBlending::Blending(op)); - } - - Err(()) - } -} - -// TODO(pcwalton): Speed up with SIMD, or better yet, find some way to not do this. -pub fn byte_swap(data: &mut [u8]) { - let length = data.len(); - // FIXME(rust #27741): Range::step_by is not stable yet as of this writing. - let mut i = 0; - while i < length { - let r = data[i + 2]; - data[i + 2] = data[i + 0]; - data[i + 0] = r; - i += 4; - } -} - -pub fn multiply_u8_pixel(a: u8, b: u8) -> u8 { - return (a as u32 * b as u32 / 255) as u8; -} - -pub fn byte_swap_and_premultiply(data: &mut [u8]) { - let length = data.len(); - - let mut i = 0; - while i < length { - let r = data[i + 2]; - let g = data[i + 1]; - let b = data[i + 0]; - let a = data[i + 3]; - - data[i + 0] = multiply_u8_pixel(r, a); - data[i + 1] = multiply_u8_pixel(g, a); - data[i + 2] = multiply_u8_pixel(b, a); - - i += 4; - } -} diff --git a/servo/components/canvas_traits/lib.rs b/servo/components/canvas_traits/lib.rs deleted file mode 100644 index 20423143e21f..000000000000 --- a/servo/components/canvas_traits/lib.rs +++ /dev/null @@ -1,25 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -#![crate_name = "canvas_traits"] -#![crate_type = "rlib"] - -#![deny(unsafe_code)] - -extern crate cssparser; -extern crate euclid; -extern crate ipc_channel; -#[macro_use] extern crate lazy_static; -extern crate malloc_size_of; -#[macro_use] extern crate malloc_size_of_derive; -extern crate nonzero; -extern crate offscreen_gl_context; -#[macro_use] extern crate serde; -extern crate serde_bytes; -extern crate servo_config; -extern crate webrender_api; - -pub mod canvas; -pub mod webgl; -mod webgl_channel; diff --git a/servo/components/canvas_traits/webgl.rs b/servo/components/canvas_traits/webgl.rs deleted file mode 100644 index cbb088e710cb..000000000000 --- a/servo/components/canvas_traits/webgl.rs +++ /dev/null @@ -1,555 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -use euclid::Size2D; -use nonzero::NonZeroU32; -use offscreen_gl_context::{GLContextAttributes, GLLimits}; -use serde_bytes::ByteBuf; -use std::fmt; -use webrender_api::{DocumentId, ImageKey, PipelineId}; - -/// Sender type used in WebGLCommands. -pub use ::webgl_channel::WebGLSender; -/// Receiver type used in WebGLCommands. -pub use ::webgl_channel::WebGLReceiver; -/// Result type for send()/recv() calls in in WebGLCommands. -pub use ::webgl_channel::WebGLSendResult; -/// Helper function that creates a WebGL channel (WebGLSender, WebGLReceiver) to be used in WebGLCommands. -pub use ::webgl_channel::webgl_channel; -/// Entry point type used in a Script Pipeline to get the WebGLChan to be used in that thread. -pub use ::webgl_channel::WebGLPipeline; -/// Entry point channel type used for sending WebGLMsg messages to the WebGL renderer. -pub use ::webgl_channel::WebGLChan; - -/// WebGL Message API -#[derive(Clone, Deserialize, Serialize)] -pub enum WebGLMsg { - /// Creates a new WebGLContext. - CreateContext(WebGLVersion, Size2D, GLContextAttributes, - WebGLSender>), - /// Resizes a WebGLContext. - ResizeContext(WebGLContextId, Size2D, WebGLSender>), - /// Drops a WebGLContext. - RemoveContext(WebGLContextId), - /// Runs a WebGLCommand in a specific WebGLContext. - WebGLCommand(WebGLContextId, WebGLCommand), - /// Runs a WebVRCommand in a specific WebGLContext. - WebVRCommand(WebGLContextId, WebVRCommand), - /// Locks a specific WebGLContext. Lock messages are used for a correct synchronization - /// with WebRender external image API. - /// WR locks a external texture when it wants to use the shared texture contents. - /// The WR client should not change the shared texture content until the Unlock call. - /// Currently OpenGL Sync Objects are used to implement the synchronization mechanism. - Lock(WebGLContextId, WebGLSender<(u32, Size2D, usize)>), - /// Unlocks a specific WebGLContext. Unlock messages are used for a correct synchronization - /// with WebRender external image API. - /// The WR unlocks a context when it finished reading the shared texture contents. - /// Unlock messages are always sent after a Lock message. - Unlock(WebGLContextId), - /// Creates or updates the image keys required for WebRender. - UpdateWebRenderImage(WebGLContextId, WebGLSender), - /// Commands used for the DOMToTexture feature. - DOMToTextureCommand(DOMToTextureCommand), - /// Frees all resources and closes the thread. - Exit, -} - -/// Contains the WebGLCommand sender and information about a WebGLContext -#[derive(Clone, Deserialize, Serialize)] -pub struct WebGLCreateContextResult { - /// Sender instance to send commands to the specific WebGLContext - pub sender: WebGLMsgSender, - /// Information about the internal GL Context. - pub limits: GLLimits, - /// How the WebGLContext is shared with WebRender. - pub share_mode: WebGLContextShareMode, - /// The GLSL version supported by the context. - pub glsl_version: WebGLSLVersion -} - -#[derive(Clone, Copy, Deserialize, MallocSizeOf, Serialize)] -pub enum WebGLContextShareMode { - /// Fast: a shared texture_id is used in WebRender. - SharedTexture, - /// Slow: glReadPixels is used to send pixels to WebRender each frame. - Readback, -} - -/// Defines the WebGL version -#[derive(Clone, Copy, Deserialize, Eq, MallocSizeOf, PartialEq, Serialize)] -pub enum WebGLVersion { - /// https://www.khronos.org/registry/webgl/specs/1.0.2/ - /// Conforms closely to the OpenGL ES 2.0 API - WebGL1, - /// https://www.khronos.org/registry/webgl/specs/latest/2.0/ - /// Conforms closely to the OpenGL ES 3.0 API - WebGL2, -} - -/// Defines the GLSL version supported by the WebGL backend contexts. -#[derive(Clone, Copy, Deserialize, Eq, MallocSizeOf, PartialEq, Serialize)] -pub struct WebGLSLVersion { - /// Major GLSL version - pub major: u32, - /// Minor GLSL version - pub minor: u32, -} - -/// Helper struct to send WebGLCommands to a specific WebGLContext. -#[derive(Clone, Deserialize, MallocSizeOf, Serialize)] -pub struct WebGLMsgSender { - ctx_id: WebGLContextId, - #[ignore_malloc_size_of = "channels are hard"] - sender: WebGLChan, -} - -impl WebGLMsgSender { - pub fn new(id: WebGLContextId, sender: WebGLChan) -> Self { - WebGLMsgSender { - ctx_id: id, - sender: sender, - } - } - - /// Returns the WebGLContextId associated to this sender - pub fn context_id(&self) -> WebGLContextId { - self.ctx_id - } - - /// Send a WebGLCommand message - #[inline] - pub fn send(&self, command: WebGLCommand) -> WebGLSendResult { - self.sender.send(WebGLMsg::WebGLCommand(self.ctx_id, command)) - } - - /// Send a WebVRCommand message - #[inline] - pub fn send_vr(&self, command: WebVRCommand) -> WebGLSendResult { - self.sender.send(WebGLMsg::WebVRCommand(self.ctx_id, command)) - } - - /// Send a resize message - #[inline] - pub fn send_resize(&self, - size: Size2D, - sender: WebGLSender>) - -> WebGLSendResult { - self.sender.send(WebGLMsg::ResizeContext(self.ctx_id, size, sender)) - } - - #[inline] - pub fn send_remove(&self) -> WebGLSendResult { - self.sender.send(WebGLMsg::RemoveContext(self.ctx_id)) - } - - #[inline] - pub fn send_update_wr_image(&self, sender: WebGLSender) -> WebGLSendResult { - self.sender.send(WebGLMsg::UpdateWebRenderImage(self.ctx_id, sender)) - } - - pub fn send_dom_to_texture(&self, command: DOMToTextureCommand) -> WebGLSendResult { - self.sender.send(WebGLMsg::DOMToTextureCommand(command)) - } -} - -/// WebGL Commands for a specific WebGLContext -#[derive(Clone, Deserialize, Serialize)] -pub enum WebGLCommand { - GetContextAttributes(WebGLSender), - ActiveTexture(u32), - BlendColor(f32, f32, f32, f32), - BlendEquation(u32), - BlendEquationSeparate(u32, u32), - BlendFunc(u32, u32), - BlendFuncSeparate(u32, u32, u32, u32), - AttachShader(WebGLProgramId, WebGLShaderId), - DetachShader(WebGLProgramId, WebGLShaderId), - BindAttribLocation(WebGLProgramId, u32, String), - BufferData(u32, ByteBuf, u32), - BufferSubData(u32, isize, ByteBuf), - Clear(u32), - ClearColor(f32, f32, f32, f32), - ClearDepth(f32), - ClearStencil(i32), - ColorMask(bool, bool, bool, bool), - CullFace(u32), - FrontFace(u32), - DepthFunc(u32), - DepthMask(bool), - DepthRange(f32, f32), - Enable(u32), - Disable(u32), - CompileShader(WebGLShaderId, String), - CopyTexImage2D(u32, i32, u32, i32, i32, i32, i32, i32), - CopyTexSubImage2D(u32, i32, i32, i32, i32, i32, i32, i32), - CreateBuffer(WebGLSender>), - CreateFramebuffer(WebGLSender>), - CreateRenderbuffer(WebGLSender>), - CreateTexture(WebGLSender>), - CreateProgram(WebGLSender>), - CreateShader(u32, WebGLSender>), - DeleteBuffer(WebGLBufferId), - DeleteFramebuffer(WebGLFramebufferId), - DeleteRenderbuffer(WebGLRenderbufferId), - DeleteTexture(WebGLTextureId), - DeleteProgram(WebGLProgramId), - DeleteShader(WebGLShaderId), - BindBuffer(u32, Option), - BindFramebuffer(u32, WebGLFramebufferBindingRequest), - BindRenderbuffer(u32, Option), - BindTexture(u32, Option), - DisableVertexAttribArray(u32), - DrawArrays(u32, i32, i32), - DrawElements(u32, i32, u32, i64), - EnableVertexAttribArray(u32), - FramebufferRenderbuffer(u32, u32, u32, Option), - FramebufferTexture2D(u32, u32, u32, Option, i32), - GetExtensions(WebGLSender), - GetParameter(u32, WebGLSender>), - GetTexParameter(u32, u32, WebGLSender), - GetProgramParameter(WebGLProgramId, u32, WebGLSender>), - GetShaderParameter(WebGLShaderId, u32, WebGLSender>), - GetShaderPrecisionFormat(u32, u32, WebGLSender<(i32, i32, i32)>), - GetActiveAttrib(WebGLProgramId, u32, WebGLSender>), - GetActiveUniform(WebGLProgramId, u32, WebGLSender>), - GetAttribLocation(WebGLProgramId, String, WebGLSender>), - GetUniformLocation(WebGLProgramId, String, WebGLSender>), - GetVertexAttrib(u32, u32, WebGLSender>), - GetVertexAttribOffset(u32, u32, WebGLSender), - GetShaderInfoLog(WebGLShaderId, WebGLSender), - GetProgramInfoLog(WebGLProgramId, WebGLSender), - GetFramebufferAttachmentParameter(u32, u32, u32, WebGLSender), - PolygonOffset(f32, f32), - RenderbufferStorage(u32, u32, i32, i32), - ReadPixels(i32, i32, i32, i32, u32, u32, WebGLSender), - SampleCoverage(f32, bool), - Scissor(i32, i32, i32, i32), - StencilFunc(u32, i32, u32), - StencilFuncSeparate(u32, u32, i32, u32), - StencilMask(u32), - StencilMaskSeparate(u32, u32), - StencilOp(u32, u32, u32), - StencilOpSeparate(u32, u32, u32, u32), - Hint(u32, u32), - IsEnabled(u32, WebGLSender), - LineWidth(f32), - PixelStorei(u32, i32), - LinkProgram(WebGLProgramId), - Uniform1f(i32, f32), - Uniform1fv(i32, Vec), - Uniform1i(i32, i32), - Uniform1iv(i32, Vec), - Uniform2f(i32, f32, f32), - Uniform2fv(i32, Vec), - Uniform2i(i32, i32, i32), - Uniform2iv(i32, Vec), - Uniform3f(i32, f32, f32, f32), - Uniform3fv(i32, Vec), - Uniform3i(i32, i32, i32, i32), - Uniform3iv(i32, Vec), - Uniform4f(i32, f32, f32, f32, f32), - Uniform4fv(i32, Vec), - Uniform4i(i32, i32, i32, i32, i32), - Uniform4iv(i32, Vec), - UniformMatrix2fv(i32, bool, Vec), - UniformMatrix3fv(i32, bool, Vec), - UniformMatrix4fv(i32, bool, Vec), - UseProgram(WebGLProgramId), - ValidateProgram(WebGLProgramId), - VertexAttrib(u32, f32, f32, f32, f32), - VertexAttribPointer(u32, i32, u32, bool, i32, u32), - VertexAttribPointer2f(u32, i32, bool, i32, u32), - GetViewport(WebGLSender<(i32, i32, i32, i32)>), - SetViewport(i32, i32, i32, i32), - TexImage2D(u32, i32, i32, i32, i32, u32, u32, ByteBuf), - TexParameteri(u32, u32, i32), - TexParameterf(u32, u32, f32), - TexSubImage2D(u32, i32, i32, i32, i32, i32, u32, u32, ByteBuf), - DrawingBufferWidth(WebGLSender), - DrawingBufferHeight(WebGLSender), - Finish(WebGLSender<()>), - Flush, - GenerateMipmap(u32), - CreateVertexArray(WebGLSender>), - DeleteVertexArray(WebGLVertexArrayId), - BindVertexArray(Option), - AliasedPointSizeRange(WebGLSender<(f32, f32)>), -} - -macro_rules! define_resource_id_struct { - ($name:ident) => { - #[derive(Clone, Copy, Eq, Hash, PartialEq)] - pub struct $name(NonZeroU32); - - impl $name { - #[allow(unsafe_code)] - #[inline] - pub unsafe fn new(id: u32) -> Self { - $name(NonZeroU32::new_unchecked(id)) - } - - #[inline] - pub fn get(self) -> u32 { - self.0.get() - } - } - - }; -} - -macro_rules! define_resource_id { - ($name:ident) => { - define_resource_id_struct!($name); - - #[allow(unsafe_code)] - impl<'de> ::serde::Deserialize<'de> for $name { - fn deserialize(deserializer: D) -> Result - where D: ::serde::Deserializer<'de> - { - let id = try!(u32::deserialize(deserializer)); - if id == 0 { - Err(::serde::de::Error::custom("expected a non-zero value")) - } else { - Ok(unsafe { $name::new(id) }) - } - } - } - - impl ::serde::Serialize for $name { - fn serialize(&self, serializer: S) -> Result - where S: ::serde::Serializer - { - self.get().serialize(serializer) - } - } - - impl ::std::fmt::Debug for $name { - fn fmt(&self, fmt: &mut ::std::fmt::Formatter) - -> Result<(), ::std::fmt::Error> { - fmt.debug_tuple(stringify!($name)) - .field(&self.get()) - .finish() - } - } - - impl ::std::fmt::Display for $name { - fn fmt(&self, fmt: &mut ::std::fmt::Formatter) - -> Result<(), ::std::fmt::Error> { - write!(fmt, "{}", self.get()) - } - } - - impl ::malloc_size_of::MallocSizeOf for $name { - fn size_of(&self, _ops: &mut ::malloc_size_of::MallocSizeOfOps) -> usize { 0 } - } - } -} - -define_resource_id!(WebGLBufferId); -define_resource_id!(WebGLFramebufferId); -define_resource_id!(WebGLRenderbufferId); -define_resource_id!(WebGLTextureId); -define_resource_id!(WebGLProgramId); -define_resource_id!(WebGLShaderId); -define_resource_id!(WebGLVertexArrayId); - -#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, MallocSizeOf, Ord)] -#[derive(PartialEq, PartialOrd, Serialize)] -pub struct WebGLContextId(pub usize); - -#[derive(Clone, Copy, Debug, Deserialize, PartialEq, Serialize)] -pub enum WebGLError { - InvalidEnum, - InvalidFramebufferOperation, - InvalidOperation, - InvalidValue, - OutOfMemory, - ContextLost, -} - -#[derive(Clone, Debug, Deserialize, Serialize)] -pub enum WebGLFramebufferBindingRequest { - Explicit(WebGLFramebufferId), - Default, -} - -#[derive(Clone, Debug, Deserialize, Serialize)] -pub enum WebGLParameter { - Int(i32), - Bool(bool), - String(String), - Float(f32), - FloatArray(Vec), - Invalid, -} - -pub type WebGLResult = Result; - -#[derive(Clone, Debug, Deserialize, Serialize)] -pub enum WebGLShaderParameter { - Int(i32), - Bool(bool), - Invalid, -} - -pub type WebVRDeviceId = u32; - -// WebVR commands that must be called in the WebGL render thread. -#[derive(Clone, Deserialize, Serialize)] -pub enum WebVRCommand { - /// Start presenting to a VR device. - Create(WebVRDeviceId), - /// Synchronize the pose information to be used in the frame. - SyncPoses(WebVRDeviceId, f64, f64, WebGLSender>), - /// Submit the frame to a VR device using the specified texture coordinates. - SubmitFrame(WebVRDeviceId, [f32; 4], [f32; 4]), - /// Stop presenting to a VR device - Release(WebVRDeviceId) -} - -// Trait object that handles WebVR commands. -// Receives the texture id and size associated to the WebGLContext. -pub trait WebVRRenderHandler: Send { - fn handle(&mut self, command: WebVRCommand, texture: Option<(u32, Size2D)>); -} - -/// WebGL commands required to implement DOMToTexture feature. -#[derive(Clone, Deserialize, Serialize)] -pub enum DOMToTextureCommand { - /// Attaches a HTMLIFrameElement to a WebGLTexture. - Attach(WebGLContextId, WebGLTextureId, DocumentId, PipelineId, Size2D), - /// Releases the HTMLIFrameElement to WebGLTexture attachment. - Detach(WebGLTextureId), - /// Lock message used for a correct synchronization with WebRender GL flow. - Lock(PipelineId, usize, WebGLSender)>>), -} - -impl fmt::Debug for WebGLCommand { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - use self::WebGLCommand::*; - let name = match *self { - GetContextAttributes(..) => "GetContextAttributes", - ActiveTexture(..) => "ActiveTexture", - BlendColor(..) => "BlendColor", - BlendEquation(..) => "BlendEquation", - BlendEquationSeparate(..) => "BlendEquationSeparate", - BlendFunc(..) => "BlendFunc", - BlendFuncSeparate(..) => "BlendFuncSeparate", - AttachShader(..) => "AttachShader", - DetachShader(..) => "DetachShader", - BindAttribLocation(..) => "BindAttribLocation", - BufferData(..) => "BufferData", - BufferSubData(..) => "BufferSubData", - Clear(..) => "Clear", - ClearColor(..) => "ClearColor", - ClearDepth(..) => "ClearDepth", - ClearStencil(..) => "ClearStencil", - ColorMask(..) => "ColorMask", - CopyTexImage2D(..) => "CopyTexImage2D", - CopyTexSubImage2D(..) => "CopyTexSubImage2D", - CullFace(..) => "CullFace", - FrontFace(..) => "FrontFace", - DepthFunc(..) => "DepthFunc", - DepthMask(..) => "DepthMask", - DepthRange(..) => "DepthRange", - Enable(..) => "Enable", - Disable(..) => "Disable", - CompileShader(..) => "CompileShader", - CreateBuffer(..) => "CreateBuffer", - CreateFramebuffer(..) => "CreateFramebuffer", - CreateRenderbuffer(..) => "CreateRenderbuffer", - CreateTexture(..) => "CreateTexture", - CreateProgram(..) => "CreateProgram", - CreateShader(..) => "CreateShader", - DeleteBuffer(..) => "DeleteBuffer", - DeleteFramebuffer(..) => "DeleteFramebuffer", - DeleteRenderbuffer(..) => "DeleteRenderBuffer", - DeleteTexture(..) => "DeleteTexture", - DeleteProgram(..) => "DeleteProgram", - DeleteShader(..) => "DeleteShader", - BindBuffer(..) => "BindBuffer", - BindFramebuffer(..) => "BindFramebuffer", - BindRenderbuffer(..) => "BindRenderbuffer", - BindTexture(..) => "BindTexture", - DisableVertexAttribArray(..) => "DisableVertexAttribArray", - DrawArrays(..) => "DrawArrays", - DrawElements(..) => "DrawElements", - EnableVertexAttribArray(..) => "EnableVertexAttribArray", - FramebufferRenderbuffer(..) => "FramebufferRenderbuffer", - FramebufferTexture2D(..) => "FramebufferTexture2D", - GetExtensions(..) => "GetExtensions", - GetParameter(..) => "GetParameter", - GetTexParameter(..) => "GetTexParameter", - GetProgramParameter(..) => "GetProgramParameter", - GetShaderParameter(..) => "GetShaderParameter", - GetShaderPrecisionFormat(..) => "GetShaderPrecisionFormat", - GetActiveAttrib(..) => "GetActiveAttrib", - GetActiveUniform(..) => "GetActiveUniform", - GetAttribLocation(..) => "GetAttribLocation", - GetUniformLocation(..) => "GetUniformLocation", - GetShaderInfoLog(..) => "GetShaderInfoLog", - GetProgramInfoLog(..) => "GetProgramInfoLog", - GetVertexAttrib(..) => "GetVertexAttrib", - GetVertexAttribOffset(..) => "GetVertexAttribOffset", - GetFramebufferAttachmentParameter(..) => "GetFramebufferAttachmentParameter", - PolygonOffset(..) => "PolygonOffset", - ReadPixels(..) => "ReadPixels", - RenderbufferStorage(..) => "RenderbufferStorage", - SampleCoverage(..) => "SampleCoverage", - Scissor(..) => "Scissor", - StencilFunc(..) => "StencilFunc", - StencilFuncSeparate(..) => "StencilFuncSeparate", - StencilMask(..) => "StencilMask", - StencilMaskSeparate(..) => "StencilMaskSeparate", - StencilOp(..) => "StencilOp", - StencilOpSeparate(..) => "StencilOpSeparate", - Hint(..) => "Hint", - IsEnabled(..) => "IsEnabled", - LineWidth(..) => "LineWidth", - PixelStorei(..) => "PixelStorei", - LinkProgram(..) => "LinkProgram", - Uniform1f(..) => "Uniform1f", - Uniform1fv(..) => "Uniform1fv", - Uniform1i(..) => "Uniform1i", - Uniform1iv(..) => "Uniform1iv", - Uniform2f(..) => "Uniform2f", - Uniform2fv(..) => "Uniform2fv", - Uniform2i(..) => "Uniform2i", - Uniform2iv(..) => "Uniform2iv", - Uniform3f(..) => "Uniform3f", - Uniform3fv(..) => "Uniform3fv", - Uniform3i(..) => "Uniform3i", - Uniform3iv(..) => "Uniform3iv", - Uniform4f(..) => "Uniform4f", - Uniform4fv(..) => "Uniform4fv", - Uniform4i(..) => "Uniform4i", - Uniform4iv(..) => "Uniform4iv", - UniformMatrix2fv(..) => "UniformMatrix2fv", - UniformMatrix3fv(..) => "UniformMatrix3fv", - UniformMatrix4fv(..) => "UniformMatrix4fv", - UseProgram(..) => "UseProgram", - ValidateProgram(..) => "ValidateProgram", - VertexAttrib(..) => "VertexAttrib", - VertexAttribPointer2f(..) => "VertexAttribPointer2f", - VertexAttribPointer(..) => "VertexAttribPointer", - GetViewport(..) => "GetViewport", - SetViewport(..) => "SetViewport", - TexImage2D(..) => "TexImage2D", - TexParameteri(..) => "TexParameteri", - TexParameterf(..) => "TexParameterf", - TexSubImage2D(..) => "TexSubImage2D", - DrawingBufferWidth(..) => "DrawingBufferWidth", - DrawingBufferHeight(..) => "DrawingBufferHeight", - Finish(..) => "Finish", - Flush => "Flush", - GenerateMipmap(..) => "GenerateMipmap", - CreateVertexArray(..) => "CreateVertexArray", - DeleteVertexArray(..) => "DeleteVertexArray", - BindVertexArray(..) => "BindVertexArray", - AliasedPointSizeRange(..) => "AliasedPointSizeRange", - }; - - write!(f, "CanvasWebGLMsg::{}(..)", name) - } -} diff --git a/servo/components/canvas_traits/webgl_channel/ipc.rs b/servo/components/canvas_traits/webgl_channel/ipc.rs deleted file mode 100644 index ac3020bbc7a0..000000000000 --- a/servo/components/canvas_traits/webgl_channel/ipc.rs +++ /dev/null @@ -1,15 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -use ipc_channel; -use serde::{Deserialize, Serialize}; -use std::io; - -pub type WebGLSender = ipc_channel::ipc::IpcSender; -pub type WebGLReceiver = ipc_channel::ipc::IpcReceiver; - -pub fn webgl_channel Deserialize<'de>>() - -> Result<(WebGLSender, WebGLReceiver), io::Error> { - ipc_channel::ipc::channel() -} diff --git a/servo/components/canvas_traits/webgl_channel/mod.rs b/servo/components/canvas_traits/webgl_channel/mod.rs deleted file mode 100644 index 1ac4ce15cb19..000000000000 --- a/servo/components/canvas_traits/webgl_channel/mod.rs +++ /dev/null @@ -1,87 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -//! Enum wrappers to be able to select different channel implementations at runtime. - -mod ipc; -mod mpsc; - -use ::webgl::WebGLMsg; -use serde::{Deserialize, Serialize}; -use servo_config::opts; - -lazy_static! { - static ref IS_MULTIPROCESS: bool = { - opts::multiprocess() - }; -} - -#[derive(Clone, Deserialize, Serialize)] -pub enum WebGLSender { - Ipc(ipc::WebGLSender), - Mpsc(mpsc::WebGLSender), -} - -impl WebGLSender { - #[inline] - pub fn send(&self, msg: T) -> WebGLSendResult { - match *self { - WebGLSender::Ipc(ref sender) => { - sender.send(msg).map_err(|_| ()) - }, - WebGLSender::Mpsc(ref sender) => { - sender.send(msg).map_err(|_| ()) - } - } - } -} - -pub type WebGLSendResult = Result<(), ()>; - -pub enum WebGLReceiver where T: for<'de> Deserialize<'de> + Serialize { - Ipc(ipc::WebGLReceiver), - Mpsc(mpsc::WebGLReceiver), -} - -impl WebGLReceiver where T: for<'de> Deserialize<'de> + Serialize { - pub fn recv(&self) -> Result { - match *self { - WebGLReceiver::Ipc(ref receiver) => { - receiver.recv().map_err(|_| ()) - }, - WebGLReceiver::Mpsc(ref receiver) => { - receiver.recv().map_err(|_| ()) - } - } - } -} - -pub fn webgl_channel() -> Result<(WebGLSender, WebGLReceiver), ()> - where T: for<'de> Deserialize<'de> + Serialize { - if *IS_MULTIPROCESS { - ipc::webgl_channel().map(|(tx, rx)| (WebGLSender::Ipc(tx), WebGLReceiver::Ipc(rx))) - .map_err(|_| ()) - } else { - mpsc::webgl_channel().map(|(tx, rx)| (WebGLSender::Mpsc(tx), WebGLReceiver::Mpsc(rx))) - } -} - -#[derive(Clone, Deserialize, Serialize)] -pub struct WebGLChan(pub WebGLSender); - -impl WebGLChan { - #[inline] - pub fn send(&self, msg: WebGLMsg) -> WebGLSendResult { - self.0.send(msg) - } -} - -#[derive(Clone, Deserialize, Serialize)] -pub struct WebGLPipeline(pub WebGLChan); - -impl WebGLPipeline { - pub fn channel(&self) -> WebGLChan { - self.0.clone() - } -} diff --git a/servo/components/canvas_traits/webgl_channel/mpsc.rs b/servo/components/canvas_traits/webgl_channel/mpsc.rs deleted file mode 100644 index b0fe29241f38..000000000000 --- a/servo/components/canvas_traits/webgl_channel/mpsc.rs +++ /dev/null @@ -1,51 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -use serde::{Deserialize, Serialize}; -use serde::{Deserializer, Serializer}; -use std::sync::mpsc; - -#[macro_use] -macro_rules! unreachable_serializable { - ($name:ident) => { - impl Serialize for $name { - fn serialize(&self, _: S) -> Result { - unreachable!(); - } - } - - impl<'a, T> Deserialize<'a> for $name { - fn deserialize(_: D) -> Result<$name, D::Error> - where D: Deserializer<'a> { - unreachable!(); - } - } - }; -} - -#[derive(Clone)] -pub struct WebGLSender(mpsc::Sender); -pub struct WebGLReceiver(mpsc::Receiver); - -impl WebGLSender { - #[inline] - pub fn send(&self, data: T) -> Result<(), mpsc::SendError> { - self.0.send(data) - } -} - -impl WebGLReceiver { - #[inline] - pub fn recv(&self) -> Result { - self.0.recv() - } -} - -pub fn webgl_channel() -> Result<(WebGLSender, WebGLReceiver), ()> { - let (sender, receiver) = mpsc::channel(); - Ok((WebGLSender(sender), WebGLReceiver(receiver))) -} - -unreachable_serializable!(WebGLReceiver); -unreachable_serializable!(WebGLSender); diff --git a/servo/components/compositing/Cargo.toml b/servo/components/compositing/Cargo.toml deleted file mode 100644 index 0948d0f0ae72..000000000000 --- a/servo/components/compositing/Cargo.toml +++ /dev/null @@ -1,35 +0,0 @@ -[package] -name = "compositing" -version = "0.0.1" -authors = ["The Servo Project Developers"] -license = "MPL-2.0" -publish = false -build = "build.rs" - -[lib] -name = "compositing" -path = "lib.rs" - -[dependencies] -euclid = "0.17" -gfx_traits = {path = "../gfx_traits"} -gleam = "0.4.29" -image = "0.18" -ipc-channel = "0.10" -libc = "0.2" -log = "0.4" -msg = {path = "../msg"} -net_traits = {path = "../net_traits"} -nonzero = {path = "../nonzero"} -profile_traits = {path = "../profile_traits"} -script_traits = {path = "../script_traits"} -servo_config = {path = "../config"} -servo_geometry = {path = "../geometry"} -servo_url = {path = "../url"} -style_traits = {path = "../style_traits"} -time = "0.1.17" -webrender = {git = "https://github.com/servo/webrender", features = ["capture"]} -webrender_api = {git = "https://github.com/servo/webrender", features = ["ipc"]} - -[build-dependencies] -toml = "0.4.5" diff --git a/servo/components/compositing/build.rs b/servo/components/compositing/build.rs deleted file mode 100644 index db081f795add..000000000000 --- a/servo/components/compositing/build.rs +++ /dev/null @@ -1,44 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -extern crate toml; - -use std::env; -use std::fs::File; -use std::io::{Read, Write}; -use std::path::Path; - -fn main() { - let lockfile_path = Path::new(&env::var("CARGO_MANIFEST_DIR").unwrap()).join("..").join("..").join("Cargo.lock"); - let revision_file_path = Path::new(&env::var_os("OUT_DIR").unwrap()).join("webrender_revision.rs"); - - let mut lockfile = String::new(); - File::open(lockfile_path).expect("Cannot open lockfile") - .read_to_string(&mut lockfile) - .expect("Failed to read lockfile"); - - match toml::from_str::(&lockfile) { - Ok(result) => { - let packages = result.get("package").expect("Cargo lockfile should contain package list"); - - match *packages { - toml::Value::Array(ref arr) => { - let source = arr - .iter() - .find(|pkg| pkg.get("name").and_then(|name| name.as_str()).unwrap_or("") == "webrender") - .and_then(|pkg| pkg.get("source").and_then(|source| source.as_str())) - .unwrap_or("unknown"); - - let parsed: Vec<&str> = source.split("#").collect(); - let revision = if parsed.len() > 1 { parsed[1] } else { source }; - - let mut revision_module_file = File::create(&revision_file_path).unwrap(); - write!(&mut revision_module_file, "{}", format!("\"{}\"", revision)).unwrap(); - }, - _ => panic!("Cannot find package definitions in lockfile") - } - }, - Err(e) => panic!(e) - } -} diff --git a/servo/components/compositing/compositor.rs b/servo/components/compositing/compositor.rs deleted file mode 100644 index b102a2a1cffc..000000000000 --- a/servo/components/compositing/compositor.rs +++ /dev/null @@ -1,1594 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -use CompositionPipeline; -use SendableFrameTree; -use compositor_thread::{CompositorProxy, CompositorReceiver}; -use compositor_thread::{InitialCompositorState, Msg}; -use euclid::{TypedPoint2D, TypedVector2D, TypedScale}; -use gfx_traits::Epoch; -use gleam::gl; -use image::{DynamicImage, ImageFormat, RgbImage}; -use ipc_channel::ipc::{self, IpcSharedMemory}; -use libc::c_void; -use msg::constellation_msg::{PipelineId, PipelineIndex, PipelineNamespaceId}; -use net_traits::image::base::{Image, PixelFormat}; -use nonzero::NonZeroU32; -use profile_traits::time::{self, ProfilerCategory, profile}; -use script_traits::{AnimationState, AnimationTickType, ConstellationMsg, LayoutControlMsg}; -use script_traits::{MouseButton, MouseEventType, ScrollState, TouchEventType, TouchId}; -use script_traits::{UntrustedNodeAddress, WindowSizeData, WindowSizeType}; -use script_traits::CompositorEvent::{MouseMoveEvent, MouseButtonEvent, TouchEvent}; -use servo_config::opts; -use servo_geometry::{DeviceIndependentPixel, DeviceUintLength}; -use std::collections::HashMap; -use std::env; -use std::fs::{File, create_dir_all}; -use std::io::Write; -use std::rc::Rc; -use std::sync::mpsc::Sender; -use std::time::{Duration, Instant}; -use style_traits::{CSSPixel, DevicePixel, PinchZoomFactor}; -use style_traits::cursor::CursorKind; -use style_traits::viewport::ViewportConstraints; -use time::{now, precise_time_ns, precise_time_s}; -use touch::{TouchHandler, TouchAction}; -use webrender; -use webrender_api::{self, DeviceIntPoint, DevicePoint, HitTestFlags, HitTestResult}; -use webrender_api::{LayoutVector2D, ScrollEventPhase, ScrollLocation}; -use windowing::{self, EmbedderCoordinates, MouseWindowEvent, WebRenderDebugOption, WindowMethods}; - -#[derive(Debug, PartialEq)] -enum UnableToComposite { - WindowUnprepared, - NotReadyToPaintImage(NotReadyToPaint), -} - -#[derive(Debug, PartialEq)] -enum NotReadyToPaint { - AnimationsActive, - JustNotifiedConstellation, - WaitingOnConstellation, -} - -// Default viewport constraints -const MAX_ZOOM: f32 = 8.0; -const MIN_ZOOM: f32 = 0.1; - -trait ConvertPipelineIdFromWebRender { - fn from_webrender(&self) -> PipelineId; -} - -impl ConvertPipelineIdFromWebRender for webrender_api::PipelineId { - fn from_webrender(&self) -> PipelineId { - PipelineId { - namespace_id: PipelineNamespaceId(self.0), - index: PipelineIndex(NonZeroU32::new(self.1).expect("Webrender pipeline zero?")), - } - } -} - -/// Holds the state when running reftests that determines when it is -/// safe to save the output image. -#[derive(Clone, Copy, Debug, PartialEq)] -enum ReadyState { - Unknown, - WaitingForConstellationReply, - ReadyToSaveImage, -} - -#[derive(Clone, Copy, Debug, Eq, PartialEq)] -struct FrameTreeId(u32); - -impl FrameTreeId { - pub fn next(&mut self) { - self.0 += 1; - } -} - -/// One pixel in layer coordinate space. -/// -/// This unit corresponds to a "pixel" in layer coordinate space, which after scaling and -/// transformation becomes a device pixel. -#[derive(Clone, Copy, Debug)] -enum LayerPixel {} - -/// NB: Never block on the constellation, because sometimes the constellation blocks on us. -pub struct IOCompositor { - /// The application window. - pub window: Rc, - - /// The port on which we receive messages. - port: CompositorReceiver, - - /// The root pipeline. - root_pipeline: Option, - - /// Tracks details about each active pipeline that the compositor knows about. - pipeline_details: HashMap, - - /// The scene scale, to allow for zooming and high-resolution painting. - scale: TypedScale, - - /// "Mobile-style" zoom that does not reflow the page. - viewport_zoom: PinchZoomFactor, - - /// Viewport zoom constraints provided by @viewport. - min_viewport_zoom: Option, - max_viewport_zoom: Option, - - /// "Desktop-style" zoom that resizes the viewport to fit the window. - page_zoom: TypedScale, - - /// The type of composition to perform - composite_target: CompositeTarget, - - /// Tracks whether we should composite this frame. - composition_request: CompositionRequest, - - /// Tracks whether we are in the process of shutting down, or have shut down and should close - /// the compositor. - pub shutdown_state: ShutdownState, - - /// Tracks the last composite time. - last_composite_time: u64, - - /// Tracks whether the zoom action has happened recently. - zoom_action: bool, - - /// The time of the last zoom action has started. - zoom_time: f64, - - /// The current frame tree ID (used to reject old paint buffers) - frame_tree_id: FrameTreeId, - - /// The channel on which messages can be sent to the constellation. - constellation_chan: Sender, - - /// The channel on which messages can be sent to the time profiler. - time_profiler_chan: time::ProfilerChan, - - /// Touch input state machine - touch_handler: TouchHandler, - - /// Pending scroll/zoom events. - pending_scroll_zoom_events: Vec, - - /// Whether we're waiting on a recomposite after dispatching a scroll. - waiting_for_results_of_scroll: bool, - - /// Used by the logic that determines when it is safe to output an - /// image for the reftest framework. - ready_to_save_state: ReadyState, - - /// Whether a scroll is in progress; i.e. whether the user's fingers are down. - scroll_in_progress: bool, - - in_scroll_transaction: Option, - - /// The webrender renderer. - webrender: webrender::Renderer, - - /// The active webrender document. - webrender_document: webrender_api::DocumentId, - - /// The webrender interface, if enabled. - webrender_api: webrender_api::RenderApi, - - /// GL functions interface (may be GL or GLES) - gl: Rc, - - /// Map of the pending paint metrics per layout thread. - /// The layout thread for each specific pipeline expects the compositor to - /// paint frames with specific given IDs (epoch). Once the compositor paints - /// these frames, it records the paint time for each of them and sends the - /// metric to the corresponding layout thread. - pending_paint_metrics: HashMap, - - /// The coordinates of the native window, its view and the screen. - embedder_coordinates: EmbedderCoordinates, -} - -#[derive(Clone, Copy)] -struct ScrollZoomEvent { - /// Change the pinch zoom level by this factor - magnification: f32, - /// Scroll by this offset, or to Start or End - scroll_location: ScrollLocation, - /// Apply changes to the frame at this location - cursor: DeviceIntPoint, - /// The scroll event phase. - phase: ScrollEventPhase, - /// The number of OS events that have been coalesced together into this one event. - event_count: u32, -} - -#[derive(Debug, PartialEq)] -enum CompositionRequest { - NoCompositingNecessary, - CompositeNow(CompositingReason), -} - -#[derive(Clone, Copy, Debug, PartialEq)] -pub enum ShutdownState { - NotShuttingDown, - ShuttingDown, - FinishedShuttingDown, -} - -struct PipelineDetails { - /// The pipeline associated with this PipelineDetails object. - pipeline: Option, - - /// Whether animations are running - animations_running: bool, - - /// Whether there are animation callbacks - animation_callbacks_running: bool, - - /// Whether this pipeline is visible - visible: bool, -} - -impl PipelineDetails { - fn new() -> PipelineDetails { - PipelineDetails { - pipeline: None, - animations_running: false, - animation_callbacks_running: false, - visible: true, - } - } -} - -#[derive(Clone, Copy, Debug, PartialEq)] -enum CompositeTarget { - /// Normal composition to a window - Window, - - /// Compose as normal, but also return a PNG of the composed output - WindowAndPng, - - /// Compose to a PNG, write it to disk, and then exit the browser (used for reftests) - PngFile -} - -struct RenderTargetInfo { - framebuffer_ids: Vec, - renderbuffer_ids: Vec, - texture_ids: Vec, -} - -impl RenderTargetInfo { - fn empty() -> RenderTargetInfo { - RenderTargetInfo { - framebuffer_ids: Vec::new(), - renderbuffer_ids: Vec::new(), - texture_ids: Vec::new(), - } - } -} - -fn initialize_png(gl: &gl::Gl, width: DeviceUintLength, height: DeviceUintLength) -> RenderTargetInfo { - let framebuffer_ids = gl.gen_framebuffers(1); - gl.bind_framebuffer(gl::FRAMEBUFFER, framebuffer_ids[0]); - - let texture_ids = gl.gen_textures(1); - gl.bind_texture(gl::TEXTURE_2D, texture_ids[0]); - - gl.tex_image_2d(gl::TEXTURE_2D, 0, gl::RGB as gl::GLint, width.get() as gl::GLsizei, - height.get() as gl::GLsizei, 0, gl::RGB, gl::UNSIGNED_BYTE, None); - gl.tex_parameter_i(gl::TEXTURE_2D, gl::TEXTURE_MAG_FILTER, gl::NEAREST as gl::GLint); - gl.tex_parameter_i(gl::TEXTURE_2D, gl::TEXTURE_MIN_FILTER, gl::NEAREST as gl::GLint); - - gl.framebuffer_texture_2d(gl::FRAMEBUFFER, gl::COLOR_ATTACHMENT0, gl::TEXTURE_2D, - texture_ids[0], 0); - - gl.bind_texture(gl::TEXTURE_2D, 0); - - let renderbuffer_ids = gl.gen_renderbuffers(1); - let depth_rb = renderbuffer_ids[0]; - gl.bind_renderbuffer(gl::RENDERBUFFER, depth_rb); - gl.renderbuffer_storage(gl::RENDERBUFFER, - gl::DEPTH_COMPONENT24, - width.get() as gl::GLsizei, - height.get() as gl::GLsizei); - gl.framebuffer_renderbuffer(gl::FRAMEBUFFER, - gl::DEPTH_ATTACHMENT, - gl::RENDERBUFFER, - depth_rb); - - RenderTargetInfo { - framebuffer_ids: framebuffer_ids, - renderbuffer_ids: renderbuffer_ids, - texture_ids: texture_ids, - } -} - -#[derive(Clone)] -pub struct RenderNotifier { - compositor_proxy: CompositorProxy, -} - -impl RenderNotifier { - pub fn new(compositor_proxy: CompositorProxy) -> RenderNotifier { - RenderNotifier { - compositor_proxy: compositor_proxy, - } - } -} - -impl webrender_api::RenderNotifier for RenderNotifier { - fn clone(&self) -> Box { - Box::new(RenderNotifier::new(self.compositor_proxy.clone())) - } - - fn wake_up(&self) { - self.compositor_proxy.recomposite(CompositingReason::NewWebRenderFrame); - } - - fn new_document_ready( - &self, - _document_id: webrender_api::DocumentId, - scrolled: bool, - composite_needed: bool, - ) { - if scrolled { - self.compositor_proxy.send(Msg::NewScrollFrameReady(composite_needed)); - } else { - self.wake_up(); - } - } -} - -impl IOCompositor { - fn new(window: Rc, state: InitialCompositorState) - -> IOCompositor { - let composite_target = match opts::get().output_file { - Some(_) => CompositeTarget::PngFile, - None => CompositeTarget::Window - }; - - IOCompositor { - gl: window.gl(), - embedder_coordinates: window.get_coordinates(), - window: window, - port: state.receiver, - root_pipeline: None, - pipeline_details: HashMap::new(), - scale: TypedScale::new(1.0), - composition_request: CompositionRequest::NoCompositingNecessary, - touch_handler: TouchHandler::new(), - pending_scroll_zoom_events: Vec::new(), - waiting_for_results_of_scroll: false, - composite_target: composite_target, - shutdown_state: ShutdownState::NotShuttingDown, - page_zoom: TypedScale::new(1.0), - viewport_zoom: PinchZoomFactor::new(1.0), - min_viewport_zoom: None, - max_viewport_zoom: None, - zoom_action: false, - zoom_time: 0f64, - frame_tree_id: FrameTreeId(0), - constellation_chan: state.constellation_chan, - time_profiler_chan: state.time_profiler_chan, - last_composite_time: 0, - ready_to_save_state: ReadyState::Unknown, - scroll_in_progress: false, - in_scroll_transaction: None, - webrender: state.webrender, - webrender_document: state.webrender_document, - webrender_api: state.webrender_api, - pending_paint_metrics: HashMap::new(), - } - } - - pub fn create(window: Rc, state: InitialCompositorState) -> IOCompositor { - let mut compositor = IOCompositor::new(window, state); - - // Set the size of the root layer. - compositor.update_zoom_transform(); - - // Tell the constellation about the initial window size. - compositor.send_window_size(WindowSizeType::Initial); - - compositor - } - - pub fn deinit(self) { - self.webrender.deinit(); - } - - pub fn maybe_start_shutting_down(&mut self) { - if self.shutdown_state == ShutdownState::NotShuttingDown { - debug!("Shutting down the constellation for WindowEvent::Quit"); - self.start_shutting_down(); - } - } - - fn start_shutting_down(&mut self) { - debug!("Compositor sending Exit message to Constellation"); - if let Err(e) = self.constellation_chan.send(ConstellationMsg::Exit) { - warn!("Sending exit message to constellation failed ({}).", e); - } - - self.shutdown_state = ShutdownState::ShuttingDown; - } - - fn finish_shutting_down(&mut self) { - debug!("Compositor received message that constellation shutdown is complete"); - - // Drain compositor port, sometimes messages contain channels that are blocking - // another thread from finishing (i.e. SetFrameTree). - while self.port.try_recv_compositor_msg().is_some() {} - - // Tell the profiler, memory profiler, and scrolling timer to shut down. - if let Ok((sender, receiver)) = ipc::channel() { - self.time_profiler_chan.send(time::ProfilerMsg::Exit(sender)); - let _ = receiver.recv(); - } - - self.shutdown_state = ShutdownState::FinishedShuttingDown; - } - - fn handle_browser_message(&mut self, msg: Msg) -> bool { - match (msg, self.shutdown_state) { - (_, ShutdownState::FinishedShuttingDown) => { - error!("compositor shouldn't be handling messages after shutting down"); - return false - } - - (Msg::Exit, _) => { - self.start_shutting_down(); - } - - (Msg::ShutdownComplete, _) => { - self.finish_shutting_down(); - return false; - } - - (Msg::ChangeRunningAnimationsState(pipeline_id, animation_state), - ShutdownState::NotShuttingDown) => { - self.change_running_animations_state(pipeline_id, animation_state); - } - - (Msg::SetFrameTree(frame_tree), - ShutdownState::NotShuttingDown) => { - self.set_frame_tree(&frame_tree); - self.send_viewport_rects(); - } - - (Msg::Recomposite(reason), ShutdownState::NotShuttingDown) => { - self.composition_request = CompositionRequest::CompositeNow(reason) - } - - - (Msg::TouchEventProcessed(result), ShutdownState::NotShuttingDown) => { - self.touch_handler.on_event_processed(result); - } - - (Msg::CreatePng(reply), ShutdownState::NotShuttingDown) => { - let res = self.composite_specific_target(CompositeTarget::WindowAndPng); - if let Err(ref e) = res { - info!("Error retrieving PNG: {:?}", e); - } - let img = res.unwrap_or(None); - if let Err(e) = reply.send(img) { - warn!("Sending reply to create png failed ({}).", e); - } - } - - (Msg::ViewportConstrained(pipeline_id, constraints), - ShutdownState::NotShuttingDown) => { - self.constrain_viewport(pipeline_id, constraints); - } - - (Msg::IsReadyToSaveImageReply(is_ready), ShutdownState::NotShuttingDown) => { - assert_eq!(self.ready_to_save_state, ReadyState::WaitingForConstellationReply); - if is_ready { - self.ready_to_save_state = ReadyState::ReadyToSaveImage; - if opts::get().is_running_problem_test { - println!("ready to save image!"); - } - } else { - self.ready_to_save_state = ReadyState::Unknown; - if opts::get().is_running_problem_test { - println!("resetting ready_to_save_state!"); - } - } - self.composite_if_necessary(CompositingReason::Headless); - } - - (Msg::PipelineVisibilityChanged(pipeline_id, visible), ShutdownState::NotShuttingDown) => { - self.pipeline_details(pipeline_id).visible = visible; - if visible { - self.process_animations(); - } - } - - (Msg::PipelineExited(pipeline_id, sender), _) => { - debug!("Compositor got pipeline exited: {:?}", pipeline_id); - self.remove_pipeline_root_layer(pipeline_id); - let _ = sender.send(()); - } - - (Msg::NewScrollFrameReady(recomposite_needed), ShutdownState::NotShuttingDown) => { - self.waiting_for_results_of_scroll = false; - if recomposite_needed { - self.composition_request = CompositionRequest::CompositeNow( - CompositingReason::NewWebRenderScrollFrame); - } - } - - (Msg::Dispatch(func), ShutdownState::NotShuttingDown) => { - // The functions sent here right now are really dumb, so they can't panic. - // But if we start running more complex code here, we should really catch panic here. - func(); - } - - (Msg::LoadComplete(_), ShutdownState::NotShuttingDown) => { - // If we're painting in headless mode, schedule a recomposite. - if opts::get().output_file.is_some() || opts::get().exit_after_load { - self.composite_if_necessary(CompositingReason::Headless); - } - }, - - (Msg::PendingPaintMetric(pipeline_id, epoch), _) => { - self.pending_paint_metrics.insert(pipeline_id, epoch); - } - - (Msg::GetClientWindow(req), ShutdownState::NotShuttingDown) => { - if let Err(e) = req.send(self.embedder_coordinates.window) { - warn!("Sending response to get client window failed ({}).", e); - } - } - - (Msg::GetScreenSize(req), ShutdownState::NotShuttingDown) => { - if let Err(e) = req.send(self.embedder_coordinates.screen) { - warn!("Sending response to get screen size failed ({}).", e); - } - } - - (Msg::GetScreenAvailSize(req), ShutdownState::NotShuttingDown) => { - if let Err(e) = req.send(self.embedder_coordinates.screen_avail) { - warn!("Sending response to get screen avail size failed ({}).", e); - } - } - - // When we are shutting_down, we need to avoid performing operations - // such as Paint that may crash because we have begun tearing down - // the rest of our resources. - (_, ShutdownState::ShuttingDown) => {} - } - - true - } - - /// Sets or unsets the animations-running flag for the given pipeline, and schedules a - /// recomposite if necessary. - fn change_running_animations_state(&mut self, - pipeline_id: PipelineId, - animation_state: AnimationState) { - match animation_state { - AnimationState::AnimationsPresent => { - let visible = self.pipeline_details(pipeline_id).visible; - self.pipeline_details(pipeline_id).animations_running = true; - if visible { - self.composite_if_necessary(CompositingReason::Animation); - } - } - AnimationState::AnimationCallbacksPresent => { - let visible = self.pipeline_details(pipeline_id).visible; - self.pipeline_details(pipeline_id).animation_callbacks_running = true; - if visible { - self.tick_animations_for_pipeline(pipeline_id); - } - } - AnimationState::NoAnimationsPresent => { - self.pipeline_details(pipeline_id).animations_running = false; - } - AnimationState::NoAnimationCallbacksPresent => { - self.pipeline_details(pipeline_id).animation_callbacks_running = false; - } - } - } - - fn pipeline_details(&mut self, pipeline_id: PipelineId) -> &mut PipelineDetails { - if !self.pipeline_details.contains_key(&pipeline_id) { - self.pipeline_details.insert(pipeline_id, PipelineDetails::new()); - } - self.pipeline_details.get_mut(&pipeline_id).expect("Insert then get failed!") - } - - pub fn pipeline(&self, pipeline_id: PipelineId) -> Option<&CompositionPipeline> { - match self.pipeline_details.get(&pipeline_id) { - Some(ref details) => details.pipeline.as_ref(), - None => { - warn!("Compositor layer has an unknown pipeline ({:?}).", pipeline_id); - None - } - } - } - - fn set_frame_tree(&mut self, frame_tree: &SendableFrameTree) { - debug!("Setting the frame tree for pipeline {}", frame_tree.pipeline.id); - - self.root_pipeline = Some(frame_tree.pipeline.clone()); - - let pipeline_id = frame_tree.pipeline.id.to_webrender(); - let mut txn = webrender_api::Transaction::new(); - txn.set_root_pipeline(pipeline_id); - txn.generate_frame(); - self.webrender_api.send_transaction(self.webrender_document, txn); - - self.create_pipeline_details_for_frame_tree(&frame_tree); - - self.send_window_size(WindowSizeType::Initial); - - self.frame_tree_id.next(); - } - - fn create_pipeline_details_for_frame_tree(&mut self, frame_tree: &SendableFrameTree) { - self.pipeline_details(frame_tree.pipeline.id).pipeline = Some(frame_tree.pipeline.clone()); - - for kid in &frame_tree.children { - self.create_pipeline_details_for_frame_tree(kid); - } - } - - fn remove_pipeline_root_layer(&mut self, pipeline_id: PipelineId) { - self.pipeline_details.remove(&pipeline_id); - } - - fn send_window_size(&self, size_type: WindowSizeType) { - let dppx = self.page_zoom * self.embedder_coordinates.hidpi_factor; - - self.webrender_api.set_window_parameters(self.webrender_document, - self.embedder_coordinates.framebuffer, - self.embedder_coordinates.viewport, - self.embedder_coordinates.hidpi_factor.get()); - - let initial_viewport = self.embedder_coordinates.viewport.size.to_f32() / dppx; - - let data = WindowSizeData { - device_pixel_ratio: dppx, - initial_viewport: initial_viewport, - }; - - let top_level_browsing_context_id = self.root_pipeline.as_ref().map(|pipeline| { - pipeline.top_level_browsing_context_id - }); - - let msg = ConstellationMsg::WindowSize(top_level_browsing_context_id, data, size_type); - - if let Err(e) = self.constellation_chan.send(msg) { - warn!("Sending window resize to constellation failed ({}).", e); - } - } - - pub fn on_resize_window_event(&mut self) { - debug!("compositor resize requested"); - - let old_coords = self.embedder_coordinates; - self.embedder_coordinates = self.window.get_coordinates(); - - // A size change could also mean a resolution change. - if self.embedder_coordinates.hidpi_factor != old_coords.hidpi_factor { - self.update_zoom_transform(); - } - - if self.embedder_coordinates.viewport == old_coords.viewport && - self.embedder_coordinates.framebuffer == old_coords.framebuffer { - return; - } - - self.send_window_size(WindowSizeType::Resize); - } - - pub fn on_mouse_window_event_class(&mut self, mouse_window_event: MouseWindowEvent) { - if opts::get().convert_mouse_to_touch { - match mouse_window_event { - MouseWindowEvent::Click(_, _) => {} - MouseWindowEvent::MouseDown(_, p) => self.on_touch_down(TouchId(0), p), - MouseWindowEvent::MouseUp(_, p) => self.on_touch_up(TouchId(0), p), - } - return - } - - self.dispatch_mouse_window_event_class(mouse_window_event); - } - - fn dispatch_mouse_window_event_class(&mut self, mouse_window_event: MouseWindowEvent) { - let point = match mouse_window_event { - MouseWindowEvent::Click(_, p) => p, - MouseWindowEvent::MouseDown(_, p) => p, - MouseWindowEvent::MouseUp(_, p) => p, - }; - - let results = self.hit_test_at_point(point); - let result = match results.items.first() { - Some(result) => result, - None => return, - }; - - let (button, event_type) = match mouse_window_event { - MouseWindowEvent::Click(button, _) => (button, MouseEventType::Click), - MouseWindowEvent::MouseDown(button, _) => (button, MouseEventType::MouseDown), - MouseWindowEvent::MouseUp(button, _) => (button, MouseEventType::MouseUp), - }; - - let event_to_send = MouseButtonEvent( - event_type, - button, - result.point_in_viewport.to_untyped(), - Some(UntrustedNodeAddress(result.tag.0 as *const c_void)), - Some(result.point_relative_to_item.to_untyped()), - ); - - let pipeline_id = PipelineId::from_webrender(result.pipeline); - let msg = ConstellationMsg::ForwardEvent(pipeline_id, event_to_send); - if let Err(e) = self.constellation_chan.send(msg) { - warn!("Sending event to constellation failed ({}).", e); - } - } - - fn hit_test_at_point(&self, point: DevicePoint) -> HitTestResult { - let dppx = self.page_zoom * self.hidpi_factor(); - let scaled_point = (point / dppx).to_untyped(); - - let world_cursor = webrender_api::WorldPoint::from_untyped(&scaled_point); - self.webrender_api.hit_test( - self.webrender_document, - None, - world_cursor, - HitTestFlags::empty() - ) - - } - - pub fn on_mouse_window_move_event_class(&mut self, cursor: DevicePoint) { - if opts::get().convert_mouse_to_touch { - self.on_touch_move(TouchId(0), cursor); - return - } - - self.dispatch_mouse_window_move_event_class(cursor); - } - - fn dispatch_mouse_window_move_event_class(&mut self, cursor: DevicePoint) { - let root_pipeline_id = match self.get_root_pipeline_id() { - Some(root_pipeline_id) => root_pipeline_id, - None => return, - }; - if self.pipeline(root_pipeline_id).is_none() { - return; - } - - let results = self.hit_test_at_point(cursor); - if let Some(item) = results.items.first() { - let node_address = Some(UntrustedNodeAddress(item.tag.0 as *const c_void)); - let event = MouseMoveEvent(Some(item.point_in_viewport.to_untyped()), node_address); - let pipeline_id = PipelineId::from_webrender(item.pipeline); - let msg = ConstellationMsg::ForwardEvent(pipeline_id, event); - if let Err(e) = self.constellation_chan.send(msg) { - warn!("Sending event to constellation failed ({}).", e); - } - - if let Some(cursor) = CursorKind::from_u8(item.tag.1 as _).ok() { - let msg = ConstellationMsg::SetCursor(cursor); - if let Err(e) = self.constellation_chan.send(msg) { - warn!("Sending event to constellation failed ({}).", e); - } - } - } - } - - fn send_touch_event( - &self, - event_type: TouchEventType, - identifier: TouchId, - point: DevicePoint) - { - let results = self.hit_test_at_point(point); - if let Some(item) = results.items.first() { - let event = TouchEvent( - event_type, - identifier, - item.point_in_viewport.to_untyped(), - Some(UntrustedNodeAddress(item.tag.0 as *const c_void)), - ); - let pipeline_id = PipelineId::from_webrender(item.pipeline); - let msg = ConstellationMsg::ForwardEvent(pipeline_id, event); - if let Err(e) = self.constellation_chan.send(msg) { - warn!("Sending event to constellation failed ({}).", e); - } - } - } - - pub fn on_touch_event(&mut self, - event_type: TouchEventType, - identifier: TouchId, - location: DevicePoint) { - match event_type { - TouchEventType::Down => self.on_touch_down(identifier, location), - TouchEventType::Move => self.on_touch_move(identifier, location), - TouchEventType::Up => self.on_touch_up(identifier, location), - TouchEventType::Cancel => self.on_touch_cancel(identifier, location), - } - } - - fn on_touch_down(&mut self, identifier: TouchId, point: DevicePoint) { - self.touch_handler.on_touch_down(identifier, point); - self.send_touch_event(TouchEventType::Down, identifier, point); - } - - fn on_touch_move(&mut self, identifier: TouchId, point: DevicePoint) { - match self.touch_handler.on_touch_move(identifier, point) { - TouchAction::Scroll(delta) => { - match point.cast() { - Some(point) => self.on_scroll_window_event( - ScrollLocation::Delta( - LayoutVector2D::from_untyped(&delta.to_untyped()) - ), - point - ), - None => error!("Point cast failed."), - } - } - TouchAction::Zoom(magnification, scroll_delta) => { - let cursor = TypedPoint2D::new(-1, -1); // Make sure this hits the base layer. - self.pending_scroll_zoom_events.push(ScrollZoomEvent { - magnification: magnification, - scroll_location: ScrollLocation::Delta(webrender_api::LayoutVector2D::from_untyped( - &scroll_delta.to_untyped())), - cursor: cursor, - phase: ScrollEventPhase::Move(true), - event_count: 1, - }); - } - TouchAction::DispatchEvent => { - self.send_touch_event(TouchEventType::Move, identifier, point); - } - _ => {} - } - } - - fn on_touch_up(&mut self, identifier: TouchId, point: DevicePoint) { - self.send_touch_event(TouchEventType::Up, identifier, point); - - if let TouchAction::Click = self.touch_handler.on_touch_up(identifier, point) { - self.simulate_mouse_click(point); - } - } - - fn on_touch_cancel(&mut self, identifier: TouchId, point: DevicePoint) { - // Send the event to script. - self.touch_handler.on_touch_cancel(identifier, point); - self.send_touch_event(TouchEventType::Cancel, identifier, point); - } - - /// - fn simulate_mouse_click(&mut self, p: DevicePoint) { - let button = MouseButton::Left; - self.dispatch_mouse_window_move_event_class(p); - self.dispatch_mouse_window_event_class(MouseWindowEvent::MouseDown(button, p)); - self.dispatch_mouse_window_event_class(MouseWindowEvent::MouseUp(button, p)); - self.dispatch_mouse_window_event_class(MouseWindowEvent::Click(button, p)); - } - - pub fn on_scroll_event(&mut self, - delta: ScrollLocation, - cursor: DeviceIntPoint, - phase: TouchEventType) { - match phase { - TouchEventType::Move => self.on_scroll_window_event(delta, cursor), - TouchEventType::Up | TouchEventType::Cancel => { - self.on_scroll_end_window_event(delta, cursor); - } - TouchEventType::Down => { - self.on_scroll_start_window_event(delta, cursor); - } - } - } - - fn on_scroll_window_event(&mut self, - scroll_location: ScrollLocation, - cursor: DeviceIntPoint) { - let event_phase = match (self.scroll_in_progress, self.in_scroll_transaction) { - (false, None) => ScrollEventPhase::Start, - (false, Some(last_scroll)) if last_scroll.elapsed() > Duration::from_millis(80) => - ScrollEventPhase::Start, - (_, _) => ScrollEventPhase::Move(self.scroll_in_progress), - }; - self.in_scroll_transaction = Some(Instant::now()); - self.pending_scroll_zoom_events.push(ScrollZoomEvent { - magnification: 1.0, - scroll_location: scroll_location, - cursor: cursor, - phase: event_phase, - event_count: 1, - }); - } - - fn on_scroll_start_window_event(&mut self, - scroll_location: ScrollLocation, - cursor: DeviceIntPoint) { - self.scroll_in_progress = true; - self.pending_scroll_zoom_events.push(ScrollZoomEvent { - magnification: 1.0, - scroll_location: scroll_location, - cursor: cursor, - phase: ScrollEventPhase::Start, - event_count: 1, - }); - } - - fn on_scroll_end_window_event(&mut self, - scroll_location: ScrollLocation, - cursor: DeviceIntPoint) { - self.scroll_in_progress = false; - self.pending_scroll_zoom_events.push(ScrollZoomEvent { - magnification: 1.0, - scroll_location: scroll_location, - cursor: cursor, - phase: ScrollEventPhase::End, - event_count: 1, - }); - } - - fn process_pending_scroll_events(&mut self) { - let had_events = self.pending_scroll_zoom_events.len() > 0; - - // Batch up all scroll events into one, or else we'll do way too much painting. - let mut last_combined_event: Option = None; - for scroll_event in self.pending_scroll_zoom_events.drain(..) { - let this_cursor = scroll_event.cursor; - - let this_delta = match scroll_event.scroll_location { - ScrollLocation::Delta(delta) => delta, - ScrollLocation::Start | ScrollLocation::End => { - // If this is an event which is scrolling to the start or end of the page, - // disregard other pending events and exit the loop. - last_combined_event = Some(scroll_event); - break; - } - }; - - if let Some(combined_event) = last_combined_event { - if combined_event.phase != scroll_event.phase { - let combined_delta = match combined_event.scroll_location { - ScrollLocation::Delta(delta) => delta, - ScrollLocation::Start | ScrollLocation::End => { - // If this is an event which is scrolling to the start or end of the page, - // disregard other pending events and exit the loop. - last_combined_event = Some(scroll_event); - break; - } - }; - // TODO: units don't match! - let delta = combined_delta / self.scale.get(); - - let cursor = - (combined_event.cursor.to_f32() / self.scale).to_untyped(); - let location = webrender_api::ScrollLocation::Delta(delta); - let cursor = webrender_api::WorldPoint::from_untyped(&cursor); - let mut txn = webrender_api::Transaction::new(); - txn.scroll(location, cursor, combined_event.phase); - self.webrender_api.send_transaction(self.webrender_document, txn); - last_combined_event = None - } - } - - match (&mut last_combined_event, scroll_event.phase) { - (last_combined_event @ &mut None, _) => { - *last_combined_event = Some(ScrollZoomEvent { - magnification: scroll_event.magnification, - scroll_location: ScrollLocation::Delta(webrender_api::LayoutVector2D::from_untyped( - &this_delta.to_untyped())), - cursor: this_cursor, - phase: scroll_event.phase, - event_count: 1, - }) - } - (&mut Some(ref mut last_combined_event), - ScrollEventPhase::Move(false)) => { - // Mac OS X sometimes delivers scroll events out of vsync during a - // fling. This causes events to get bunched up occasionally, causing - // nasty-looking "pops". To mitigate this, during a fling we average - // deltas instead of summing them. - if let ScrollLocation::Delta(delta) = last_combined_event.scroll_location { - let old_event_count = - TypedScale::new(last_combined_event.event_count as f32); - last_combined_event.event_count += 1; - let new_event_count = - TypedScale::new(last_combined_event.event_count as f32); - last_combined_event.scroll_location = ScrollLocation::Delta( - (delta * old_event_count + this_delta) / - new_event_count); - } - } - (&mut Some(ref mut last_combined_event), _) => { - if let ScrollLocation::Delta(delta) = last_combined_event.scroll_location { - last_combined_event.scroll_location = ScrollLocation::Delta(delta + this_delta); - last_combined_event.event_count += 1 - } - } - } - } - - if let Some(combined_event) = last_combined_event { - let scroll_location = match combined_event.scroll_location { - ScrollLocation::Delta(delta) => { - let scaled_delta = (TypedVector2D::from_untyped(&delta.to_untyped()) / self.scale) - .to_untyped(); - let calculated_delta = webrender_api::LayoutVector2D::from_untyped(&scaled_delta); - ScrollLocation::Delta(calculated_delta) - }, - // Leave ScrollLocation unchanged if it is Start or End location. - sl @ ScrollLocation::Start | sl @ ScrollLocation::End => sl, - }; - let cursor = (combined_event.cursor.to_f32() / self.scale).to_untyped(); - let cursor = webrender_api::WorldPoint::from_untyped(&cursor); - let mut txn = webrender_api::Transaction::new(); - txn.scroll(scroll_location, cursor, combined_event.phase); - self.webrender_api.send_transaction(self.webrender_document, txn); - self.waiting_for_results_of_scroll = true - } - - if had_events { - self.send_viewport_rects(); - } - } - - /// If there are any animations running, dispatches appropriate messages to the constellation. - fn process_animations(&mut self) { - let mut pipeline_ids = vec![]; - for (pipeline_id, pipeline_details) in &self.pipeline_details { - if (pipeline_details.animations_running || - pipeline_details.animation_callbacks_running) && - pipeline_details.visible { - pipeline_ids.push(*pipeline_id); - } - } - let animation_state = if pipeline_ids.is_empty() { - windowing::AnimationState::Idle - } else { - windowing::AnimationState::Animating - }; - self.window.set_animation_state(animation_state); - for pipeline_id in &pipeline_ids { - self.tick_animations_for_pipeline(*pipeline_id) - } - } - - fn tick_animations_for_pipeline(&mut self, pipeline_id: PipelineId) { - let animation_callbacks_running = self.pipeline_details(pipeline_id).animation_callbacks_running; - if animation_callbacks_running { - let msg = ConstellationMsg::TickAnimation(pipeline_id, AnimationTickType::Script); - if let Err(e) = self.constellation_chan.send(msg) { - warn!("Sending tick to constellation failed ({}).", e); - } - } - - // We may need to tick animations in layout. (See #12749.) - let animations_running = self.pipeline_details(pipeline_id).animations_running; - if animations_running { - let msg = ConstellationMsg::TickAnimation(pipeline_id, AnimationTickType::Layout); - if let Err(e) = self.constellation_chan.send(msg) { - warn!("Sending tick to constellation failed ({}).", e); - } - } - } - - fn constrain_viewport(&mut self, pipeline_id: PipelineId, constraints: ViewportConstraints) { - let is_root = self.root_pipeline.as_ref().map_or(false, |root_pipeline| { - root_pipeline.id == pipeline_id - }); - - if is_root { - self.viewport_zoom = constraints.initial_zoom; - self.min_viewport_zoom = constraints.min_zoom; - self.max_viewport_zoom = constraints.max_zoom; - self.update_zoom_transform(); - } - } - - fn hidpi_factor(&self) -> TypedScale { - match opts::get().device_pixels_per_px { - Some(device_pixels_per_px) => TypedScale::new(device_pixels_per_px), - None => match opts::get().output_file { - Some(_) => TypedScale::new(1.0), - None => self.embedder_coordinates.hidpi_factor, - } - } - } - - fn device_pixels_per_page_px(&self) -> TypedScale { - self.page_zoom * self.hidpi_factor() - } - - fn update_zoom_transform(&mut self) { - let scale = self.device_pixels_per_page_px(); - self.scale = TypedScale::new(scale.get()); - } - - pub fn on_zoom_reset_window_event(&mut self) { - self.page_zoom = TypedScale::new(1.0); - self.update_zoom_transform(); - self.send_window_size(WindowSizeType::Resize); - self.update_page_zoom_for_webrender(); - } - - pub fn on_zoom_window_event(&mut self, magnification: f32) { - self.page_zoom = TypedScale::new((self.page_zoom.get() * magnification) - .max(MIN_ZOOM).min(MAX_ZOOM)); - self.update_zoom_transform(); - self.send_window_size(WindowSizeType::Resize); - self.update_page_zoom_for_webrender(); - } - - fn update_page_zoom_for_webrender(&mut self) { - let page_zoom = webrender_api::ZoomFactor::new(self.page_zoom.get()); - - let mut txn = webrender_api::Transaction::new(); - txn.set_page_zoom(page_zoom); - self.webrender_api.send_transaction(self.webrender_document, txn); - } - - /// Simulate a pinch zoom - pub fn on_pinch_zoom_window_event(&mut self, magnification: f32) { - self.pending_scroll_zoom_events.push(ScrollZoomEvent { - magnification: magnification, - scroll_location: ScrollLocation::Delta(TypedVector2D::zero()), // TODO: Scroll to keep the center in view? - cursor: TypedPoint2D::new(-1, -1), // Make sure this hits the base layer. - phase: ScrollEventPhase::Move(true), - event_count: 1, - }); - } - - fn send_viewport_rects(&self) { - let mut scroll_states_per_pipeline = HashMap::new(); - for scroll_layer_state in self.webrender_api.get_scroll_node_state(self.webrender_document) { - let scroll_state = ScrollState { - scroll_id: scroll_layer_state.id, - scroll_offset: scroll_layer_state.scroll_offset.to_untyped(), - }; - - scroll_states_per_pipeline - .entry(scroll_layer_state.id.pipeline_id()) - .or_insert(vec![]) - .push(scroll_state); - } - - for (pipeline_id, scroll_states) in scroll_states_per_pipeline { - if let Some(pipeline) = self.pipeline(pipeline_id.from_webrender()) { - let msg = LayoutControlMsg::SetScrollStates(scroll_states); - let _ = pipeline.layout_chan.send(msg); - } - } - } - - // Check if any pipelines currently have active animations or animation callbacks. - fn animations_active(&self) -> bool { - for (_, details) in &self.pipeline_details { - // If animations are currently running, then don't bother checking - // with the constellation if the output image is stable. - if details.animations_running { - return true; - } - if details.animation_callbacks_running { - return true; - } - } - - false - } - - /// Query the constellation to see if the current compositor - /// output matches the current frame tree output, and if the - /// associated script threads are idle. - fn is_ready_to_paint_image_output(&mut self) -> Result<(), NotReadyToPaint> { - match self.ready_to_save_state { - ReadyState::Unknown => { - // Unsure if the output image is stable. - - // Collect the currently painted epoch of each pipeline that is - // complete (i.e. has *all* layers painted to the requested epoch). - // This gets sent to the constellation for comparison with the current - // frame tree. - let mut pipeline_epochs = HashMap::new(); - for (id, _) in &self.pipeline_details { - let webrender_pipeline_id = id.to_webrender(); - if let Some(webrender_api::Epoch(epoch)) = self.webrender - .current_epoch(webrender_pipeline_id) { - let epoch = Epoch(epoch); - pipeline_epochs.insert(*id, epoch); - } - } - - // Pass the pipeline/epoch states to the constellation and check - // if it's safe to output the image. - let msg = ConstellationMsg::IsReadyToSaveImage(pipeline_epochs); - if let Err(e) = self.constellation_chan.send(msg) { - warn!("Sending ready to save to constellation failed ({}).", e); - } - self.ready_to_save_state = ReadyState::WaitingForConstellationReply; - Err(NotReadyToPaint::JustNotifiedConstellation) - } - ReadyState::WaitingForConstellationReply => { - // If waiting on a reply from the constellation to the last - // query if the image is stable, then assume not ready yet. - Err(NotReadyToPaint::WaitingOnConstellation) - } - ReadyState::ReadyToSaveImage => { - // Constellation has replied at some point in the past - // that the current output image is stable and ready - // for saving. - // Reset the flag so that we check again in the future - // TODO: only reset this if we load a new document? - if opts::get().is_running_problem_test { - println!("was ready to save, resetting ready_to_save_state"); - } - self.ready_to_save_state = ReadyState::Unknown; - Ok(()) - } - } - } - - pub fn composite(&mut self) { - let target = self.composite_target; - match self.composite_specific_target(target) { - Ok(_) => if opts::get().output_file.is_some() || opts::get().exit_after_load { - println!("Shutting down the Constellation after generating an output file or exit flag specified"); - self.start_shutting_down(); - }, - Err(e) => if opts::get().is_running_problem_test { - if e != UnableToComposite::NotReadyToPaintImage(NotReadyToPaint::WaitingOnConstellation) { - println!("not ready to composite: {:?}", e); - } - }, - } - } - - /// Composite either to the screen or to a png image or both. - /// Returns Ok if composition was performed or Err if it was not possible to composite - /// for some reason. If CompositeTarget is Window or Png no image data is returned; - /// in the latter case the image is written directly to a file. If CompositeTarget - /// is WindowAndPng Ok(Some(png::Image)) is returned. - fn composite_specific_target(&mut self, - target: CompositeTarget) - -> Result, UnableToComposite> { - let width = self.embedder_coordinates.framebuffer.width_typed(); - let height = self.embedder_coordinates.framebuffer.height_typed(); - if !self.window.prepare_for_composite(width, height) { - return Err(UnableToComposite::WindowUnprepared) - } - - self.webrender.update(); - - let wait_for_stable_image = match target { - CompositeTarget::WindowAndPng | CompositeTarget::PngFile => true, - CompositeTarget::Window => opts::get().exit_after_load, - }; - - if wait_for_stable_image { - // The current image may be ready to output. However, if there are animations active, - // tick those instead and continue waiting for the image output to be stable AND - // all active animations to complete. - if self.animations_active() { - self.process_animations(); - return Err(UnableToComposite::NotReadyToPaintImage(NotReadyToPaint::AnimationsActive)); - } - if let Err(result) = self.is_ready_to_paint_image_output() { - return Err(UnableToComposite::NotReadyToPaintImage(result)) - } - } - - let render_target_info = match target { - CompositeTarget::Window => RenderTargetInfo::empty(), - _ => initialize_png(&*self.gl, width, height) - }; - - profile(ProfilerCategory::Compositing, None, self.time_profiler_chan.clone(), || { - debug!("compositor: compositing"); - - // Paint the scene. - // TODO(gw): Take notice of any errors the renderer returns! - self.webrender.render(self.embedder_coordinates.framebuffer).ok(); - }); - - // If there are pending paint metrics, we check if any of the painted epochs is - // one of the ones that the paint metrics recorder is expecting . In that case, - // we get the current time, inform the layout thread about it and remove the - // pending metric from the list. - if !self.pending_paint_metrics.is_empty() { - let paint_time = precise_time_ns(); - let mut to_remove = Vec::new(); - // For each pending paint metrics pipeline id - for (id, pending_epoch) in &self.pending_paint_metrics { - // we get the last painted frame id from webrender - if let Some(webrender_api::Epoch(epoch)) = self.webrender.current_epoch(id.to_webrender()) { - // and check if it is the one the layout thread is expecting, - let epoch = Epoch(epoch); - if *pending_epoch != epoch { - continue; - } - // in which case, we remove it from the list of pending metrics, - to_remove.push(id.clone()); - if let Some(pipeline) = self.pipeline(*id) { - // and inform the layout thread with the measured paint time. - let msg = LayoutControlMsg::PaintMetric(epoch, paint_time); - if let Err(e) = pipeline.layout_chan.send(msg) { - warn!("Sending PaintMetric message to layout failed ({}).", e); - } - } - } - } - for id in to_remove.iter() { - self.pending_paint_metrics.remove(id); - } - } - - let rv = match target { - CompositeTarget::Window => None, - CompositeTarget::WindowAndPng => { - let img = self.draw_img(render_target_info, - width, - height); - Some(Image { - width: img.width(), - height: img.height(), - format: PixelFormat::RGB8, - bytes: IpcSharedMemory::from_bytes(&*img), - id: None, - }) - } - CompositeTarget::PngFile => { - profile(ProfilerCategory::ImageSaving, None, self.time_profiler_chan.clone(), || { - match opts::get().output_file.as_ref() { - Some(path) => match File::create(path) { - Ok(mut file) => { - let img = self.draw_img(render_target_info, width, height); - let dynamic_image = DynamicImage::ImageRgb8(img); - if let Err(e) = dynamic_image.save(&mut file, ImageFormat::PNG) { - error!("Failed to save {} ({}).", path, e); - } - }, - Err(e) => error!("Failed to create {} ({}).", path, e), - }, - None => error!("No file specified."), - } - }); - None - } - }; - - // Perform the page flip. This will likely block for a while. - self.window.present(); - - self.last_composite_time = precise_time_ns(); - - self.composition_request = CompositionRequest::NoCompositingNecessary; - - self.process_animations(); - self.start_scrolling_bounce_if_necessary(); - self.waiting_for_results_of_scroll = false; - - Ok(rv) - } - - fn draw_img(&self, - render_target_info: RenderTargetInfo, - width: DeviceUintLength, - height: DeviceUintLength) - -> RgbImage { - let width = width.get() as usize; - let height = height.get() as usize; - // For some reason, OSMesa fails to render on the 3rd - // attempt in headless mode, under some conditions. - // I think this can only be some kind of synchronization - // bug in OSMesa, but explicitly un-binding any vertex - // array here seems to work around that bug. - // See https://github.com/servo/servo/issues/18606. - self.gl.bind_vertex_array(0); - - let mut pixels = self.gl.read_pixels(0, 0, - width as gl::GLsizei, - height as gl::GLsizei, - gl::RGB, gl::UNSIGNED_BYTE); - - self.gl.bind_framebuffer(gl::FRAMEBUFFER, 0); - - self.gl.delete_buffers(&render_target_info.texture_ids); - self.gl.delete_renderbuffers(&render_target_info.renderbuffer_ids); - self.gl.delete_framebuffers(&render_target_info.framebuffer_ids); - - // flip image vertically (texture is upside down) - let orig_pixels = pixels.clone(); - let stride = width * 3; - for y in 0..height { - let dst_start = y * stride; - let src_start = (height - y - 1) * stride; - let src_slice = &orig_pixels[src_start .. src_start + stride]; - (&mut pixels[dst_start .. dst_start + stride]).clone_from_slice(&src_slice[..stride]); - } - RgbImage::from_raw(width as u32, height as u32, pixels).expect("Flipping image failed!") - } - - fn composite_if_necessary(&mut self, reason: CompositingReason) { - if self.composition_request == CompositionRequest::NoCompositingNecessary { - if opts::get().is_running_problem_test { - println!("updating composition_request ({:?})", reason); - } - self.composition_request = CompositionRequest::CompositeNow(reason) - } else if opts::get().is_running_problem_test { - println!("composition_request is already {:?}", self.composition_request); - } - } - - fn get_root_pipeline_id(&self) -> Option { - self.root_pipeline.as_ref().map(|pipeline| pipeline.id) - } - - fn start_scrolling_bounce_if_necessary(&mut self) { - if self.scroll_in_progress { - return - } - - if self.webrender.layers_are_bouncing_back() { - let mut txn = webrender_api::Transaction::new(); - txn.tick_scrolling_bounce_animations(); - self.webrender_api.send_transaction(self.webrender_document, txn); - self.send_viewport_rects() - } - } - - pub fn receive_messages(&mut self) -> bool { - // Check for new messages coming from the other threads in the system. - let mut compositor_messages = vec![]; - let mut found_recomposite_msg = false; - while let Some(msg) = self.port.try_recv_compositor_msg() { - match msg { - Msg::Recomposite(_) if found_recomposite_msg => {} - Msg::Recomposite(_) => { - found_recomposite_msg = true; - compositor_messages.push(msg) - } - _ => compositor_messages.push(msg), - } - } - for msg in compositor_messages { - if !self.handle_browser_message(msg) { - return false - } - } - true - } - - pub fn perform_updates(&mut self) -> bool { - if self.shutdown_state == ShutdownState::FinishedShuttingDown { - return false; - } - - // If a pinch-zoom happened recently, ask for tiles at the new resolution - if self.zoom_action && precise_time_s() - self.zoom_time > 0.3 { - self.zoom_action = false; - } - - match self.composition_request { - CompositionRequest::NoCompositingNecessary => {} - CompositionRequest::CompositeNow(_) => { - self.composite() - } - } - - if !self.pending_scroll_zoom_events.is_empty() && !self.waiting_for_results_of_scroll { - self.process_pending_scroll_events() - } - self.shutdown_state != ShutdownState::FinishedShuttingDown - } - - /// Repaints and recomposites synchronously. You must be careful when calling this, as if a - /// paint is not scheduled the compositor will hang forever. - /// - /// This is used when resizing the window. - pub fn repaint_synchronously(&mut self) { - while self.shutdown_state != ShutdownState::ShuttingDown { - let msg = self.port.recv_compositor_msg(); - let need_recomposite = match msg { - Msg::Recomposite(_) => true, - _ => false, - }; - let keep_going = self.handle_browser_message(msg); - if need_recomposite { - self.composite(); - break - } - if !keep_going { - break - } - } - } - - pub fn pinch_zoom_level(&self) -> f32 { - // TODO(gw): Access via WR. - 1.0 - } - - pub fn toggle_webrender_debug(&mut self, option: WebRenderDebugOption) { - let mut flags = self.webrender.get_debug_flags(); - let flag = match option { - WebRenderDebugOption::Profiler => { - webrender::DebugFlags::PROFILER_DBG | - webrender::DebugFlags::GPU_TIME_QUERIES | - webrender::DebugFlags::GPU_SAMPLE_QUERIES - } - WebRenderDebugOption::TextureCacheDebug => { - webrender::DebugFlags::TEXTURE_CACHE_DBG - } - WebRenderDebugOption::RenderTargetDebug => { - webrender::DebugFlags::RENDER_TARGET_DBG - } - }; - flags.toggle(flag); - self.webrender.set_debug_flags(flags); - - let mut txn = webrender_api::Transaction::new(); - txn.generate_frame(); - self.webrender_api.send_transaction(self.webrender_document, txn); - } - - pub fn capture_webrender(&mut self) { - match env::current_dir() { - Ok(current_dir) => { - let capture_id = now().to_timespec().sec.to_string(); - let capture_path = current_dir.join("capture_webrender").join(capture_id); - let revision_file_path = capture_path.join("wr.txt"); - - if let Err(err) = create_dir_all(&capture_path) { - eprintln!("Unable to create path '{:?}' for capture: {:?}", capture_path, err); - return - } - - self.webrender_api.save_capture(capture_path, webrender_api::CaptureBits::all()); - - match File::create(revision_file_path) { - Ok(mut file) => { - let revision = include!(concat!(env!("OUT_DIR"), "/webrender_revision.rs")); - if let Err(err) = write!(&mut file, "{}", revision) { - eprintln!("Unable to write webrender revision: {:?}", err) - } - } - Err(err) => eprintln!("Capture triggered, creating webrender revision info skipped: {:?}", err) - } - }, - Err(err) => eprintln!("Unable to locate path to save captures: {:?}", err) - } - } -} - -/// Why we performed a composite. This is used for debugging. -#[derive(Clone, Copy, Debug, PartialEq)] -pub enum CompositingReason { - /// We hit the delayed composition timeout. (See `delayed_composition.rs`.) - DelayedCompositeTimeout, - /// The window has been scrolled and we're starting the first recomposite. - Scroll, - /// A scroll has continued and we need to recomposite again. - ContinueScroll, - /// We're performing the single composite in headless mode. - Headless, - /// We're performing a composite to run an animation. - Animation, - /// A new frame tree has been loaded. - NewFrameTree, - /// New painted buffers have been received. - NewPaintedBuffers, - /// The window has been zoomed. - Zoom, - /// A new WebRender frame has arrived. - NewWebRenderFrame, - /// WebRender has processed a scroll event and has generated a new frame. - NewWebRenderScrollFrame, -} diff --git a/servo/components/compositing/compositor_thread.rs b/servo/components/compositing/compositor_thread.rs deleted file mode 100644 index 3f43c2ba2bb1..000000000000 --- a/servo/components/compositing/compositor_thread.rs +++ /dev/null @@ -1,265 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -//! Communication with the compositor thread. - -use SendableFrameTree; -use compositor::CompositingReason; -use gfx_traits::Epoch; -use ipc_channel::ipc::IpcSender; -use msg::constellation_msg::{Key, KeyModifiers, KeyState, PipelineId, TopLevelBrowsingContextId}; -use net_traits::image::base::Image; -use profile_traits::mem; -use profile_traits::time; -use script_traits::{AnimationState, ConstellationMsg, EventResult, LoadData}; -use servo_url::ServoUrl; -use std::fmt::{Debug, Error, Formatter}; -use std::sync::mpsc::{Receiver, Sender}; -use style_traits::cursor::CursorKind; -use style_traits::viewport::ViewportConstraints; -use webrender; -use webrender_api::{self, DeviceIntPoint, DeviceUintSize}; - - -/// Used to wake up the event loop, provided by the servo port/embedder. -pub trait EventLoopWaker : 'static + Send { - fn clone(&self) -> Box; - fn wake(&self); -} - -/// Sends messages to the embedder. -pub struct EmbedderProxy { - pub sender: Sender, - pub event_loop_waker: Box, -} - -impl EmbedderProxy { - pub fn send(&self, msg: EmbedderMsg) { - // Send a message and kick the OS event loop awake. - if let Err(err) = self.sender.send(msg) { - warn!("Failed to send response ({}).", err); - } - self.event_loop_waker.wake(); - } -} - -impl Clone for EmbedderProxy { - fn clone(&self) -> EmbedderProxy { - EmbedderProxy { - sender: self.sender.clone(), - event_loop_waker: self.event_loop_waker.clone(), - } - } -} - -/// The port that the embedder receives messages on. -pub struct EmbedderReceiver { - pub receiver: Receiver -} - -impl EmbedderReceiver { - pub fn try_recv_embedder_msg(&mut self) -> Option { - self.receiver.try_recv().ok() - } - pub fn recv_embedder_msg(&mut self) -> EmbedderMsg { - self.receiver.recv().unwrap() - } -} - -/// Sends messages to the compositor. -pub struct CompositorProxy { - pub sender: Sender, - pub event_loop_waker: Box, -} - -impl CompositorProxy { - pub fn send(&self, msg: Msg) { - // Send a message and kick the OS event loop awake. - if let Err(err) = self.sender.send(msg) { - warn!("Failed to send response ({}).", err); - } - self.event_loop_waker.wake(); - } -} - -impl Clone for CompositorProxy { - fn clone(&self) -> CompositorProxy { - CompositorProxy { - sender: self.sender.clone(), - event_loop_waker: self.event_loop_waker.clone(), - } - } -} - -/// The port that the compositor receives messages on. -pub struct CompositorReceiver { - pub receiver: Receiver -} - -impl CompositorReceiver { - pub fn try_recv_compositor_msg(&mut self) -> Option { - self.receiver.try_recv().ok() - } - pub fn recv_compositor_msg(&mut self) -> Msg { - self.receiver.recv().unwrap() - } -} - -impl CompositorProxy { - pub fn recomposite(&self, reason: CompositingReason) { - self.send(Msg::Recomposite(reason)); - } -} - -pub enum EmbedderMsg { - /// A status message to be displayed by the browser chrome. - Status(TopLevelBrowsingContextId, Option), - /// Alerts the embedder that the current page has changed its title. - ChangePageTitle(TopLevelBrowsingContextId, Option), - /// Move the window to a point - MoveTo(TopLevelBrowsingContextId, DeviceIntPoint), - /// Resize the window to size - ResizeTo(TopLevelBrowsingContextId, DeviceUintSize), - /// Wether or not to follow a link - AllowNavigation(TopLevelBrowsingContextId, ServoUrl, IpcSender), - /// Sends an unconsumed key event back to the embedder. - KeyEvent(Option, Option, Key, KeyState, KeyModifiers), - /// Changes the cursor. - SetCursor(CursorKind), - /// A favicon was detected - NewFavicon(TopLevelBrowsingContextId, ServoUrl), - /// tag finished parsing - HeadParsed(TopLevelBrowsingContextId), - /// The history state has changed. - HistoryChanged(TopLevelBrowsingContextId, Vec, usize), - /// Enter or exit fullscreen - SetFullscreenState(TopLevelBrowsingContextId, bool), - /// The load of a page has begun - LoadStart(TopLevelBrowsingContextId), - /// The load of a page has completed - LoadComplete(TopLevelBrowsingContextId), - /// A pipeline panicked. First string is the reason, second one is the backtrace. - Panic(TopLevelBrowsingContextId, String, Option), - /// Servo has shut down - Shutdown, -} - -/// Messages from the painting thread and the constellation thread to the compositor thread. -pub enum Msg { - /// Requests that the compositor shut down. - Exit, - - /// Informs the compositor that the constellation has completed shutdown. - /// Required because the constellation can have pending calls to make - /// (e.g. SetFrameTree) at the time that we send it an ExitMsg. - ShutdownComplete, - - /// Alerts the compositor that the given pipeline has changed whether it is running animations. - ChangeRunningAnimationsState(PipelineId, AnimationState), - /// Replaces the current frame tree, typically called during main frame navigation. - SetFrameTree(SendableFrameTree), - /// Composite. - Recomposite(CompositingReason), - /// Script has handled a touch event, and either prevented or allowed default actions. - TouchEventProcessed(EventResult), - /// Composite to a PNG file and return the Image over a passed channel. - CreatePng(IpcSender>), - /// Alerts the compositor that the viewport has been constrained in some manner - ViewportConstrained(PipelineId, ViewportConstraints), - /// A reply to the compositor asking if the output image is stable. - IsReadyToSaveImageReply(bool), - /// Pipeline visibility changed - PipelineVisibilityChanged(PipelineId, bool), - /// WebRender has successfully processed a scroll. The boolean specifies whether a composite is - /// needed. - NewScrollFrameReady(bool), - /// A pipeline was shut down. - // This message acts as a synchronization point between the constellation, - // when it shuts down a pipeline, to the compositor; when the compositor - // sends a reply on the IpcSender, the constellation knows it's safe to - // tear down the other threads associated with this pipeline. - PipelineExited(PipelineId, IpcSender<()>), - /// Runs a closure in the compositor thread. - /// It's used to dispatch functions from webrender to the main thread's event loop. - /// Required to allow WGL GLContext sharing in Windows. - Dispatch(Box), - /// Indicates to the compositor that it needs to record the time when the frame with - /// the given ID (epoch) is painted and report it to the layout thread of the given - /// pipeline ID. - PendingPaintMetric(PipelineId, Epoch), - /// The load of a page has completed - LoadComplete(TopLevelBrowsingContextId), - - /// Get Window Informations size and position. - GetClientWindow(IpcSender<(DeviceUintSize, DeviceIntPoint)>), - /// Get screen size. - GetScreenSize(IpcSender), - /// Get screen available size. - GetScreenAvailSize(IpcSender), -} - -impl Debug for Msg { - fn fmt(&self, f: &mut Formatter) -> Result<(), Error> { - match *self { - Msg::Exit => write!(f, "Exit"), - Msg::ShutdownComplete => write!(f, "ShutdownComplete"), - Msg::ChangeRunningAnimationsState(..) => write!(f, "ChangeRunningAnimationsState"), - Msg::SetFrameTree(..) => write!(f, "SetFrameTree"), - Msg::Recomposite(..) => write!(f, "Recomposite"), - Msg::TouchEventProcessed(..) => write!(f, "TouchEventProcessed"), - Msg::CreatePng(..) => write!(f, "CreatePng"), - Msg::ViewportConstrained(..) => write!(f, "ViewportConstrained"), - Msg::IsReadyToSaveImageReply(..) => write!(f, "IsReadyToSaveImageReply"), - Msg::PipelineVisibilityChanged(..) => write!(f, "PipelineVisibilityChanged"), - Msg::PipelineExited(..) => write!(f, "PipelineExited"), - Msg::NewScrollFrameReady(..) => write!(f, "NewScrollFrameReady"), - Msg::Dispatch(..) => write!(f, "Dispatch"), - Msg::PendingPaintMetric(..) => write!(f, "PendingPaintMetric"), - Msg::LoadComplete(..) => write!(f, "LoadComplete"), - Msg::GetClientWindow(..) => write!(f, "GetClientWindow"), - Msg::GetScreenSize(..) => write!(f, "GetScreenSize"), - Msg::GetScreenAvailSize(..) => write!(f, "GetScreenAvailSize"), - } - } -} - -impl Debug for EmbedderMsg { - fn fmt(&self, f: &mut Formatter) -> Result<(), Error> { - match *self { - EmbedderMsg::Status(..) => write!(f, "Status"), - EmbedderMsg::ChangePageTitle(..) => write!(f, "ChangePageTitle"), - EmbedderMsg::MoveTo(..) => write!(f, "MoveTo"), - EmbedderMsg::ResizeTo(..) => write!(f, "ResizeTo"), - EmbedderMsg::AllowNavigation(..) => write!(f, "AllowNavigation"), - EmbedderMsg::KeyEvent(..) => write!(f, "KeyEvent"), - EmbedderMsg::SetCursor(..) => write!(f, "SetCursor"), - EmbedderMsg::NewFavicon(..) => write!(f, "NewFavicon"), - EmbedderMsg::HeadParsed(..) => write!(f, "HeadParsed"), - EmbedderMsg::HistoryChanged(..) => write!(f, "HistoryChanged"), - EmbedderMsg::SetFullscreenState(..) => write!(f, "SetFullscreenState"), - EmbedderMsg::LoadStart(..) => write!(f, "LoadStart"), - EmbedderMsg::LoadComplete(..) => write!(f, "LoadComplete"), - EmbedderMsg::Panic(..) => write!(f, "Panic"), - EmbedderMsg::Shutdown => write!(f, "Shutdown"), - } - } -} - -/// Data used to construct a compositor. -pub struct InitialCompositorState { - /// A channel to the compositor. - pub sender: CompositorProxy, - /// A port on which messages inbound to the compositor can be received. - pub receiver: CompositorReceiver, - /// A channel to the constellation. - pub constellation_chan: Sender, - /// A channel to the time profiler thread. - pub time_profiler_chan: time::ProfilerChan, - /// A channel to the memory profiler thread. - pub mem_profiler_chan: mem::ProfilerChan, - /// Instance of webrender API - pub webrender: webrender::Renderer, - pub webrender_document: webrender_api::DocumentId, - pub webrender_api: webrender_api::RenderApi, -} diff --git a/servo/components/compositing/lib.rs b/servo/components/compositing/lib.rs deleted file mode 100644 index e1a870f96950..000000000000 --- a/servo/components/compositing/lib.rs +++ /dev/null @@ -1,57 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -#![deny(unsafe_code)] - -extern crate euclid; -extern crate gfx_traits; -extern crate gleam; -extern crate image; -extern crate ipc_channel; -extern crate libc; -#[macro_use] -extern crate log; -extern crate msg; -extern crate net_traits; -extern crate nonzero; -extern crate profile_traits; -extern crate script_traits; -extern crate servo_config; -extern crate servo_geometry; -extern crate servo_url; -extern crate style_traits; -extern crate time; -extern crate webrender; -extern crate webrender_api; - -pub use compositor_thread::CompositorProxy; -pub use compositor::IOCompositor; -pub use compositor::RenderNotifier; -pub use compositor::ShutdownState; -use euclid::TypedSize2D; -use ipc_channel::ipc::IpcSender; -use msg::constellation_msg::PipelineId; -use msg::constellation_msg::TopLevelBrowsingContextId; -use script_traits::{ConstellationControlMsg, LayoutControlMsg}; -use style_traits::CSSPixel; - -mod compositor; -pub mod compositor_thread; -mod touch; -pub mod windowing; - -pub struct SendableFrameTree { - pub pipeline: CompositionPipeline, - pub size: Option>, - pub children: Vec, -} - -/// The subset of the pipeline that is needed for layer composition. -#[derive(Clone)] -pub struct CompositionPipeline { - pub id: PipelineId, - pub top_level_browsing_context_id: TopLevelBrowsingContextId, - pub script_chan: IpcSender, - pub layout_chan: IpcSender, -} diff --git a/servo/components/compositing/touch.rs b/servo/components/compositing/touch.rs deleted file mode 100644 index fd4877ead75b..000000000000 --- a/servo/components/compositing/touch.rs +++ /dev/null @@ -1,230 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -use euclid::{TypedPoint2D, TypedVector2D}; -use euclid::TypedScale; -use script_traits::{EventResult, TouchId}; -use self::TouchState::*; -use style_traits::DevicePixel; - -/// Minimum number of `DeviceIndependentPixel` to begin touch scrolling. -const TOUCH_PAN_MIN_SCREEN_PX: f32 = 20.0; - -pub struct TouchHandler { - pub state: TouchState, - pub active_touch_points: Vec, -} - -#[derive(Clone, Copy, Debug)] -pub struct TouchPoint { - pub id: TouchId, - pub point: TypedPoint2D -} - -impl TouchPoint { - pub fn new(id: TouchId, point: TypedPoint2D) -> Self { - TouchPoint { id: id, point: point } - } -} - -/// The states of the touch input state machine. -/// -/// TODO: Add support for "flinging" (scrolling inertia) -#[derive(Clone, Copy, Debug, Eq, PartialEq)] -pub enum TouchState { - /// Not tracking any touch point - Nothing, - /// A touchstart event was dispatched to the page, but the response wasn't received yet. - /// Contains the initial touch point. - WaitingForScript, - /// Script is consuming the current touch sequence; don't perform default actions. - DefaultPrevented, - /// A single touch point is active and may perform click or pan default actions. - /// Contains the initial touch location. - Touching, - /// A single touch point is active and has started panning. - Panning, - /// A two-finger pinch zoom gesture is active. - Pinching, - /// A multi-touch gesture is in progress. Contains the number of active touch points. - MultiTouch, -} - -/// The action to take in response to a touch event -#[derive(Clone, Copy, Debug)] -pub enum TouchAction { - /// Simulate a mouse click. - Click, - /// Scroll by the provided offset. - Scroll(TypedVector2D), - /// Zoom by a magnification factor and scroll by the provided offset. - Zoom(f32, TypedVector2D), - /// Send a JavaScript event to content. - DispatchEvent, - /// Don't do anything. - NoAction, -} - -impl TouchHandler { - pub fn new() -> Self { - TouchHandler { - state: Nothing, - active_touch_points: Vec::new(), - } - } - - pub fn on_touch_down(&mut self, id: TouchId, point: TypedPoint2D) { - let point = TouchPoint::new(id, point); - self.active_touch_points.push(point); - - self.state = match self.state { - Nothing => WaitingForScript, - Touching | Panning => Pinching, - WaitingForScript => WaitingForScript, - DefaultPrevented => DefaultPrevented, - Pinching | MultiTouch => MultiTouch, - }; - } - - pub fn on_touch_move(&mut self, id: TouchId, point: TypedPoint2D) - -> TouchAction { - let idx = match self.active_touch_points.iter_mut().position(|t| t.id == id) { - Some(i) => i, - None => { - warn!("Got a touchmove event for a non-active touch point"); - return TouchAction::NoAction; - } - }; - let old_point = self.active_touch_points[idx].point; - - let action = match self.state { - Touching => { - let delta = point - old_point; - - if delta.x.abs() > TOUCH_PAN_MIN_SCREEN_PX || - delta.y.abs() > TOUCH_PAN_MIN_SCREEN_PX - { - self.state = Panning; - TouchAction::Scroll(delta) - } else { - TouchAction::NoAction - } - } - Panning => { - let delta = point - old_point; - TouchAction::Scroll(delta) - } - DefaultPrevented => { - TouchAction::DispatchEvent - } - Pinching => { - let (d0, c0) = self.pinch_distance_and_center(); - self.active_touch_points[idx].point = point; - let (d1, c1) = self.pinch_distance_and_center(); - - let magnification = d1 / d0; - let scroll_delta = c1 - c0 * TypedScale::new(magnification); - - TouchAction::Zoom(magnification, scroll_delta) - } - WaitingForScript => TouchAction::NoAction, - MultiTouch => TouchAction::NoAction, - Nothing => unreachable!(), - }; - - // If we're still waiting to see whether this is a click or pan, remember the original - // location. Otherwise, update the touch point with the latest location. - if self.state != Touching && self.state != WaitingForScript { - self.active_touch_points[idx].point = point; - } - action - } - - pub fn on_touch_up(&mut self, id: TouchId, _point: TypedPoint2D) - -> TouchAction { - match self.active_touch_points.iter().position(|t| t.id == id) { - Some(i) => { - self.active_touch_points.swap_remove(i); - } - None => { - warn!("Got a touch up event for a non-active touch point"); - } - } - match self.state { - Touching => { - // FIXME: If the duration exceeds some threshold, send a contextmenu event instead. - // FIXME: Don't send a click if preventDefault is called on the touchend event. - self.state = Nothing; - TouchAction::Click - } - Nothing | Panning => { - self.state = Nothing; - TouchAction::NoAction - } - Pinching => { - self.state = Panning; - TouchAction::NoAction - } - WaitingForScript | DefaultPrevented | MultiTouch => { - if self.active_touch_points.is_empty() { - self.state = Nothing; - } - TouchAction::NoAction - } - } - } - - pub fn on_touch_cancel(&mut self, id: TouchId, _point: TypedPoint2D) { - match self.active_touch_points.iter().position(|t| t.id == id) { - Some(i) => { - self.active_touch_points.swap_remove(i); - } - None => { - warn!("Got a touchcancel event for a non-active touch point"); - return; - } - } - match self.state { - Nothing => {} - Touching | Panning => { - self.state = Nothing; - } - Pinching => { - self.state = Panning; - } - WaitingForScript | DefaultPrevented | MultiTouch => { - if self.active_touch_points.is_empty() { - self.state = Nothing; - } - } - } - } - - pub fn on_event_processed(&mut self, result: EventResult) { - if let WaitingForScript = self.state { - self.state = match result { - EventResult::DefaultPrevented => DefaultPrevented, - EventResult::DefaultAllowed => match self.touch_count() { - 1 => Touching, - 2 => Pinching, - _ => MultiTouch, - } - } - } - } - - fn touch_count(&self) -> usize { - self.active_touch_points.len() - } - - fn pinch_distance_and_center(&self) -> (f32, TypedPoint2D) { - debug_assert_eq!(self.touch_count(), 2); - let p0 = self.active_touch_points[0].point; - let p1 = self.active_touch_points[1].point; - let center = p0.lerp(p1, 0.5); - let distance = (p0 - p1).length(); - - (distance, center) - } -} diff --git a/servo/components/compositing/windowing.rs b/servo/components/compositing/windowing.rs deleted file mode 100644 index 4bfe455ab5b6..000000000000 --- a/servo/components/compositing/windowing.rs +++ /dev/null @@ -1,157 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -//! Abstract windowing methods. The concrete implementations of these can be found in `platform/`. - -use compositor_thread::EventLoopWaker; -use euclid::TypedScale; -use gleam::gl; -use ipc_channel::ipc::IpcSender; -use msg::constellation_msg::{Key, KeyModifiers, KeyState, TopLevelBrowsingContextId, TraversalDirection}; -use script_traits::{MouseButton, TouchEventType, TouchId}; -use servo_geometry::{DeviceIndependentPixel, DeviceUintLength}; -use servo_url::ServoUrl; -use std::fmt::{Debug, Error, Formatter}; -use std::rc::Rc; -use style_traits::DevicePixel; -use webrender_api::{DeviceIntPoint, DevicePoint, DeviceUintSize, DeviceUintRect, ScrollLocation}; - -#[derive(Clone)] -pub enum MouseWindowEvent { - Click(MouseButton, DevicePoint), - MouseDown(MouseButton, DevicePoint), - MouseUp(MouseButton, DevicePoint), -} - -/// Various debug and profiling flags that WebRender supports. -#[derive(Clone)] -pub enum WebRenderDebugOption { - Profiler, - TextureCacheDebug, - RenderTargetDebug, -} - -/// Events that the windowing system sends to Servo. -#[derive(Clone)] -pub enum WindowEvent { - /// Sent when no message has arrived, but the event loop was kicked for some reason (perhaps - /// by another Servo subsystem). - /// - /// FIXME(pcwalton): This is kind of ugly and may not work well with multiprocess Servo. - /// It's possible that this should be something like - /// `CompositorMessageWindowEvent(compositor_thread::Msg)` instead. - Idle, - /// Sent when part of the window is marked dirty and needs to be redrawn. Before sending this - /// message, the window must make the same GL context as in `PrepareRenderingEvent` current. - Refresh, - /// Sent when the window is resized. - Resize, - /// Sent when a new URL is to be loaded. - LoadUrl(TopLevelBrowsingContextId, ServoUrl), - /// Sent when a mouse hit test is to be performed. - MouseWindowEventClass(MouseWindowEvent), - /// Sent when a mouse move. - MouseWindowMoveEventClass(DevicePoint), - /// Touch event: type, identifier, point - Touch(TouchEventType, TouchId, DevicePoint), - /// Sent when the user scrolls. The first point is the delta and the second point is the - /// origin. - Scroll(ScrollLocation, DeviceIntPoint, TouchEventType), - /// Sent when the user zooms. - Zoom(f32), - /// Simulated "pinch zoom" gesture for non-touch platforms (e.g. ctrl-scrollwheel). - PinchZoom(f32), - /// Sent when the user resets zoom to default. - ResetZoom, - /// Sent when the user uses chrome navigation (i.e. backspace or shift-backspace). - Navigation(TopLevelBrowsingContextId, TraversalDirection), - /// Sent when the user quits the application - Quit, - /// Sent when a key input state changes - KeyEvent(Option, Key, KeyState, KeyModifiers), - /// Sent when Ctr+R/Apple+R is called to reload the current page. - Reload(TopLevelBrowsingContextId), - /// Create a new top level browsing context - NewBrowser(ServoUrl, IpcSender), - /// Close a top level browsing context - CloseBrowser(TopLevelBrowsingContextId), - /// Make a top level browsing context visible, hiding the previous - /// visible one. - SelectBrowser(TopLevelBrowsingContextId), - /// Toggles a debug flag in WebRender - ToggleWebRenderDebug(WebRenderDebugOption), - /// Capture current WebRender - CaptureWebRender, -} - -impl Debug for WindowEvent { - fn fmt(&self, f: &mut Formatter) -> Result<(), Error> { - match *self { - WindowEvent::Idle => write!(f, "Idle"), - WindowEvent::Refresh => write!(f, "Refresh"), - WindowEvent::Resize => write!(f, "Resize"), - WindowEvent::KeyEvent(..) => write!(f, "Key"), - WindowEvent::LoadUrl(..) => write!(f, "LoadUrl"), - WindowEvent::MouseWindowEventClass(..) => write!(f, "Mouse"), - WindowEvent::MouseWindowMoveEventClass(..) => write!(f, "MouseMove"), - WindowEvent::Touch(..) => write!(f, "Touch"), - WindowEvent::Scroll(..) => write!(f, "Scroll"), - WindowEvent::Zoom(..) => write!(f, "Zoom"), - WindowEvent::PinchZoom(..) => write!(f, "PinchZoom"), - WindowEvent::ResetZoom => write!(f, "ResetZoom"), - WindowEvent::Navigation(..) => write!(f, "Navigation"), - WindowEvent::Quit => write!(f, "Quit"), - WindowEvent::Reload(..) => write!(f, "Reload"), - WindowEvent::NewBrowser(..) => write!(f, "NewBrowser"), - WindowEvent::CloseBrowser(..) => write!(f, "CloseBrowser"), - WindowEvent::SelectBrowser(..) => write!(f, "SelectBrowser"), - WindowEvent::ToggleWebRenderDebug(..) => write!(f, "ToggleWebRenderDebug"), - WindowEvent::CaptureWebRender => write!(f, "CaptureWebRender"), - } - } -} - -#[derive(Clone, Copy, Debug, PartialEq)] -pub enum AnimationState { - Idle, - Animating, -} - -pub trait WindowMethods { - /// Presents the window to the screen (perhaps by page flipping). - fn present(&self); - /// Requests that the window system prepare a composite. Typically this will involve making - /// some type of platform-specific graphics context current. Returns true if the composite may - /// proceed and false if it should not. - fn prepare_for_composite(&self, width: DeviceUintLength, height: DeviceUintLength) -> bool; - /// Return the GL function pointer trait. - fn gl(&self) -> Rc; - /// Returns a thread-safe object to wake up the window's event loop. - fn create_event_loop_waker(&self) -> Box; - /// Get the coordinates of the native window, the screen and the framebuffer. - fn get_coordinates(&self) -> EmbedderCoordinates; - /// Does this window support a clipboard - fn supports_clipboard(&self) -> bool; - /// Set whether the application is currently animating. - /// Typically, when animations are active, the window - /// will want to avoid blocking on UI events, and just - /// run the event loop at the vsync interval. - fn set_animation_state(&self, _state: AnimationState); -} - -#[derive(Clone, Copy, Debug)] -pub struct EmbedderCoordinates { - /// The pixel density of the display. - pub hidpi_factor: TypedScale, - /// Size of the screen. - pub screen: DeviceUintSize, - /// Size of the available screen space (screen without toolbars and docks). - pub screen_avail: DeviceUintSize, - /// Size of the native window. - pub window: (DeviceUintSize, DeviceIntPoint), - /// Size of the GL buffer in the window. - pub framebuffer: DeviceUintSize, - /// Coordinates of the document within the framebuffer. - pub viewport: DeviceUintRect, -} diff --git a/servo/components/config/Cargo.toml b/servo/components/config/Cargo.toml deleted file mode 100644 index adcefa67156e..000000000000 --- a/servo/components/config/Cargo.toml +++ /dev/null @@ -1,33 +0,0 @@ -[package] -name = "servo_config" -version = "0.0.1" -authors = ["The Servo Project Developers"] -license = "MPL-2.0" -publish = false - -[lib] -name = "servo_config" -path = "lib.rs" -test = false -doctest = false - -[dependencies] -euclid = "0.17" -getopts = "0.2.11" -lazy_static = "1" -log = "0.4" -num_cpus = "1.1.0" -rustc-serialize = "0.3" -serde = "1.0" -servo_geometry = {path = "../geometry"} -servo_url = {path = "../url"} -url = "1.2" - -[dev-dependencies] -env_logger = "0.5" - -[target.'cfg(all(unix, not(target_os = "macos"), not(target_os = "ios"), not(target_os = "android")))'.dependencies] -xdg = "2.0" - -[target.'cfg(target_os = "android")'.dependencies] -android_injected_glue = "0.2" diff --git a/servo/components/config/basedir.rs b/servo/components/config/basedir.rs deleted file mode 100644 index 2f634448b34c..000000000000 --- a/servo/components/config/basedir.rs +++ /dev/null @@ -1,56 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -//! Contains routines for retrieving default config directories. -//! For linux based platforms, it uses the XDG base directory spec but provides -//! similar abstractions for non-linux platforms. - -#[cfg(target_os = "android")] -use android_injected_glue; -#[cfg(any(target_os = "macos", target_os = "windows"))] -use std::env; -#[cfg(target_os = "android")] -use std::ffi::CStr; -use std::path::PathBuf; -#[cfg(all(unix, not(target_os = "macos"), not(target_os = "ios"), not(target_os = "android")))] -use xdg; - -#[cfg(all(unix, not(target_os = "macos"), not(target_os = "ios"), not(target_os = "android")))] -pub fn default_config_dir() -> PathBuf { - let xdg_dirs = xdg::BaseDirectories::with_profile("servo", "default").unwrap(); - xdg_dirs.get_config_home() -} - -#[cfg(target_os = "android")] -#[allow(unsafe_code)] -pub fn default_config_dir() -> PathBuf { - let dir = unsafe { - CStr::from_ptr((*android_injected_glue::get_app().activity).externalDataPath) - }; - PathBuf::from(dir.to_str().unwrap()) -} - -#[cfg(target_os = "macos")] -pub fn default_config_dir() -> PathBuf { - let mut config_dir = env::home_dir().unwrap(); - config_dir.push("Library"); - config_dir.push("Application Support"); - config_dir.push("Servo"); - config_dir -} - -#[cfg(target_os = "windows")] -pub fn default_config_dir() -> PathBuf { - let mut config_dir = match env::var_os("APPDATA") { - Some(appdata_path) => PathBuf::from(appdata_path), - None => { - let mut dir = env::home_dir().unwrap(); - dir.push("Appdata"); - dir.push("Roaming"); - dir - } - }; - config_dir.push("Servo"); - config_dir -} diff --git a/servo/components/config/lib.rs b/servo/components/config/lib.rs deleted file mode 100644 index 55c33e25b025..000000000000 --- a/servo/components/config/lib.rs +++ /dev/null @@ -1,34 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -#![deny(unsafe_code)] - -#[cfg(target_os = "android")] -extern crate android_injected_glue; -extern crate euclid; -extern crate getopts; -#[macro_use] extern crate lazy_static; -#[macro_use] extern crate log; -extern crate num_cpus; -extern crate rustc_serialize; -#[macro_use] extern crate serde; -extern crate servo_geometry; -extern crate servo_url; -extern crate url; -#[cfg(all(unix, not(target_os = "macos"), not(target_os = "ios"), not(target_os = "android")))] -extern crate xdg; - -pub mod basedir; -#[allow(unsafe_code)] pub mod opts; -pub mod prefs; -pub mod resource_files; - -pub fn servo_version() -> String { - let cargo_version = env!("CARGO_PKG_VERSION"); - let git_info = option_env!("GIT_INFO"); - match git_info { - Some(info) => format!("Servo {}{}", cargo_version, info), - None => format!("Servo {}", cargo_version), - } -} diff --git a/servo/components/config/opts.rs b/servo/components/config/opts.rs deleted file mode 100644 index 2c1de2277280..000000000000 --- a/servo/components/config/opts.rs +++ /dev/null @@ -1,949 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -//! Configuration options for a single run of the servo application. Created -//! from command line arguments. - -use euclid::TypedSize2D; -use getopts::Options; -use num_cpus; -use prefs::{self, PrefValue, PREFS}; -use resource_files::set_resources_path; -use servo_geometry::DeviceIndependentPixel; -use servo_url::ServoUrl; -use std::borrow::Cow; -use std::cmp; -use std::default::Default; -use std::env; -use std::fs::{self, File}; -use std::io::{self, Read, Write}; -use std::path::{Path, PathBuf}; -use std::process; -use std::sync::atomic::{AtomicBool, ATOMIC_BOOL_INIT, Ordering}; -use url::{self, Url}; - - -/// Global flags for Servo, currently set on the command line. -#[derive(Clone, Deserialize, Serialize)] -pub struct Opts { - pub is_running_problem_test: bool, - - /// The initial URL to load. - pub url: Option, - - /// The maximum size of each tile in pixels (`-s`). - pub tile_size: usize, - - /// The ratio of device pixels per px at the default scale. If unspecified, will use the - /// platform default setting. - pub device_pixels_per_px: Option, - - /// `None` to disable the time profiler or `Some` to enable it with: - /// - /// - an interval in seconds to cause it to produce output on that interval. - /// (`i.e. -p 5`). - /// - a file path to write profiling info to a TSV file upon Servo's termination. - /// (`i.e. -p out.tsv`). - /// - an InfluxDB hostname to store profiling info upon Servo's termination. - /// (`i.e. -p http://localhost:8086`) - pub time_profiling: Option, - - /// When the profiler is enabled, this is an optional path to dump a self-contained HTML file - /// visualizing the traces as a timeline. - pub time_profiler_trace_path: Option, - - /// `None` to disable the memory profiler or `Some` with an interval in seconds to enable it - /// and cause it to produce output on that interval (`-m`). - pub mem_profiler_period: Option, - - pub nonincremental_layout: bool, - - /// Where to load userscripts from, if any. An empty string will load from - /// the resources/user-agent-js directory, and if the option isn't passed userscripts - /// won't be loaded - pub userscripts: Option, - - pub user_stylesheets: Vec<(Vec, ServoUrl)>, - - pub output_file: Option, - - /// Replace unpaires surrogates in DOM strings with U+FFFD. - /// See - pub replace_surrogates: bool, - - /// Log GC passes and their durations. - pub gc_profile: bool, - - /// Load web fonts synchronously to avoid non-deterministic network-driven reflows. - pub load_webfonts_synchronously: bool, - - pub headless: bool, - pub hard_fail: bool, - - /// True if we should bubble intrinsic widths sequentially (`-b`). If this is true, then - /// intrinsic widths are computed as a separate pass instead of during flow construction. You - /// may wish to turn this flag on in order to benchmark style recalculation against other - /// browser engines. - pub bubble_inline_sizes_separately: bool, - - /// True if we should show borders on all fragments for debugging purposes - /// (`--show-debug-fragment-borders`). - pub show_debug_fragment_borders: bool, - - /// True if we should paint borders around flows based on which thread painted them. - pub show_debug_parallel_layout: bool, - - /// If set with --disable-text-aa, disable antialiasing on fonts. This is primarily useful for reftests - /// where pixel perfect results are required when using fonts such as the Ahem - /// font for layout tests. - pub enable_text_antialiasing: bool, - - /// If set with --disable-subpixel, use subpixel antialiasing for glyphs. In the future - /// this will likely become the default, but for now it's opt-in while we work - /// out any bugs and improve the implementation. - pub enable_subpixel_text_antialiasing: bool, - - /// If set with --disable-canvas-aa, disable antialiasing on the HTML canvas element. - /// Like --disable-text-aa, this is useful for reftests where pixel perfect results are required. - pub enable_canvas_antialiasing: bool, - - /// True if each step of layout is traced to an external JSON file - /// for debugging purposes. Settings this implies sequential layout - /// and paint. - pub trace_layout: bool, - - /// Periodically print out on which events script threads spend their processing time. - pub profile_script_events: bool, - - /// Enable all heartbeats for profiling. - pub profile_heartbeats: bool, - - /// `None` to disable debugger or `Some` with a port number to start a server to listen to - /// remote Firefox debugger connections. - pub debugger_port: Option, - - /// `None` to disable devtools or `Some` with a port number to start a server to listen to - /// remote Firefox devtools connections. - pub devtools_port: Option, - - /// `None` to disable WebDriver or `Some` with a port number to start a server to listen to - /// remote WebDriver commands. - pub webdriver_port: Option, - - /// The initial requested size of the window. - pub initial_window_size: TypedSize2D, - - /// An optional string allowing the user agent to be set for testing. - pub user_agent: Cow<'static, str>, - - /// Whether we're running in multiprocess mode. - pub multiprocess: bool, - - /// Whether we're running inside the sandbox. - pub sandbox: bool, - - /// Probability of randomly closing a pipeline, - /// used for testing the hardening of the constellation. - pub random_pipeline_closure_probability: Option, - - /// The seed for the RNG used to randomly close pipelines, - /// used for testing the hardening of the constellation. - pub random_pipeline_closure_seed: Option, - - /// Dumps the DOM after restyle. - pub dump_style_tree: bool, - - /// Dumps the rule tree. - pub dump_rule_tree: bool, - - /// Dumps the flow tree after a layout. - pub dump_flow_tree: bool, - - /// Dumps the display list after a layout. - pub dump_display_list: bool, - - /// Dumps the display list in JSON form after a layout. - pub dump_display_list_json: bool, - - /// Emits notifications when there is a relayout. - pub relayout_event: bool, - - /// Whether Style Sharing Cache is used - pub disable_share_style_cache: bool, - - /// Whether to show in stdout style sharing cache stats after a restyle. - pub style_sharing_stats: bool, - - /// Translate mouse input into touch events. - pub convert_mouse_to_touch: bool, - - /// True to exit after the page load (`-x`). - pub exit_after_load: bool, - - /// Do not use native titlebar - pub no_native_titlebar: bool, - - /// Enable vsync in the compositor - pub enable_vsync: bool, - - /// True to show webrender profiling stats on screen. - pub webrender_stats: bool, - - /// True if webrender recording should be enabled. - pub webrender_record: bool, - - /// True if webrender is allowed to batch draw calls as instances. - pub webrender_batch: bool, - - /// True to compile all webrender shaders at init time. This is mostly - /// useful when modifying the shaders, to ensure they all compile - /// after each change is made. - pub precache_shaders: bool, - - /// True if WebRender should use multisample antialiasing. - pub use_msaa: bool, - - /// Directory for a default config directory - pub config_dir: Option, - - // don't skip any backtraces on panic - pub full_backtraces: bool, - - /// True to use OS native signposting facilities. This makes profiling events (script activity, - /// reflow, compositing, etc.) appear in Instruments.app on macOS. - pub signpost: bool, - - /// Print the version and exit. - pub is_printing_version: bool, - - /// Path to SSL certificates. - pub certificate_path: Option, - - /// Unminify Javascript. - pub unminify_js: bool, - - /// Print Progressive Web Metrics to console. - pub print_pwm: bool, -} - -fn print_usage(app: &str, opts: &Options) { - let message = format!("Usage: {} [ options ... ] [URL]\n\twhere options include", app); - println!("{}", opts.usage(&message)); -} - - -/// Debug options for Servo, currently set on the command line with -Z -#[derive(Default)] -pub struct DebugOptions { - /// List all the debug options. - pub help: bool, - - /// Bubble intrinsic widths separately like other engines. - pub bubble_widths: bool, - - /// Disable antialiasing of rendered text. - pub disable_text_aa: bool, - - /// Disable subpixel antialiasing of rendered text. - pub disable_subpixel_aa: bool, - - /// Disable antialiasing of rendered text on the HTML canvas element. - pub disable_canvas_aa: bool, - - /// Print the DOM after each restyle. - pub dump_style_tree: bool, - - /// Dumps the rule tree. - pub dump_rule_tree: bool, - - /// Print the flow tree after each layout. - pub dump_flow_tree: bool, - - /// Print the display list after each layout. - pub dump_display_list: bool, - - /// Print the display list in JSON form. - pub dump_display_list_json: bool, - - /// Print notifications when there is a relayout. - pub relayout_event: bool, - - /// Profile which events script threads spend their time on. - pub profile_script_events: bool, - - /// Enable all heartbeats for profiling. - pub profile_heartbeats: bool, - - /// Paint borders along fragment boundaries. - pub show_fragment_borders: bool, - - /// Mark which thread laid each flow out with colors. - pub show_parallel_layout: bool, - - /// Write layout trace to an external file for debugging. - pub trace_layout: bool, - - /// Disable the style sharing cache. - pub disable_share_style_cache: bool, - - /// Whether to show in stdout style sharing cache stats after a restyle. - pub style_sharing_stats: bool, - - /// Translate mouse input into touch events. - pub convert_mouse_to_touch: bool, - - /// Replace unpaires surrogates in DOM strings with U+FFFD. - /// See - pub replace_surrogates: bool, - - /// Log GC passes and their durations. - pub gc_profile: bool, - - /// Load web fonts synchronously to avoid non-deterministic network-driven reflows. - pub load_webfonts_synchronously: bool, - - /// Disable vsync in the compositor - pub disable_vsync: bool, - - /// Show webrender profiling stats on screen. - pub webrender_stats: bool, - - /// Enable webrender recording. - pub webrender_record: bool, - - /// Enable webrender instanced draw call batching. - pub webrender_disable_batch: bool, - - /// Use multisample antialiasing in WebRender. - pub use_msaa: bool, - - // don't skip any backtraces on panic - pub full_backtraces: bool, - - /// True to compile all webrender shaders at init time. This is mostly - /// useful when modifying the shaders, to ensure they all compile - /// after each change is made. - pub precache_shaders: bool, - - /// True to use OS native signposting facilities. This makes profiling events (script activity, - /// reflow, compositing, etc.) appear in Instruments.app on macOS. - pub signpost: bool, -} - - -impl DebugOptions { - pub fn extend(&mut self, debug_string: String) -> Result<(), String> { - for option in debug_string.split(',') { - match option { - "help" => self.help = true, - "bubble-widths" => self.bubble_widths = true, - "disable-text-aa" => self.disable_text_aa = true, - "disable-subpixel-aa" => self.disable_subpixel_aa = true, - "disable-canvas-aa" => self.disable_text_aa = true, - "dump-style-tree" => self.dump_style_tree = true, - "dump-rule-tree" => self.dump_rule_tree = true, - "dump-flow-tree" => self.dump_flow_tree = true, - "dump-display-list" => self.dump_display_list = true, - "dump-display-list-json" => self.dump_display_list_json = true, - "relayout-event" => self.relayout_event = true, - "profile-script-events" => self.profile_script_events = true, - "profile-heartbeats" => self.profile_heartbeats = true, - "show-fragment-borders" => self.show_fragment_borders = true, - "show-parallel-layout" => self.show_parallel_layout = true, - "trace-layout" => self.trace_layout = true, - "disable-share-style-cache" => self.disable_share_style_cache = true, - "style-sharing-stats" => self.style_sharing_stats = true, - "convert-mouse-to-touch" => self.convert_mouse_to_touch = true, - "replace-surrogates" => self.replace_surrogates = true, - "gc-profile" => self.gc_profile = true, - "load-webfonts-synchronously" => self.load_webfonts_synchronously = true, - "disable-vsync" => self.disable_vsync = true, - "wr-stats" => self.webrender_stats = true, - "wr-record" => self.webrender_record = true, - "wr-no-batch" => self.webrender_disable_batch = true, - "msaa" => self.use_msaa = true, - "full-backtraces" => self.full_backtraces = true, - "precache-shaders" => self.precache_shaders = true, - "signpost" => self.signpost = true, - "" => {}, - _ => return Err(String::from(option)), - }; - }; - Ok(()) - } -} - - -fn print_debug_usage(app: &str) -> ! { - fn print_option(name: &str, description: &str) { - println!("\t{:<35} {}", name, description); - } - - println!("Usage: {} debug option,[options,...]\n\twhere options include\n\nOptions:", app); - - print_option("bubble-widths", "Bubble intrinsic widths separately like other engines."); - print_option("disable-text-aa", "Disable antialiasing of rendered text."); - print_option("disable-canvas-aa", "Disable antialiasing on the HTML canvas element."); - print_option("dump-style-tree", "Print the DOM with computed styles after each restyle."); - print_option("dump-flow-tree", "Print the flow tree after each layout."); - print_option("dump-display-list", "Print the display list after each layout."); - print_option("dump-display-list-json", "Print the display list in JSON form."); - print_option("relayout-event", "Print notifications when there is a relayout."); - print_option("profile-script-events", "Enable profiling of script-related events."); - print_option("profile-heartbeats", "Enable heartbeats for all thread categories."); - print_option("show-fragment-borders", "Paint borders along fragment boundaries."); - print_option("show-parallel-layout", "Mark which thread laid each flow out with colors."); - print_option("trace-layout", "Write layout trace to an external file for debugging."); - print_option("disable-share-style-cache", - "Disable the style sharing cache."); - print_option("parallel-display-list-building", "Build display lists in parallel."); - print_option("convert-mouse-to-touch", "Send touch events instead of mouse events"); - print_option("replace-surrogates", "Replace unpaires surrogates in DOM strings with U+FFFD. \ - See https://github.com/servo/servo/issues/6564"); - print_option("gc-profile", "Log GC passes and their durations."); - print_option("load-webfonts-synchronously", - "Load web fonts synchronously to avoid non-deterministic network-driven reflows"); - print_option("disable-vsync", - "Disable vsync mode in the compositor to allow profiling at more than monitor refresh rate"); - print_option("wr-stats", "Show WebRender profiler on screen."); - print_option("msaa", "Use multisample antialiasing in WebRender."); - print_option("full-backtraces", "Print full backtraces for all errors"); - print_option("wr-debug", "Display webrender tile borders."); - print_option("wr-no-batch", "Disable webrender instanced batching."); - print_option("precache-shaders", "Compile all shaders during init."); - print_option("signpost", "Emit native OS signposts for profile events (currently macOS only)"); - - println!(""); - - process::exit(0) -} - -#[derive(Clone, Deserialize, Serialize)] -pub enum OutputOptions { - /// Database connection config (hostname, name, user, pass) - DB(ServoUrl, Option, Option, Option), - FileName(String), - Stdout(f64), -} - -fn args_fail(msg: &str) -> ! { - writeln!(io::stderr(), "{}", msg).unwrap(); - process::exit(1) -} - -static MULTIPROCESS: AtomicBool = ATOMIC_BOOL_INIT; - -#[inline] -pub fn multiprocess() -> bool { - MULTIPROCESS.load(Ordering::Relaxed) -} - -enum UserAgent { - Desktop, - Android, - #[allow(non_camel_case_types)] - iOS -} - -fn default_user_agent_string(agent: UserAgent) -> &'static str { - #[cfg(all(target_os = "linux", target_arch = "x86_64"))] - const DESKTOP_UA_STRING: &'static str = - "Mozilla/5.0 (X11; Linux x86_64; rv:55.0) Servo/1.0 Firefox/55.0"; - #[cfg(all(target_os = "linux", not(target_arch = "x86_64")))] - const DESKTOP_UA_STRING: &'static str = - "Mozilla/5.0 (X11; Linux i686; rv:55.0) Servo/1.0 Firefox/55.0"; - - #[cfg(all(target_os = "windows", target_arch = "x86_64"))] - const DESKTOP_UA_STRING: &'static str = - "Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:55.0) Servo/1.0 Firefox/55.0"; - #[cfg(all(target_os = "windows", not(target_arch = "x86_64")))] - const DESKTOP_UA_STRING: &'static str = - "Mozilla/5.0 (Windows NT 6.1; rv:55.0) Servo/1.0 Firefox/55.0"; - - #[cfg(not(any(target_os = "linux", target_os = "windows")))] - // Neither Linux nor Windows, so maybe OS X, and if not then OS X is an okay fallback. - const DESKTOP_UA_STRING: &'static str = - "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.10; rv:55.0) Servo/1.0 Firefox/55.0"; - - - match agent { - UserAgent::Desktop => { - DESKTOP_UA_STRING - } - UserAgent::Android => { - "Mozilla/5.0 (Android; Mobile; rv:55.0) Servo/1.0 Firefox/55.0" - } - UserAgent::iOS => { - "Mozilla/5.0 (iPhone; CPU iPhone OS 8_3 like Mac OS X; rv:55.0) Servo/1.0 Firefox/55.0" - } - } -} - -#[cfg(target_os = "android")] -const DEFAULT_USER_AGENT: UserAgent = UserAgent::Android; - -#[cfg(target_os = "ios")] -const DEFAULT_USER_AGENT: UserAgent = UserAgent::iOS; - -#[cfg(not(any(target_os = "android", target_os = "ios")))] -const DEFAULT_USER_AGENT: UserAgent = UserAgent::Desktop; - -pub fn default_opts() -> Opts { - Opts { - is_running_problem_test: false, - url: None, - tile_size: 512, - device_pixels_per_px: None, - time_profiling: None, - time_profiler_trace_path: None, - mem_profiler_period: None, - nonincremental_layout: false, - userscripts: None, - user_stylesheets: Vec::new(), - output_file: None, - replace_surrogates: false, - gc_profile: false, - load_webfonts_synchronously: false, - headless: false, - hard_fail: true, - bubble_inline_sizes_separately: false, - show_debug_fragment_borders: false, - show_debug_parallel_layout: false, - enable_text_antialiasing: true, - enable_subpixel_text_antialiasing: true, - enable_canvas_antialiasing: true, - trace_layout: false, - debugger_port: None, - devtools_port: None, - webdriver_port: None, - initial_window_size: TypedSize2D::new(1024, 740), - user_agent: default_user_agent_string(DEFAULT_USER_AGENT).into(), - multiprocess: false, - random_pipeline_closure_probability: None, - random_pipeline_closure_seed: None, - sandbox: false, - dump_style_tree: false, - dump_rule_tree: false, - dump_flow_tree: false, - dump_display_list: false, - dump_display_list_json: false, - relayout_event: false, - profile_script_events: false, - profile_heartbeats: false, - disable_share_style_cache: false, - style_sharing_stats: false, - convert_mouse_to_touch: false, - exit_after_load: false, - no_native_titlebar: false, - enable_vsync: true, - webrender_stats: false, - use_msaa: false, - config_dir: None, - full_backtraces: false, - is_printing_version: false, - webrender_record: false, - webrender_batch: true, - precache_shaders: false, - signpost: false, - certificate_path: None, - unminify_js: false, - print_pwm: false, - } -} - -pub fn from_cmdline_args(args: &[String]) -> ArgumentParsingResult { - let (app_name, args) = args.split_first().unwrap(); - - let mut opts = Options::new(); - opts.optflag("c", "cpu", "CPU painting"); - opts.optflag("g", "gpu", "GPU painting"); - opts.optopt("o", "output", "Output file", "output.png"); - opts.optopt("s", "size", "Size of tiles", "512"); - opts.optopt("", "device-pixel-ratio", "Device pixels per px", ""); - opts.optflagopt("p", "profile", "Time profiler flag and either a TSV output filename \ - OR an interval for output to Stdout (blank for Stdout with interval of 5s)", "10 \ - OR time.tsv"); - opts.optflagopt("", "profiler-trace-path", - "Path to dump a self-contained HTML timeline of profiler traces", - ""); - opts.optflagopt("m", "memory-profile", "Memory profiler flag and output interval", "10"); - opts.optflag("x", "exit", "Exit after load flag"); - opts.optopt("y", "layout-threads", "Number of threads to use for layout", "1"); - opts.optflag("i", "nonincremental-layout", "Enable to turn off incremental layout."); - opts.optflagopt("", "userscripts", - "Uses userscripts in resources/user-agent-js, or a specified full path", ""); - opts.optmulti("", "user-stylesheet", - "A user stylesheet to be added to every document", "file.css"); - opts.optflag("z", "headless", "Headless mode"); - opts.optflag("f", "hard-fail", "Exit on thread failure instead of displaying about:failure"); - opts.optflag("F", "soft-fail", "Display about:failure on thread failure instead of exiting"); - opts.optflagopt("", "remote-debugging-port", "Start remote debugger server on port", "2794"); - opts.optflagopt("", "devtools", "Start remote devtools server on port", "6000"); - opts.optflagopt("", "webdriver", "Start remote WebDriver server on port", "7000"); - opts.optopt("", "resolution", "Set window resolution.", "1024x740"); - opts.optopt("u", - "user-agent", - "Set custom user agent string (or ios / android / desktop for platform default)", - "NCSA Mosaic/1.0 (X11;SunOS 4.1.4 sun4m)"); - opts.optflag("M", "multiprocess", "Run in multiprocess mode"); - opts.optflag("S", "sandbox", "Run in a sandbox if multiprocess"); - opts.optopt("", - "random-pipeline-closure-probability", - "Probability of randomly closing a pipeline (for testing constellation hardening).", - "0.0"); - opts.optopt("", "random-pipeline-closure-seed", "A fixed seed for repeatbility of random pipeline closure.", ""); - opts.optmulti("Z", "debug", - "A comma-separated string of debug options. Pass help to show available options.", ""); - opts.optflag("h", "help", "Print this message"); - opts.optopt("", "resources-path", "Path to find static resources", "/home/servo/resources"); - opts.optopt("", "certificate-path", "Path to find SSL certificates", "/home/servo/resources/certs"); - opts.optopt("", "content-process" , "Run as a content process and connect to the given pipe", - "servo-ipc-channel.abcdefg"); - opts.optmulti("", "pref", - "A preference to set to enable", "dom.bluetooth.enabled"); - opts.optflag("b", "no-native-titlebar", "Do not use native titlebar"); - opts.optflag("w", "webrender", "Use webrender backend"); - opts.optopt("G", "graphics", "Select graphics backend (gl or es2)", "gl"); - opts.optopt("", "config-dir", - "config directory following xdg spec on linux platform", ""); - opts.optflag("v", "version", "Display servo version information"); - opts.optflag("", "unminify-js", "Unminify Javascript"); - opts.optopt("", "profiler-db-user", "Profiler database user", ""); - opts.optopt("", "profiler-db-pass", "Profiler database password", ""); - opts.optopt("", "profiler-db-name", "Profiler database name", ""); - opts.optflag("", "print-pwm", "Print Progressive Web Metrics"); - - let opt_match = match opts.parse(args) { - Ok(m) => m, - Err(f) => args_fail(&f.to_string()), - }; - - set_resources_path(opt_match.opt_str("resources-path")); - - if opt_match.opt_present("h") || opt_match.opt_present("help") { - print_usage(app_name, &opts); - process::exit(0); - }; - - // If this is the content process, we'll receive the real options over IPC. So just fill in - // some dummy options for now. - if let Some(content_process) = opt_match.opt_str("content-process") { - MULTIPROCESS.store(true, Ordering::SeqCst); - return ArgumentParsingResult::ContentProcess(content_process); - } - - let mut debug_options = DebugOptions::default(); - - for debug_string in opt_match.opt_strs("Z") { - if let Err(e) = debug_options.extend(debug_string) { - args_fail(&format!("error: unrecognized debug option: {}", e)); - } - } - - if debug_options.help { - print_debug_usage(app_name) - } - - let cwd = env::current_dir().unwrap(); - let url_opt = if !opt_match.free.is_empty() { - Some(&opt_match.free[0][..]) - } else { - None - }; - let is_running_problem_test = - url_opt - .as_ref() - .map_or(false, |url| - url.starts_with("http://web-platform.test:8000/2dcontext/drawing-images-to-the-canvas/") || - url.starts_with("http://web-platform.test:8000/_mozilla/mozilla/canvas/") || - url.starts_with("http://web-platform.test:8000/_mozilla/css/canvas_over_area.html")); - - let url_opt = url_opt.and_then(|url_string| parse_url_or_filename(&cwd, url_string) - .or_else(|error| { - warn!("URL parsing failed ({:?}).", error); - Err(error) - }).ok()); - - let tile_size: usize = match opt_match.opt_str("s") { - Some(tile_size_str) => tile_size_str.parse() - .unwrap_or_else(|err| args_fail(&format!("Error parsing option: -s ({})", err))), - None => 512, - }; - - let device_pixels_per_px = opt_match.opt_str("device-pixel-ratio").map(|dppx_str| - dppx_str.parse() - .unwrap_or_else(|err| args_fail(&format!("Error parsing option: --device-pixel-ratio ({})", err))) - ); - - // If only the flag is present, default to a 5 second period for both profilers - let time_profiling = if opt_match.opt_present("p") { - match opt_match.opt_str("p") { - Some(argument) => match argument.parse::() { - Ok(interval) => Some(OutputOptions::Stdout(interval)) , - Err(_) => { - match ServoUrl::parse(&argument) { - Ok(url) => Some(OutputOptions::DB(url, opt_match.opt_str("profiler-db-name"), - opt_match.opt_str("profiler-db-user"), - opt_match.opt_str("profiler-db-pass"))), - Err(_) => Some(OutputOptions::FileName(argument)), - } - } - }, - None => Some(OutputOptions::Stdout(5.0 as f64)), - } - } else { - // if the p option doesn't exist: - None - }; - - if let Some(ref time_profiler_trace_path) = opt_match.opt_str("profiler-trace-path") { - let mut path = PathBuf::from(time_profiler_trace_path); - path.pop(); - if let Err(why) = fs::create_dir_all(&path) { - error!("Couldn't create/open {:?}: {:?}", - Path::new(time_profiler_trace_path).to_string_lossy(), why); - } - } - - let mem_profiler_period = opt_match.opt_default("m", "5").map(|period| { - period.parse().unwrap_or_else(|err| args_fail(&format!("Error parsing option: -m ({})", err))) - }); - - let mut layout_threads: Option = opt_match.opt_str("y") - .map(|layout_threads_str| { - layout_threads_str.parse() - .unwrap_or_else(|err| args_fail(&format!("Error parsing option: -y ({})", err))) - }); - - let nonincremental_layout = opt_match.opt_present("i"); - - let random_pipeline_closure_probability = opt_match.opt_str("random-pipeline-closure-probability").map(|prob| - prob.parse().unwrap_or_else(|err| { - args_fail(&format!("Error parsing option: --random-pipeline-closure-probability ({})", err)) - }) - ); - - let random_pipeline_closure_seed = opt_match.opt_str("random-pipeline-closure-seed").map(|seed| - seed.parse().unwrap_or_else(|err| { - args_fail(&format!("Error parsing option: --random-pipeline-closure-seed ({})", err)) - }) - ); - - let mut bubble_inline_sizes_separately = debug_options.bubble_widths; - if debug_options.trace_layout { - layout_threads = Some(1); - bubble_inline_sizes_separately = true; - } - - let debugger_port = opt_match.opt_default("remote-debugging-port", "2794").map(|port| { - port.parse() - .unwrap_or_else(|err| args_fail(&format!("Error parsing option: --remote-debugging-port ({})", err))) - }); - - let devtools_port = opt_match.opt_default("devtools", "6000").map(|port| { - port.parse().unwrap_or_else(|err| args_fail(&format!("Error parsing option: --devtools ({})", err))) - }); - - let webdriver_port = opt_match.opt_default("webdriver", "7000").map(|port| { - port.parse().unwrap_or_else(|err| args_fail(&format!("Error parsing option: --webdriver ({})", err))) - }); - - let initial_window_size = match opt_match.opt_str("resolution") { - Some(res_string) => { - let res: Vec = res_string.split('x').map(|r| { - r.parse().unwrap_or_else(|err| args_fail(&format!("Error parsing option: --resolution ({})", err))) - }).collect(); - TypedSize2D::new(res[0], res[1]) - } - None => { - TypedSize2D::new(1024, 740) - } - }; - - if opt_match.opt_present("M") { - MULTIPROCESS.store(true, Ordering::SeqCst) - } - - let user_agent = match opt_match.opt_str("u") { - Some(ref ua) if ua == "ios" => default_user_agent_string(UserAgent::iOS).into(), - Some(ref ua) if ua == "android" => default_user_agent_string(UserAgent::Android).into(), - Some(ref ua) if ua == "desktop" => default_user_agent_string(UserAgent::Desktop).into(), - Some(ua) => ua.into(), - None => default_user_agent_string(DEFAULT_USER_AGENT).into(), - }; - - let user_stylesheets = opt_match.opt_strs("user-stylesheet").iter().map(|filename| { - let path = cwd.join(filename); - let url = ServoUrl::from_url(Url::from_file_path(&path).unwrap()); - let mut contents = Vec::new(); - File::open(path) - .unwrap_or_else(|err| args_fail(&format!("Couldn't open {}: {}", filename, err))) - .read_to_end(&mut contents) - .unwrap_or_else(|err| args_fail(&format!("Couldn't read {}: {}", filename, err))); - (contents, url) - }).collect(); - - let do_not_use_native_titlebar = - opt_match.opt_present("b") || - !PREFS.get("shell.native-titlebar.enabled").as_boolean().unwrap(); - - let is_printing_version = opt_match.opt_present("v") || opt_match.opt_present("version"); - - let opts = Opts { - is_running_problem_test: is_running_problem_test, - url: url_opt, - tile_size: tile_size, - device_pixels_per_px: device_pixels_per_px, - time_profiling: time_profiling, - time_profiler_trace_path: opt_match.opt_str("profiler-trace-path"), - mem_profiler_period: mem_profiler_period, - nonincremental_layout: nonincremental_layout, - userscripts: opt_match.opt_default("userscripts", ""), - user_stylesheets: user_stylesheets, - output_file: opt_match.opt_str("o"), - replace_surrogates: debug_options.replace_surrogates, - gc_profile: debug_options.gc_profile, - load_webfonts_synchronously: debug_options.load_webfonts_synchronously, - headless: opt_match.opt_present("z"), - hard_fail: opt_match.opt_present("f") && !opt_match.opt_present("F"), - bubble_inline_sizes_separately: bubble_inline_sizes_separately, - profile_script_events: debug_options.profile_script_events, - profile_heartbeats: debug_options.profile_heartbeats, - trace_layout: debug_options.trace_layout, - debugger_port: debugger_port, - devtools_port: devtools_port, - webdriver_port: webdriver_port, - initial_window_size: initial_window_size, - user_agent: user_agent, - multiprocess: opt_match.opt_present("M"), - sandbox: opt_match.opt_present("S"), - random_pipeline_closure_probability: random_pipeline_closure_probability, - random_pipeline_closure_seed: random_pipeline_closure_seed, - show_debug_fragment_borders: debug_options.show_fragment_borders, - show_debug_parallel_layout: debug_options.show_parallel_layout, - enable_text_antialiasing: !debug_options.disable_text_aa, - enable_subpixel_text_antialiasing: !debug_options.disable_subpixel_aa, - enable_canvas_antialiasing: !debug_options.disable_canvas_aa, - dump_style_tree: debug_options.dump_style_tree, - dump_rule_tree: debug_options.dump_rule_tree, - dump_flow_tree: debug_options.dump_flow_tree, - dump_display_list: debug_options.dump_display_list, - dump_display_list_json: debug_options.dump_display_list_json, - relayout_event: debug_options.relayout_event, - disable_share_style_cache: debug_options.disable_share_style_cache, - style_sharing_stats: debug_options.style_sharing_stats, - convert_mouse_to_touch: debug_options.convert_mouse_to_touch, - exit_after_load: opt_match.opt_present("x"), - no_native_titlebar: do_not_use_native_titlebar, - enable_vsync: !debug_options.disable_vsync, - webrender_stats: debug_options.webrender_stats, - use_msaa: debug_options.use_msaa, - config_dir: opt_match.opt_str("config-dir").map(Into::into), - full_backtraces: debug_options.full_backtraces, - is_printing_version: is_printing_version, - webrender_record: debug_options.webrender_record, - webrender_batch: !debug_options.webrender_disable_batch, - precache_shaders: debug_options.precache_shaders, - signpost: debug_options.signpost, - certificate_path: opt_match.opt_str("certificate-path"), - unminify_js: opt_match.opt_present("unminify-js"), - print_pwm: opt_match.opt_present("print-pwm"), - }; - - set_defaults(opts); - - // These must happen after setting the default options, since the prefs rely on - // on the resource path. - // Note that command line preferences have the highest precedence - - prefs::add_user_prefs(); - - for pref in opt_match.opt_strs("pref").iter() { - parse_pref_from_command_line(pref); - } - - if let Some(layout_threads) = layout_threads { - PREFS.set("layout.threads", PrefValue::Number(layout_threads as f64)); - } else if let Some(layout_threads) = PREFS.get("layout.threads").as_string() { - PREFS.set("layout.threads", PrefValue::Number(layout_threads.parse::().unwrap())); - } else if *PREFS.get("layout.threads") == PrefValue::Missing { - let layout_threads = cmp::max(num_cpus::get() * 3 / 4, 1); - PREFS.set("layout.threads", PrefValue::Number(layout_threads as f64)); - } - - ArgumentParsingResult::ChromeProcess -} - -pub enum ArgumentParsingResult { - ChromeProcess, - ContentProcess(String), -} - -// Make Opts available globally. This saves having to clone and pass -// opts everywhere it is used, which gets particularly cumbersome -// when passing through the DOM structures. -static mut DEFAULT_OPTIONS: *mut Opts = 0 as *mut Opts; -const INVALID_OPTIONS: *mut Opts = 0x01 as *mut Opts; - -lazy_static! { - static ref OPTIONS: Opts = { - unsafe { - let initial = if !DEFAULT_OPTIONS.is_null() { - let opts = Box::from_raw(DEFAULT_OPTIONS); - *opts - } else { - default_opts() - }; - DEFAULT_OPTIONS = INVALID_OPTIONS; - initial - } - }; -} - -pub fn set_defaults(opts: Opts) { - // Set the static to the new default value. - MULTIPROCESS.store(opts.multiprocess, Ordering::SeqCst); - - unsafe { - assert!(DEFAULT_OPTIONS.is_null()); - assert_ne!(DEFAULT_OPTIONS, INVALID_OPTIONS); - let box_opts = Box::new(opts); - DEFAULT_OPTIONS = Box::into_raw(box_opts); - } -} - -pub fn parse_pref_from_command_line(pref: &str) { - let split: Vec<&str> = pref.splitn(2, '=').collect(); - let pref_name = split[0]; - let value = split.get(1); - match value { - Some(&"false") => PREFS.set(pref_name, PrefValue::Boolean(false)), - Some(&"true") | None => PREFS.set(pref_name, PrefValue::Boolean(true)), - Some(value) => match value.parse::() { - Ok(v) => PREFS.set(pref_name, PrefValue::Number(v)), - Err(_) => PREFS.set(pref_name, PrefValue::String(value.to_string())) - } - }; -} - -#[inline] -pub fn get() -> &'static Opts { - &OPTIONS -} - -pub fn parse_url_or_filename(cwd: &Path, input: &str) -> Result { - match ServoUrl::parse(input) { - Ok(url) => Ok(url), - Err(url::ParseError::RelativeUrlWithoutBase) => { - Url::from_file_path(&*cwd.join(input)).map(ServoUrl::from_url) - } - Err(_) => Err(()), - } -} - -impl Opts { - pub fn should_use_osmesa(&self) -> bool { - self.headless - } -} diff --git a/servo/components/config/prefs.rs b/servo/components/config/prefs.rs deleted file mode 100644 index fff7880e569c..000000000000 --- a/servo/components/config/prefs.rs +++ /dev/null @@ -1,280 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -use basedir::default_config_dir; -use num_cpus; -use opts; -use resource_files::resources_dir_path; -use rustc_serialize::json::{Json, ToJson}; -use std::borrow::ToOwned; -use std::cmp::max; -use std::collections::HashMap; -use std::fs::File; -use std::io::{Read, Write, stderr}; -use std::path::PathBuf; -use std::sync::{Arc, RwLock}; - -lazy_static! { - pub static ref PREFS: Preferences = { - let defaults = default_prefs(); - if let Ok(prefs) = read_prefs() { - defaults.extend(prefs); - } - defaults - }; -} - -#[derive(Clone, Debug, Deserialize, PartialEq, Serialize)] -pub enum PrefValue { - Boolean(bool), - String(String), - Number(f64), - Missing -} - -impl PrefValue { - pub fn from_json(data: Json) -> Result { - let value = match data { - Json::Boolean(x) => PrefValue::Boolean(x), - Json::String(x) => PrefValue::String(x), - Json::F64(x) => PrefValue::Number(x), - Json::I64(x) => PrefValue::Number(x as f64), - Json::U64(x) => PrefValue::Number(x as f64), - _ => return Err(()) - }; - Ok(value) - } - - pub fn as_boolean(&self) -> Option { - match *self { - PrefValue::Boolean(value) => { - Some(value) - }, - _ => None - } - } - - pub fn as_string(&self) -> Option<&str> { - match *self { - PrefValue::String(ref value) => { - Some(&value) - }, - _ => None - } - } - - pub fn as_i64(&self) -> Option { - match *self { - PrefValue::Number(x) => Some(x as i64), - _ => None, - } - } - - pub fn as_u64(&self) -> Option { - match *self { - PrefValue::Number(x) => Some(x as u64), - _ => None, - } - } -} - -impl ToJson for PrefValue { - fn to_json(&self) -> Json { - match *self { - PrefValue::Boolean(x) => { - Json::Boolean(x) - }, - PrefValue::String(ref x) => { - Json::String(x.clone()) - }, - PrefValue::Number(x) => { - Json::F64(x) - }, - PrefValue::Missing => Json::Null - } - } -} - -#[derive(Clone, Debug, Deserialize, Serialize)] -pub enum Pref { - NoDefault(Arc), - WithDefault(Arc, Option>) -} - - -impl Pref { - pub fn new(value: PrefValue) -> Pref { - Pref::NoDefault(Arc::new(value)) - } - - fn new_default(value: PrefValue) -> Pref { - Pref::WithDefault(Arc::new(value), None) - } - - fn from_json(data: Json) -> Result { - let value = PrefValue::from_json(data)?; - Ok(Pref::new_default(value)) - } - - pub fn value(&self) -> &Arc { - match *self { - Pref::NoDefault(ref x) => x, - Pref::WithDefault(ref default, ref override_value) => { - match *override_value { - Some(ref x) => x, - None => default - } - } - } - } - - fn set(&mut self, value: PrefValue) { - // TODO - this should error if we try to override a pref of one type - // with a value of a different type - match *self { - Pref::NoDefault(ref mut pref_value) => { - *pref_value = Arc::new(value) - }, - Pref::WithDefault(_, ref mut override_value) => { - *override_value = Some(Arc::new(value)) - } - } - } -} - -impl ToJson for Pref { - fn to_json(&self) -> Json { - self.value().to_json() - } -} - -pub fn default_prefs() -> Preferences { - let prefs = Preferences(Arc::new(RwLock::new(HashMap::new()))); - prefs.set("layout.threads", PrefValue::Number( - max(num_cpus::get() * 3 / 4, 1) as f64)); - prefs -} - -pub fn read_prefs_from_file(mut file: T) - -> Result, ()> where T: Read { - let json = Json::from_reader(&mut file).or_else(|e| { - println!("Ignoring invalid JSON in preferences: {:?}.", e); - Err(()) - })?; - - let mut prefs = HashMap::new(); - if let Json::Object(obj) = json { - for (name, value) in obj.into_iter() { - match Pref::from_json(value) { - Ok(x) => { - prefs.insert(name, x); - }, - Err(_) => println!("Ignoring non-boolean/string/i64 preference value for {:?}", name), - } - } - } - Ok(prefs) -} - -pub fn add_user_prefs() { - match opts::get().config_dir { - Some(ref config_path) => { - let mut path = PathBuf::from(config_path); - init_user_prefs(&mut path); - } - None => { - let mut path = default_config_dir(); - if path.join("prefs.json").exists() { - init_user_prefs(&mut path); - } - } - } -} - -fn init_user_prefs(path: &mut PathBuf) { - path.push("prefs.json"); - if let Ok(file) = File::open(path) { - if let Ok(prefs) = read_prefs_from_file(file) { - PREFS.extend(prefs); - } - } else { - writeln!(&mut stderr(), "Error opening prefs.json from config directory") - .expect("failed printing to stderr"); - } -} - -fn read_prefs() -> Result, ()> { - let mut path = resources_dir_path().map_err(|_| ())?; - path.push("prefs.json"); - - let file = File::open(path).or_else(|e| { - writeln!(&mut stderr(), "Error opening preferences: {:?}.", e) - .expect("failed printing to stderr"); - Err(()) - })?; - - read_prefs_from_file(file) -} - -pub struct Preferences(Arc>>); - -impl Preferences { - pub fn get(&self, name: &str) -> Arc { - self.0.read().unwrap().get(name).map_or(Arc::new(PrefValue::Missing), |x| x.value().clone()) - } - - pub fn cloned(&self) -> HashMap { - self.0.read().unwrap().clone() - } - - pub fn set(&self, name: &str, value: PrefValue) { - let mut prefs = self.0.write().unwrap(); - if let Some(pref) = prefs.get_mut(name) { - pref.set(value); - return; - } - prefs.insert(name.to_owned(), Pref::new(value)); - } - - pub fn reset(&self, name: &str) -> Arc { - let mut prefs = self.0.write().unwrap(); - let result = match prefs.get_mut(name) { - None => return Arc::new(PrefValue::Missing), - Some(&mut Pref::NoDefault(_)) => Arc::new(PrefValue::Missing), - Some(&mut Pref::WithDefault(ref default, ref mut set_value)) => { - *set_value = None; - default.clone() - }, - }; - if *result == PrefValue::Missing { - prefs.remove(name); - } - result - } - - pub fn reset_all(&self) { - let names = { - self.0.read().unwrap().keys().cloned().collect::>() - }; - for name in names.iter() { - self.reset(name); - } - } - - pub fn extend(&self, extension: HashMap) { - self.0.write().unwrap().extend(extension); - } - - pub fn is_webvr_enabled(&self) -> bool { - self.get("dom.webvr.enabled").as_boolean().unwrap_or(false) - } - - pub fn is_dom_to_texture_enabled(&self) -> bool { - self.get("dom.webgl.dom_to_texture.enabled").as_boolean().unwrap_or(false) - } - - pub fn is_webgl2_enabled(&self) -> bool { - self.get("dom.webgl2.enabled").as_boolean().unwrap_or(false) - } -} diff --git a/servo/components/config/resource_files.rs b/servo/components/config/resource_files.rs deleted file mode 100644 index e8fc58328b04..000000000000 --- a/servo/components/config/resource_files.rs +++ /dev/null @@ -1,83 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -#[cfg(target_os = "android")] -use android_injected_glue; -#[cfg(not(target_os = "android"))] -use std::env; -#[cfg(target_os = "android")] -use std::ffi::CStr; -use std::fs::File; -use std::io::{self, Read}; -use std::path::{Path, PathBuf}; -use std::sync::{Arc, Mutex}; - -lazy_static! { - static ref CMD_RESOURCE_DIR: Arc>> = { - Arc::new(Mutex::new(None)) - }; -} - -pub fn set_resources_path(path: Option) { - let mut dir = CMD_RESOURCE_DIR.lock().unwrap(); - *dir = path; -} - -#[cfg(target_os = "android")] -#[allow(unsafe_code)] -pub fn resources_dir_path() -> io::Result { - let mut dir = CMD_RESOURCE_DIR.lock().unwrap(); - - if let Some(ref path) = *dir { - return Ok(PathBuf::from(path)); - } - - let data_path = unsafe { - CStr::from_ptr((*android_injected_glue::get_app().activity).externalDataPath) - }; - let path = PathBuf::from(data_path.to_str().unwrap()); - *dir = Some(path.to_str().unwrap().to_owned()); - Ok(path) -} - -#[cfg(not(target_os = "android"))] -pub fn resources_dir_path() -> io::Result { - let mut dir = CMD_RESOURCE_DIR.lock().unwrap(); - - if let Some(ref path) = *dir { - return Ok(PathBuf::from(path)); - } - - // FIXME: Find a way to not rely on the executable being - // under `[/$target_triple]/target/debug` - // or `[/$target_triple]/target/release`. - let mut path = env::current_exe()?; - // Follow symlink - path = path.canonicalize()?; - - while path.pop() { - path.push("resources"); - if path.is_dir() { - break; - } - path.pop(); - // Check for Resources on mac when using a case sensitive filesystem. - path.push("Resources"); - if path.is_dir() { - break; - } - path.pop(); - } - *dir = Some(path.to_str().unwrap().to_owned()); - Ok(path) -} - -pub fn read_resource_file>(relative_path: P) -> io::Result> { - let mut path = resources_dir_path()?; - path.push(relative_path); - let mut file = File::open(&path)?; - let mut data = Vec::new(); - file.read_to_end(&mut data)?; - Ok(data) -} diff --git a/servo/components/config/tests/opts.rs b/servo/components/config/tests/opts.rs deleted file mode 100644 index 53a049e103cc..000000000000 --- a/servo/components/config/tests/opts.rs +++ /dev/null @@ -1,95 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -extern crate servo_config; - -use servo_config::opts::{parse_url_or_filename, parse_pref_from_command_line}; -use servo_config::prefs::{PrefValue, PREFS}; -use std::path::Path; - -#[cfg(not(target_os = "windows"))] -const FAKE_CWD: &'static str = "/fake/cwd"; - -#[cfg(target_os = "windows")] -const FAKE_CWD: &'static str = "C:/fake/cwd"; - -#[test] -fn test_argument_parsing() { - let fake_cwd = Path::new(FAKE_CWD); - assert!(parse_url_or_filename(fake_cwd, "http://example.net:invalid").is_err()); - - let url = parse_url_or_filename(fake_cwd, "http://example.net").unwrap(); - assert_eq!(url.scheme(), "http"); - - let url = parse_url_or_filename(fake_cwd, "file:///foo/bar.html").unwrap(); - assert_eq!(url.scheme(), "file"); - assert_eq!(url.path_segments().unwrap().collect::>(), ["foo", "bar.html"]); -} - -#[test] -#[cfg(not(target_os = "windows"))] -fn test_file_path_parsing() { - let fake_cwd = Path::new(FAKE_CWD); - - let url = parse_url_or_filename(fake_cwd, "bar.html").unwrap(); - assert_eq!(url.scheme(), "file"); - assert_eq!(url.path_segments().unwrap().collect::>(), ["fake", "cwd", "bar.html"]); -} - -#[test] -#[cfg(target_os = "windows")] -fn test_file_path_parsing() { - let fake_cwd = Path::new(FAKE_CWD); - - let url = parse_url_or_filename(fake_cwd, "bar.html").unwrap(); - assert_eq!(url.scheme(), "file"); - assert_eq!(url.path_segments().unwrap().collect::>(), ["C:", "fake", "cwd", "bar.html"]); -} - -#[test] -#[cfg(not(target_os = "windows"))] -// Windows file paths can't contain ? -fn test_argument_parsing_special() { - let fake_cwd = Path::new(FAKE_CWD); - - // '?' and '#' have a special meaning in URLs... - let url = parse_url_or_filename(fake_cwd, "file:///foo/bar?baz#buzz.html").unwrap(); - assert_eq!(&*url.to_file_path().unwrap(), Path::new("/foo/bar")); - assert_eq!(url.scheme(), "file"); - assert_eq!(url.path_segments().unwrap().collect::>(), ["foo", "bar"]); - assert_eq!(url.query(), Some("baz")); - assert_eq!(url.fragment(), Some("buzz.html")); - - // but not in file names. - let url = parse_url_or_filename(fake_cwd, "./bar?baz#buzz.html").unwrap(); - assert_eq!(&*url.to_file_path().unwrap(), Path::new("/fake/cwd/bar?baz#buzz.html")); - assert_eq!(url.scheme(), "file"); - assert_eq!(url.path_segments().unwrap().collect::>(), - ["fake", "cwd", "bar%3Fbaz%23buzz.html"]); - assert_eq!(url.query(), None); - assert_eq!(url.fragment(), None); -} - -#[test] -fn test_parse_pref_from_command_line() { - // Test with boolean values. - parse_pref_from_command_line("testtrue=true"); - assert_eq!(*PREFS.get("testtrue"), PrefValue::Boolean(true)); - parse_pref_from_command_line("testfalse=false"); - assert_eq!(*PREFS.get("testfalse"), PrefValue::Boolean(false)); - - // Test with numbers. - parse_pref_from_command_line("testint=42"); - assert_eq!(*PREFS.get("testint"), PrefValue::Number(42 as f64)); - parse_pref_from_command_line("testfloat=4.2"); - assert_eq!(*PREFS.get("testfloat"), PrefValue::Number(4.2)); - - // Test default (string). - parse_pref_from_command_line("teststr=str"); - assert_eq!(*PREFS.get("teststr"), PrefValue::String("str".to_owned())); - - // Test with no value. - parse_pref_from_command_line("testempty"); - assert_eq!(*PREFS.get("testempty"), PrefValue::Boolean(true)); -} diff --git a/servo/components/config/tests/prefs.rs b/servo/components/config/tests/prefs.rs deleted file mode 100644 index 605b0f2f49be..000000000000 --- a/servo/components/config/tests/prefs.rs +++ /dev/null @@ -1,77 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -extern crate servo_config; - -use servo_config::basedir; -use servo_config::prefs::{PREFS, PrefValue, read_prefs_from_file}; -use std::fs::{self, File}; -use std::io::{Read, Write}; - -#[test] -fn test_create_pref() { - let json_str = "{\ - \"layout.writing-mode.enabled\": true,\ - \"network.mime.sniff\": false,\ - \"shell.homepage\": \"https://servo.org\"\ -}"; - - let prefs = read_prefs_from_file(json_str.as_bytes()); - assert!(prefs.is_ok()); - let prefs = prefs.unwrap(); - - assert_eq!(prefs.len(), 3); -} - -#[test] -fn test_get_set_reset_extend() { - let json_str = "{\ - \"layout.writing-mode.enabled\": true,\ - \"extra.stuff\": false,\ - \"shell.homepage\": \"https://google.com\"\ -}"; - - assert_eq!(*PREFS.get("test"), PrefValue::Missing); - PREFS.set("test", PrefValue::String("hi".to_owned())); - assert_eq!(*PREFS.get("test"), PrefValue::String("hi".to_owned())); - assert_eq!(*PREFS.get("shell.homepage"), PrefValue::String("https://servo.org".to_owned())); - PREFS.set("shell.homepage", PrefValue::Boolean(true)); - assert_eq!(*PREFS.get("shell.homepage"), PrefValue::Boolean(true)); - PREFS.reset("shell.homepage"); - assert_eq!(*PREFS.get("shell.homepage"), PrefValue::String("https://servo.org".to_owned())); - - let extension = read_prefs_from_file(json_str.as_bytes()).unwrap(); - PREFS.extend(extension); - assert_eq!(*PREFS.get("shell.homepage"), PrefValue::String("https://google.com".to_owned())); - assert_eq!(*PREFS.get("layout.writing-mode.enabled"), PrefValue::Boolean(true)); - assert_eq!(*PREFS.get("extra.stuff"), PrefValue::Boolean(false)); -} - -#[test] -fn test_default_config_dir_create_read_write() { - let json_str = "{\ - \"layout.writing-mode.enabled\": true,\ - \"extra.stuff\": false,\ - \"shell.homepage\": \"https://google.com\"\ -}"; - let mut expected_json = String::new(); - let config_path = basedir::default_config_dir(); - - if !config_path.exists() { - fs::create_dir_all(&config_path).unwrap(); - } - - let json_path = config_path.join("test_config.json"); - - let mut fd = File::create(&json_path).unwrap(); - assert_eq!(json_path.exists(), true); - - fd.write_all(json_str.as_bytes()).unwrap(); - let mut fd = File::open(&json_path).unwrap(); - fd.read_to_string(&mut expected_json).unwrap(); - - assert_eq!(json_str, expected_json); - - fs::remove_file(&json_path).unwrap(); -} diff --git a/servo/components/constellation/Cargo.toml b/servo/components/constellation/Cargo.toml deleted file mode 100644 index ee8067086a39..000000000000 --- a/servo/components/constellation/Cargo.toml +++ /dev/null @@ -1,44 +0,0 @@ -[package] -name = "constellation" -version = "0.0.1" -authors = ["The Servo Project Developers"] -license = "MPL-2.0" -publish = false - -[lib] -name = "constellation" -path = "lib.rs" - -[dependencies] -backtrace = "0.3" -bluetooth_traits = { path = "../bluetooth_traits" } -canvas = {path = "../canvas"} -clipboard = "0.4" -canvas_traits = {path = "../canvas_traits"} -compositing = {path = "../compositing"} -debugger = {path = "../debugger"} -devtools_traits = {path = "../devtools_traits"} -euclid = "0.17" -gfx = {path = "../gfx"} -gfx_traits = {path = "../gfx_traits"} -hyper = "0.10" -ipc-channel = "0.10" -layout_traits = {path = "../layout_traits"} -log = "0.4" -metrics = {path = "../metrics"} -msg = {path = "../msg"} -net = {path = "../net"} -net_traits = {path = "../net_traits"} -profile_traits = {path = "../profile_traits"} -script_traits = {path = "../script_traits"} -serde = "1.0" -style_traits = {path = "../style_traits"} -servo_config = {path = "../config"} -servo_rand = {path = "../rand"} -servo_remutex = {path = "../remutex"} -servo_url = {path = "../url"} -webvr_traits = {path = "../webvr_traits"} -webrender_api = {git = "https://github.com/servo/webrender", features = ["ipc"]} - -[target.'cfg(all(not(target_os = "windows"), not(target_os = "ios")))'.dependencies] -gaol = {git = "https://github.com/servo/gaol"} diff --git a/servo/components/constellation/browsingcontext.rs b/servo/components/constellation/browsingcontext.rs deleted file mode 100644 index 4926bbcf7dd5..000000000000 --- a/servo/components/constellation/browsingcontext.rs +++ /dev/null @@ -1,140 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -use euclid::TypedSize2D; -use msg::constellation_msg::{BrowsingContextId, PipelineId, TopLevelBrowsingContextId}; -use pipeline::Pipeline; -use std::collections::{HashMap, HashSet}; -use style_traits::CSSPixel; - -/// The constellation's view of a browsing context. -/// Each browsing context has a session history, caused by -/// navigation and traversing the history. Each browsing context has its -/// current entry, plus past and future entries. The past is sorted -/// chronologically, the future is sorted reverse chronologically: -/// in particular prev.pop() is the latest past entry, and -/// next.pop() is the earliest future entry. -pub struct BrowsingContext { - /// The browsing context id. - pub id: BrowsingContextId, - - /// The top-level browsing context ancestor - pub top_level_id: TopLevelBrowsingContextId, - - /// The size of the frame. - pub size: Option>, - - /// The pipeline for the current session history entry. - pub pipeline_id: PipelineId, - - pub pipelines: HashSet, -} - -impl BrowsingContext { - /// Create a new browsing context. - /// Note this just creates the browsing context, it doesn't add it to the constellation's set of browsing contexts. - pub fn new(id: BrowsingContextId, - top_level_id: TopLevelBrowsingContextId, - pipeline_id: PipelineId) - -> BrowsingContext - { - let mut pipelines = HashSet::new(); - pipelines.insert(pipeline_id); - BrowsingContext { - id: id, - top_level_id: top_level_id, - size: None, - pipeline_id: pipeline_id, - pipelines, - } - } - - pub fn update_current_entry(&mut self, pipeline_id: PipelineId) { - self.pipeline_id = pipeline_id; - } - - /// Is this a top-level browsing context? - pub fn is_top_level(&self) -> bool { - self.id == self.top_level_id - } -} - -/// An iterator over browsing contexts, returning the descendant -/// contexts whose active documents are fully active, in depth-first -/// order. -pub struct FullyActiveBrowsingContextsIterator<'a> { - /// The browsing contexts still to iterate over. - pub stack: Vec, - - /// The set of all browsing contexts. - pub browsing_contexts: &'a HashMap, - - /// The set of all pipelines. We use this to find the active - /// children of a frame, which are the iframes in the currently - /// active document. - pub pipelines: &'a HashMap, -} - -impl<'a> Iterator for FullyActiveBrowsingContextsIterator<'a> { - type Item = &'a BrowsingContext; - fn next(&mut self) -> Option<&'a BrowsingContext> { - loop { - let browsing_context_id = self.stack.pop()?; - let browsing_context = match self.browsing_contexts.get(&browsing_context_id) { - Some(browsing_context) => browsing_context, - None => { - warn!("BrowsingContext {:?} iterated after closure.", browsing_context_id); - continue; - }, - }; - let pipeline = match self.pipelines.get(&browsing_context.pipeline_id) { - Some(pipeline) => pipeline, - None => { - warn!("Pipeline {:?} iterated after closure.", browsing_context.pipeline_id); - continue; - }, - }; - self.stack.extend(pipeline.children.iter()); - return Some(browsing_context) - } - } -} - -/// An iterator over browsing contexts, returning all descendant -/// contexts in depth-first order. Note that this iterator returns all -/// contexts, not just the fully active ones. -pub struct AllBrowsingContextsIterator<'a> { - /// The browsing contexts still to iterate over. - pub stack: Vec, - - /// The set of all browsing contexts. - pub browsing_contexts: &'a HashMap, - - /// The set of all pipelines. We use this to find the - /// children of a browsing context, which are the iframes in all documents - /// in the session history. - pub pipelines: &'a HashMap, -} - -impl<'a> Iterator for AllBrowsingContextsIterator<'a> { - type Item = &'a BrowsingContext; - fn next(&mut self) -> Option<&'a BrowsingContext> { - let pipelines = self.pipelines; - loop { - let browsing_context_id = self.stack.pop()?; - let browsing_context = match self.browsing_contexts.get(&browsing_context_id) { - Some(browsing_context) => browsing_context, - None => { - warn!("BrowsingContext {:?} iterated after closure.", browsing_context_id); - continue; - }, - }; - let child_browsing_context_ids = browsing_context.pipelines.iter() - .filter_map(|pipeline_id| pipelines.get(&pipeline_id)) - .flat_map(|pipeline| pipeline.children.iter()); - self.stack.extend(child_browsing_context_ids); - return Some(browsing_context) - } - } -} diff --git a/servo/components/constellation/constellation.rs b/servo/components/constellation/constellation.rs deleted file mode 100644 index 9217939ee2ca..000000000000 --- a/servo/components/constellation/constellation.rs +++ /dev/null @@ -1,2959 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -//! The `Constellation`, Servo's Grand Central Station -//! -//! The constellation tracks all information kept globally by the -//! browser engine, which includes: -//! -//! * The set of all `EventLoop` objects. Each event loop is -//! the constellation's view of a script thread. The constellation -//! interacts with a script thread by message-passing. -//! -//! * The set of all `Pipeline` objects. Each pipeline gives the -//! constellation's view of a `Window`, with its script thread and -//! layout threads. Pipelines may share script threads, but not -//! layout threads. -//! -//! * The set of all `BrowsingContext` objects. Each browsing context -//! gives the constellation's view of a `WindowProxy`. -//! Each browsing context stores an independent -//! session history, created by navigation. The session -//! history can be traversed, for example by the back and forwards UI, -//! so each session history maintains a list of past and future pipelines, -//! as well as the current active pipeline. -//! -//! There are two kinds of browsing context: top-level ones (for -//! example tabs in a browser UI), and nested ones (typically caused -//! by `iframe` elements). Browsing contexts have a hierarchy -//! (typically caused by `iframe`s containing `iframe`s), giving rise -//! to a forest whose roots are top-level browsing context. The logical -//! relationship between these types is: -//! -//! ``` -//! +------------+ +------------+ +---------+ -//! | Browsing | ------parent?------> | Pipeline | --event_loop--> | Event | -//! | Context | ------current------> | | | Loop | -//! | | ------prev*--------> | | <---pipeline*-- | | -//! | | ------next*--------> | | +---------+ -//! | | | | -//! | | <-top_level--------- | | -//! | | <-browsing_context-- | | -//! +------------+ +------------+ -//! ``` -// -//! The constellation also maintains channels to threads, including: -//! -//! * The script and layout threads. -//! * The graphics compositor. -//! * The font cache, image cache, and resource manager, which load -//! and cache shared fonts, images, or other resources. -//! * The service worker manager. -//! * The devtools, debugger and webdriver servers. -//! -//! The constellation passes messages between the threads, and updates its state -//! to track the evolving state of the browsing context tree. -//! -//! The constellation acts as a logger, tracking any `warn!` messages from threads, -//! and converting any `error!` or `panic!` into a crash report. -//! -//! Since there is only one constellation, and its responsibilities include crash reporting, -//! it is very important that it does not panic. -//! -//! It's also important that the constellation not deadlock. In particular, we need -//! to be careful that we don't introduce any cycles in the can-block-on relation. -//! Blocking is typically introduced by `receiver.recv()`, which blocks waiting for the -//! sender to send some data. Servo tries to achieve deadlock-freedom by using the following -//! can-block-on relation: -//! -//! * Layout can block on canvas -//! * Layout can block on font cache -//! * Layout can block on image cache -//! * Constellation can block on compositor -//! * Constellation can block on embedder -//! * Constellation can block on layout -//! * Script can block on anything (other than script) -//! * Blocking is transitive (if T1 can block on T2 and T2 can block on T3 then T1 can block on T3) -//! * Nothing can block on itself! -//! -//! There is a complexity intoduced by IPC channels, since they do not support -//! non-blocking send. This means that as well as `receiver.recv()` blocking, -//! `sender.send(data)` can also block when the IPC buffer is full. For this reason it is -//! very important that all IPC receivers where we depend on non-blocking send -//! use a router to route IPC messages to an mpsc channel. The reason why that solves -//! the problem is that under the hood, the router uses a dedicated thread to forward -//! messages, and: -//! -//! * Anything (other than a routing thread) can block on a routing thread -//! -//! See https://github.com/servo/servo/issues/14704 - -use backtrace::Backtrace; -use bluetooth_traits::BluetoothRequest; -use browsingcontext::{AllBrowsingContextsIterator, BrowsingContext, FullyActiveBrowsingContextsIterator}; -use canvas::canvas_paint_thread::CanvasPaintThread; -use canvas::webgl_thread::WebGLThreads; -use canvas_traits::canvas::CanvasId; -use canvas_traits::canvas::CanvasMsg; -use clipboard::{ClipboardContext, ClipboardProvider}; -use compositing::SendableFrameTree; -use compositing::compositor_thread::{CompositorProxy, EmbedderMsg, EmbedderProxy}; -use compositing::compositor_thread::Msg as ToCompositorMsg; -use debugger; -use devtools_traits::{ChromeToDevtoolsControlMsg, DevtoolsControlMsg}; -use euclid::{Size2D, TypedSize2D, TypedScale}; -use event_loop::EventLoop; -use gfx::font_cache_thread::FontCacheThread; -use gfx_traits::Epoch; -use ipc_channel::{Error as IpcError}; -use ipc_channel::ipc::{self, IpcSender, IpcReceiver}; -use ipc_channel::router::ROUTER; -use layout_traits::LayoutThreadFactory; -use log::{Log, Level, LevelFilter, Metadata, Record}; -use msg::constellation_msg::{BrowsingContextId, TopLevelBrowsingContextId, PipelineId}; -use msg::constellation_msg::{Key, KeyModifiers, KeyState}; -use msg::constellation_msg::{PipelineNamespace, PipelineNamespaceId, TraversalDirection}; -use net_traits::{self, IpcSend, FetchResponseMsg, ResourceThreads}; -use net_traits::pub_domains::reg_host; -use net_traits::request::RequestInit; -use net_traits::storage_thread::{StorageThreadMsg, StorageType}; -use network_listener::NetworkListener; -use pipeline::{InitialPipelineState, Pipeline}; -use profile_traits::mem; -use profile_traits::time; -use script_traits::{AnimationState, AnimationTickType, CompositorEvent}; -use script_traits::{ConstellationControlMsg, ConstellationMsg as FromCompositorMsg, DiscardBrowsingContext}; -use script_traits::{DocumentActivity, DocumentState, LayoutControlMsg, LoadData}; -use script_traits::{IFrameLoadInfo, IFrameLoadInfoWithData, IFrameSandboxState, TimerSchedulerMsg}; -use script_traits::{LayoutMsg as FromLayoutMsg, ScriptMsg as FromScriptMsg, ScriptThreadFactory}; -use script_traits::{LogEntry, ScriptToConstellationChan, ServiceWorkerMsg, webdriver_msg}; -use script_traits::{SWManagerMsg, ScopeThings, UpdatePipelineIdReason, WebDriverCommandMsg}; -use script_traits::{WindowSizeData, WindowSizeType}; -use serde::{Deserialize, Serialize}; -use servo_config::opts; -use servo_config::prefs::PREFS; -use servo_rand::{Rng, SeedableRng, ServoRng, random}; -use servo_remutex::ReentrantMutex; -use servo_url::{Host, ImmutableOrigin, ServoUrl}; -use session_history::{JointSessionHistory, NeedsToReload, SessionHistoryChange, SessionHistoryDiff}; -use std::borrow::ToOwned; -use std::collections::{HashMap, VecDeque}; -use std::marker::PhantomData; -use std::process; -use std::rc::{Rc, Weak}; -use std::sync::Arc; -use std::sync::mpsc::{Receiver, Sender, channel}; -use std::thread; -use style_traits::CSSPixel; -use style_traits::cursor::CursorKind; -use style_traits::viewport::ViewportConstraints; -use timer_scheduler::TimerScheduler; -use webrender_api; -use webvr_traits::{WebVREvent, WebVRMsg}; - -/// The `Constellation` itself. In the servo browser, there is one -/// constellation, which maintains all of the browser global data. -/// In embedded applications, there may be more than one constellation, -/// which are independent of each other. -/// -/// The constellation may be in a different process from the pipelines, -/// and communicates using IPC. -/// -/// It is parameterized over a `LayoutThreadFactory` and a -/// `ScriptThreadFactory` (which in practice are implemented by -/// `LayoutThread` in the `layout` crate, and `ScriptThread` in -/// the `script` crate). Script and layout communicate using a `Message` -/// type. -pub struct Constellation { - /// An IPC channel for script threads to send messages to the constellation. - /// This is the script threads' view of `script_receiver`. - script_sender: IpcSender<(PipelineId, FromScriptMsg)>, - - /// A channel for the constellation to receive messages from script threads. - /// This is the constellation's view of `script_sender`. - script_receiver: Receiver>, - - /// An IPC channel for layout threads to send messages to the constellation. - /// This is the layout threads' view of `layout_receiver`. - layout_sender: IpcSender, - - /// A channel for the constellation to receive messages from layout threads. - /// This is the constellation's view of `layout_sender`. - layout_receiver: Receiver>, - - /// A channel for network listener to send messages to the constellation. - network_listener_sender: Sender<(PipelineId, FetchResponseMsg)>, - - /// A channel for the constellation to receive messages from network listener. - network_listener_receiver: Receiver<(PipelineId, FetchResponseMsg)>, - - /// A channel for the constellation to receive messages from the compositor thread. - compositor_receiver: Receiver, - - /// A channel through which messages can be sent to the embedder. - embedder_proxy: EmbedderProxy, - - /// A channel (the implementation of which is port-specific) for the - /// constellation to send messages to the compositor thread. - compositor_proxy: CompositorProxy, - - /// The last frame tree sent to WebRender. - active_browser_id: Option, - - /// Channels for the constellation to send messages to the public - /// resource-related threads. There are two groups of resource - /// threads: one for public browsing, and one for private - /// browsing. - public_resource_threads: ResourceThreads, - - /// Channels for the constellation to send messages to the private - /// resource-related threads. There are two groups of resource - /// threads: one for public browsing, and one for private - /// browsing. - private_resource_threads: ResourceThreads, - - /// A channel for the constellation to send messages to the font - /// cache thread. - font_cache_thread: FontCacheThread, - - /// A channel for the constellation to send messages to the - /// debugger thread. - debugger_chan: Option, - - /// A channel for the constellation to send messages to the - /// devtools thread. - devtools_chan: Option>, - - /// An IPC channel for the constellation to send messages to the - /// bluetooth thread. - bluetooth_thread: IpcSender, - - /// An IPC channel for the constellation to send messages to the - /// Service Worker Manager thread. - swmanager_chan: Option>, - - /// An IPC channel for Service Worker Manager threads to send - /// messages to the constellation. This is the SW Manager thread's - /// view of `swmanager_receiver`. - swmanager_sender: IpcSender, - - /// A channel for the constellation to receive messages from the - /// Service Worker Manager thread. This is the constellation's view of - /// `swmanager_sender`. - swmanager_receiver: Receiver>, - - /// A channel for the constellation to send messages to the - /// time profiler thread. - time_profiler_chan: time::ProfilerChan, - - /// A channel for the constellation to send messages to the - /// memory profiler thread. - mem_profiler_chan: mem::ProfilerChan, - - /// A channel for the constellation to send messages to the - /// timer thread. - scheduler_chan: IpcSender, - - /// A single WebRender document the constellation operates on. - webrender_document: webrender_api::DocumentId, - - /// A channel for the constellation to send messages to the - /// WebRender thread. - webrender_api_sender: webrender_api::RenderApiSender, - - /// The set of all event loops in the browser. We generate a new - /// event loop for each registered domain name (aka eTLD+1) in - /// each top-level browsing context. We store the event loops in a map - /// indexed by top-level browsing context id - /// (as a `TopLevelBrowsingContextId`) and registered - /// domain name (as a `Host`) to event loops. This double - /// indirection ensures that separate tabs do not share event - /// loops, even if the same domain is loaded in each. - /// It is important that scripts with the same eTLD+1 - /// share an event loop, since they can use `document.domain` - /// to become same-origin, at which point they can share DOM objects. - event_loops: HashMap>>, - - joint_session_histories: HashMap, - - /// The set of all the pipelines in the browser. - /// (See the `pipeline` module for more details.) - pipelines: HashMap, - - /// The set of all the browsing contexts in the browser. - browsing_contexts: HashMap, - - /// When a navigation is performed, we do not immediately update - /// the session history, instead we ask the event loop to begin loading - /// the new document, and do not update the browsing context until the - /// document is active. Between starting the load and it activating, - /// we store a `SessionHistoryChange` object for the navigation in progress. - pending_changes: Vec, - - /// The currently focused pipeline for key events. - focus_pipeline_id: Option, - - /// Pipeline IDs are namespaced in order to avoid name collisions, - /// and the namespaces are allocated by the constellation. - next_pipeline_namespace_id: PipelineNamespaceId, - - /// The size of the top-level window. - window_size: WindowSizeData, - - /// Means of accessing the clipboard - clipboard_ctx: Option, - - /// Bits of state used to interact with the webdriver implementation - webdriver: WebDriverData, - - /// Document states for loaded pipelines (used only when writing screenshots). - document_states: HashMap, - - /// Are we shutting down? - shutting_down: bool, - - /// Have we seen any warnings? Hopefully always empty! - /// The buffer contains `(thread_name, reason)` entries. - handled_warnings: VecDeque<(Option, String)>, - - /// The random number generator and probability for closing pipelines. - /// This is for testing the hardening of the constellation. - random_pipeline_closure: Option<(ServoRng, f32)>, - - /// Phantom data that keeps the Rust type system happy. - phantom: PhantomData<(Message, LTF, STF)>, - - /// Entry point to create and get channels to a WebGLThread. - webgl_threads: Option, - - /// A channel through which messages can be sent to the webvr thread. - webvr_chan: Option>, - - /// An Id for the next canvas to use. - canvas_id: CanvasId, -} - -/// State needed to construct a constellation. -pub struct InitialConstellationState { - /// A channel through which messages can be sent to the embedder. - pub embedder_proxy: EmbedderProxy, - - /// A channel through which messages can be sent to the compositor. - pub compositor_proxy: CompositorProxy, - - /// A channel to the debugger, if applicable. - pub debugger_chan: Option, - - /// A channel to the developer tools, if applicable. - pub devtools_chan: Option>, - - /// A channel to the bluetooth thread. - pub bluetooth_thread: IpcSender, - - /// A channel to the font cache thread. - pub font_cache_thread: FontCacheThread, - - /// A channel to the resource thread. - pub public_resource_threads: ResourceThreads, - - /// A channel to the resource thread. - pub private_resource_threads: ResourceThreads, - - /// A channel to the time profiler thread. - pub time_profiler_chan: time::ProfilerChan, - - /// A channel to the memory profiler thread. - pub mem_profiler_chan: mem::ProfilerChan, - - /// Webrender document ID. - pub webrender_document: webrender_api::DocumentId, - - /// Webrender API. - pub webrender_api_sender: webrender_api::RenderApiSender, - - /// Entry point to create and get channels to a WebGLThread. - pub webgl_threads: Option, - - /// A channel to the webgl thread. - pub webvr_chan: Option>, - - /// Whether the constellation supports the clipboard. - /// TODO: this field is not used, remove it? - pub supports_clipboard: bool, -} - -/// Data needed for webdriver -struct WebDriverData { - load_channel: Option<(PipelineId, IpcSender)>, - resize_channel: Option>, -} - -impl WebDriverData { - fn new() -> WebDriverData { - WebDriverData { - load_channel: None, - resize_channel: None, - } - } -} - -/// When we are running reftests, we save an image to compare against a reference. -/// This enum gives the possible states of preparing such an image. -#[derive(Debug, PartialEq)] -enum ReadyToSave { - NoTopLevelBrowsingContext, - PendingChanges, - WebFontNotLoaded, - DocumentLoading, - EpochMismatch, - PipelineUnknown, - Ready, -} - -/// When we are exiting a pipeline, we can either force exiting or not. -/// A normal exit waits for the compositor to update its state before -/// exiting, and delegates layout exit to script. A forced exit does -/// not notify the compositor, and exits layout without involving script. -#[derive(Clone, Copy)] -enum ExitPipelineMode { - Normal, - Force, -} - -/// The constellation uses logging to perform crash reporting. -/// The constellation receives all `warn!`, `error!` and `panic!` messages, -/// and generates a crash report when it receives a panic. - -/// A logger directed at the constellation from content processes -#[derive(Clone)] -pub struct FromScriptLogger { - /// A channel to the constellation - pub script_to_constellation_chan: Arc>, -} - -impl FromScriptLogger { - /// Create a new constellation logger. - pub fn new(script_to_constellation_chan: ScriptToConstellationChan) -> FromScriptLogger { - FromScriptLogger { - script_to_constellation_chan: Arc::new(ReentrantMutex::new(script_to_constellation_chan)) - } - } - - /// The maximum log level the constellation logger is interested in. - pub fn filter(&self) -> LevelFilter { - LevelFilter::Warn - } -} - -impl Log for FromScriptLogger { - fn enabled(&self, metadata: &Metadata) -> bool { - metadata.level() <= Level::Warn - } - - fn log(&self, record: &Record) { - if let Some(entry) = log_entry(record) { - debug!("Sending log entry {:?}.", entry); - let thread_name = thread::current().name().map(ToOwned::to_owned); - let msg = FromScriptMsg::LogEntry(thread_name, entry); - let chan = self.script_to_constellation_chan.lock().unwrap_or_else(|err| err.into_inner()); - let _ = chan.send(msg); - } - } - - fn flush(&self) {} -} - -/// A logger directed at the constellation from the compositor -#[derive(Clone)] -pub struct FromCompositorLogger { - /// A channel to the constellation - pub constellation_chan: Arc>>, -} - -impl FromCompositorLogger { - /// Create a new constellation logger. - pub fn new(constellation_chan: Sender) -> FromCompositorLogger { - FromCompositorLogger { - constellation_chan: Arc::new(ReentrantMutex::new(constellation_chan)) - } - } - - /// The maximum log level the constellation logger is interested in. - pub fn filter(&self) -> LevelFilter { - LevelFilter::Warn - } -} - -impl Log for FromCompositorLogger { - fn enabled(&self, metadata: &Metadata) -> bool { - metadata.level() <= Level::Warn - } - - fn log(&self, record: &Record) { - if let Some(entry) = log_entry(record) { - debug!("Sending log entry {:?}.", entry); - let top_level_id = TopLevelBrowsingContextId::installed(); - let thread_name = thread::current().name().map(ToOwned::to_owned); - let msg = FromCompositorMsg::LogEntry(top_level_id, thread_name, entry); - let chan = self.constellation_chan.lock().unwrap_or_else(|err| err.into_inner()); - let _ = chan.send(msg); - } - } - - fn flush(&self) {} -} - -/// Rust uses `Record` for storing logging, but servo converts that to -/// a `LogEntry`. We do this so that we can record panics as well as log -/// messages, and because `Record` does not implement serde (de)serialization, -/// so cannot be used over an IPC channel. -fn log_entry(record: &Record) -> Option { - match record.level() { - Level::Error if thread::panicking() => Some(LogEntry::Panic( - format!("{}", record.args()), - format!("{:?}", Backtrace::new()) - )), - Level::Error => Some(LogEntry::Error( - format!("{}", record.args()) - )), - Level::Warn => Some(LogEntry::Warn( - format!("{}", record.args()) - )), - _ => None, - } -} - -/// The number of warnings to include in each crash report. -const WARNINGS_BUFFER_SIZE: usize = 32; - -/// Route an ipc receiver to an mpsc receiver, preserving any errors. -/// This is the same as `route_ipc_receiver_to_new_mpsc_receiver`, -/// but does not panic on deserializtion errors. -fn route_ipc_receiver_to_new_mpsc_receiver_preserving_errors(ipc_receiver: IpcReceiver) - -> Receiver> - where T: for<'de> Deserialize<'de> + Serialize + Send + 'static -{ - let (mpsc_sender, mpsc_receiver) = channel(); - ROUTER.add_route(ipc_receiver.to_opaque(), Box::new(move |message| { - drop(mpsc_sender.send(message.to::())) - })); - mpsc_receiver -} - -impl Constellation - where LTF: LayoutThreadFactory, - STF: ScriptThreadFactory -{ - /// Create a new constellation thread. - pub fn start(state: InitialConstellationState) -> (Sender, IpcSender) { - let (compositor_sender, compositor_receiver) = channel(); - - // service worker manager to communicate with constellation - let (swmanager_sender, swmanager_receiver) = ipc::channel().expect("ipc channel failure"); - let sw_mgr_clone = swmanager_sender.clone(); - - thread::Builder::new().name("Constellation".to_owned()).spawn(move || { - let (ipc_script_sender, ipc_script_receiver) = ipc::channel().expect("ipc channel failure"); - let script_receiver = route_ipc_receiver_to_new_mpsc_receiver_preserving_errors(ipc_script_receiver); - - let (ipc_layout_sender, ipc_layout_receiver) = ipc::channel().expect("ipc channel failure"); - let layout_receiver = route_ipc_receiver_to_new_mpsc_receiver_preserving_errors(ipc_layout_receiver); - - let (network_listener_sender, network_listener_receiver) = channel(); - - let swmanager_receiver = route_ipc_receiver_to_new_mpsc_receiver_preserving_errors(swmanager_receiver); - - PipelineNamespace::install(PipelineNamespaceId(0)); - - let mut constellation: Constellation = Constellation { - script_sender: ipc_script_sender, - layout_sender: ipc_layout_sender, - script_receiver: script_receiver, - compositor_receiver: compositor_receiver, - layout_receiver: layout_receiver, - network_listener_sender: network_listener_sender, - network_listener_receiver: network_listener_receiver, - embedder_proxy: state.embedder_proxy, - compositor_proxy: state.compositor_proxy, - active_browser_id: None, - debugger_chan: state.debugger_chan, - devtools_chan: state.devtools_chan, - bluetooth_thread: state.bluetooth_thread, - public_resource_threads: state.public_resource_threads, - private_resource_threads: state.private_resource_threads, - font_cache_thread: state.font_cache_thread, - swmanager_chan: None, - swmanager_receiver: swmanager_receiver, - swmanager_sender: sw_mgr_clone, - event_loops: HashMap::new(), - joint_session_histories: HashMap::new(), - pipelines: HashMap::new(), - browsing_contexts: HashMap::new(), - pending_changes: vec!(), - // We initialize the namespace at 1, since we reserved namespace 0 for the constellation - next_pipeline_namespace_id: PipelineNamespaceId(1), - focus_pipeline_id: None, - time_profiler_chan: state.time_profiler_chan, - mem_profiler_chan: state.mem_profiler_chan, - window_size: WindowSizeData { - initial_viewport: opts::get().initial_window_size.to_f32() * - TypedScale::new(1.0), - device_pixel_ratio: - TypedScale::new(opts::get().device_pixels_per_px.unwrap_or(1.0)), - }, - phantom: PhantomData, - clipboard_ctx: if state.supports_clipboard { - match ClipboardContext::new() { - Ok(c) => Some(c), - Err(e) => { - warn!("Error creating clipboard context ({})", e); - None - }, - } - } else { - None - }, - webdriver: WebDriverData::new(), - scheduler_chan: TimerScheduler::start(), - document_states: HashMap::new(), - webrender_document: state.webrender_document, - webrender_api_sender: state.webrender_api_sender, - shutting_down: false, - handled_warnings: VecDeque::new(), - random_pipeline_closure: opts::get().random_pipeline_closure_probability.map(|prob| { - let seed = opts::get().random_pipeline_closure_seed.unwrap_or_else(random); - let rng = ServoRng::from_seed(&[seed]); - warn!("Randomly closing pipelines."); - info!("Using seed {} for random pipeline closure.", seed); - (rng, prob) - }), - webgl_threads: state.webgl_threads, - webvr_chan: state.webvr_chan, - canvas_id: CanvasId(0), - }; - - constellation.run(); - }).expect("Thread spawning failed"); - - (compositor_sender, swmanager_sender) - } - - /// The main event loop for the constellation. - fn run(&mut self) { - while !self.shutting_down || !self.pipelines.is_empty() { - // Randomly close a pipeline if --random-pipeline-closure-probability is set - // This is for testing the hardening of the constellation. - self.maybe_close_random_pipeline(); - self.handle_request(); - } - self.handle_shutdown(); - } - - /// Generate a new pipeline id namespace. - fn next_pipeline_namespace_id(&mut self) -> PipelineNamespaceId { - let namespace_id = self.next_pipeline_namespace_id; - let PipelineNamespaceId(ref mut i) = self.next_pipeline_namespace_id; - *i += 1; - namespace_id - } - - /// Helper function for creating a pipeline - fn new_pipeline(&mut self, - pipeline_id: PipelineId, - browsing_context_id: BrowsingContextId, - top_level_browsing_context_id: TopLevelBrowsingContextId, - parent_info: Option, - initial_window_size: Option>, - // TODO: we have to provide ownership of the LoadData - // here, because it will be send on an ipc channel, - // and ipc channels take onership of their data. - // https://github.com/servo/ipc-channel/issues/138 - load_data: LoadData, - sandbox: IFrameSandboxState, - is_private: bool) { - if self.shutting_down { return; } - debug!("Creating new pipeline {} in browsing context {}.", pipeline_id, browsing_context_id); - - let (event_loop, host) = match sandbox { - IFrameSandboxState::IFrameSandboxed => (None, None), - IFrameSandboxState::IFrameUnsandboxed => { - // If this is an about:blank load, it must share the creator's event loop. - // This must match the logic in the script thread when determining the proper origin. - if load_data.url.as_str() != "about:blank" { - match reg_host(&load_data.url) { - None => (None, None), - Some(host) => { - let event_loop = self.event_loops.get(&top_level_browsing_context_id) - .and_then(|map| map.get(&host)) - .and_then(|weak| weak.upgrade()); - match event_loop { - None => (None, Some(host)), - Some(event_loop) => (Some(event_loop.clone()), None), - } - }, - } - } else if let Some(parent) = parent_info - .and_then(|pipeline_id| self.pipelines.get(&pipeline_id)) { - (Some(parent.event_loop.clone()), None) - } else if let Some(creator) = load_data.creator_pipeline_id - .and_then(|pipeline_id| self.pipelines.get(&pipeline_id)) { - (Some(creator.event_loop.clone()), None) - } else { - (None, None) - } - }, - }; - - let resource_threads = if is_private { - self.private_resource_threads.clone() - } else { - self.public_resource_threads.clone() - }; - - let parent_visibility = parent_info - .and_then(|parent_pipeline_id| self.pipelines.get(&parent_pipeline_id)) - .map(|pipeline| pipeline.visible); - - let prev_visibility = self.browsing_contexts.get(&browsing_context_id) - .and_then(|browsing_context| self.pipelines.get(&browsing_context.pipeline_id)) - .map(|pipeline| pipeline.visible) - .or(parent_visibility); - - let result = Pipeline::spawn::(InitialPipelineState { - id: pipeline_id, - browsing_context_id, - top_level_browsing_context_id, - parent_info, - script_to_constellation_chan: ScriptToConstellationChan { - sender: self.script_sender.clone(), - pipeline_id: pipeline_id, - }, - layout_to_constellation_chan: self.layout_sender.clone(), - scheduler_chan: self.scheduler_chan.clone(), - compositor_proxy: self.compositor_proxy.clone(), - devtools_chan: self.devtools_chan.clone(), - bluetooth_thread: self.bluetooth_thread.clone(), - swmanager_thread: self.swmanager_sender.clone(), - font_cache_thread: self.font_cache_thread.clone(), - resource_threads, - time_profiler_chan: self.time_profiler_chan.clone(), - mem_profiler_chan: self.mem_profiler_chan.clone(), - window_size: initial_window_size, - event_loop, - load_data, - device_pixel_ratio: self.window_size.device_pixel_ratio, - pipeline_namespace_id: self.next_pipeline_namespace_id(), - prev_visibility, - webrender_api_sender: self.webrender_api_sender.clone(), - webrender_document: self.webrender_document, - is_private, - webgl_chan: self.webgl_threads.as_ref().map(|threads| threads.pipeline()), - webvr_chan: self.webvr_chan.clone() - }); - - let pipeline = match result { - Ok(result) => result, - Err(e) => return self.handle_send_error(pipeline_id, e), - }; - - if let Some(host) = host { - debug!("Adding new host entry {} for top-level browsing context {}.", host, top_level_browsing_context_id); - self.event_loops.entry(top_level_browsing_context_id) - .or_insert_with(HashMap::new) - .insert(host, Rc::downgrade(&pipeline.event_loop)); - } - - assert!(!self.pipelines.contains_key(&pipeline_id)); - self.pipelines.insert(pipeline_id, pipeline); - } - - /// Get an iterator for the fully active browsing contexts in a subtree. - fn fully_active_descendant_browsing_contexts_iter(&self, browsing_context_id: BrowsingContextId) - -> FullyActiveBrowsingContextsIterator - { - FullyActiveBrowsingContextsIterator { - stack: vec!(browsing_context_id), - pipelines: &self.pipelines, - browsing_contexts: &self.browsing_contexts, - } - } - - /// Get an iterator for the fully active browsing contexts in a tree. - fn fully_active_browsing_contexts_iter(&self, top_level_browsing_context_id: TopLevelBrowsingContextId) - -> FullyActiveBrowsingContextsIterator - { - self.fully_active_descendant_browsing_contexts_iter(BrowsingContextId::from(top_level_browsing_context_id)) - } - - /// Get an iterator for the browsing contexts in a subtree. - fn all_descendant_browsing_contexts_iter(&self, browsing_context_id: BrowsingContextId) - -> AllBrowsingContextsIterator - { - AllBrowsingContextsIterator { - stack: vec!(browsing_context_id), - pipelines: &self.pipelines, - browsing_contexts: &self.browsing_contexts, - } - } - - /// Create a new browsing context and update the internal bookkeeping. - fn new_browsing_context(&mut self, - browsing_context_id: BrowsingContextId, - top_level_id: TopLevelBrowsingContextId, - pipeline_id: PipelineId) { - debug!("Creating new browsing context {}", browsing_context_id); - let browsing_context = BrowsingContext::new(browsing_context_id, top_level_id, pipeline_id); - self.browsing_contexts.insert(browsing_context_id, browsing_context); - - // If a child browsing_context, add it to the parent pipeline. - let parent_info = self.pipelines.get(&pipeline_id) - .and_then(|pipeline| pipeline.parent_info); - if let Some(parent_id) = parent_info { - if let Some(parent) = self.pipelines.get_mut(&parent_id) { - parent.add_child(browsing_context_id); - } - } - } - - fn add_pending_change(&mut self, change: SessionHistoryChange) { - self.handle_load_start_msg(change.top_level_browsing_context_id, change.new_pipeline_id); - self.pending_changes.push(change); - } - - /// Handles loading pages, navigation, and granting access to the compositor - #[allow(unsafe_code)] - fn handle_request(&mut self) { - enum Request { - Script((PipelineId, FromScriptMsg)), - Compositor(FromCompositorMsg), - Layout(FromLayoutMsg), - NetworkListener((PipelineId, FetchResponseMsg)), - FromSWManager(SWManagerMsg), - } - - // Get one incoming request. - // This is one of the few places where the compositor is - // allowed to panic. If one of the receiver.recv() calls - // fails, it is because the matching sender has been - // reclaimed, but this can't happen in normal execution - // because the constellation keeps a pointer to the sender, - // so it should never be reclaimed. A possible scenario in - // which receiver.recv() fails is if some unsafe code - // produces undefined behaviour, resulting in the destructor - // being called. If this happens, there's not much we can do - // other than panic. - let request = { - let receiver_from_script = &self.script_receiver; - let receiver_from_compositor = &self.compositor_receiver; - let receiver_from_layout = &self.layout_receiver; - let receiver_from_network_listener = &self.network_listener_receiver; - let receiver_from_swmanager = &self.swmanager_receiver; - select! { - msg = receiver_from_script.recv() => - msg.expect("Unexpected script channel panic in constellation").map(Request::Script), - msg = receiver_from_compositor.recv() => - Ok(Request::Compositor(msg.expect("Unexpected compositor channel panic in constellation"))), - msg = receiver_from_layout.recv() => - msg.expect("Unexpected layout channel panic in constellation").map(Request::Layout), - msg = receiver_from_network_listener.recv() => - Ok(Request::NetworkListener( - msg.expect("Unexpected network listener channel panic in constellation") - )), - msg = receiver_from_swmanager.recv() => - msg.expect("Unexpected panic channel panic in constellation").map(Request::FromSWManager) - } - }; - - let request = match request { - Ok(request) => request, - Err(err) => return error!("Deserialization failed ({}).", err), - }; - - match request { - Request::Compositor(message) => { - self.handle_request_from_compositor(message) - }, - Request::Script(message) => { - self.handle_request_from_script(message); - }, - Request::Layout(message) => { - self.handle_request_from_layout(message); - }, - Request::NetworkListener(message) => { - self.handle_request_from_network_listener(message); - }, - Request::FromSWManager(message) => { - self.handle_request_from_swmanager(message); - } - } - } - - fn handle_request_from_network_listener(&mut self, message: (PipelineId, FetchResponseMsg)) { - let (id, message_) = message; - let result = match self.pipelines.get(&id) { - Some(pipeline) => { - let msg = ConstellationControlMsg::NavigationResponse(id, message_); - pipeline.event_loop.send(msg) - }, - None => { - return warn!("Pipeline {:?} got fetch data after closure!", id); - }, - }; - if let Err(e) = result { - self.handle_send_error(id, e); - } - } - - fn handle_request_from_swmanager(&mut self, message: SWManagerMsg) { - match message { - SWManagerMsg::OwnSender(sw_sender) => { - // store service worker manager for communicating with it. - self.swmanager_chan = Some(sw_sender); - } - } - } - - fn handle_request_from_compositor(&mut self, message: FromCompositorMsg) { - match message { - FromCompositorMsg::Exit => { - debug!("constellation exiting"); - self.handle_exit(); - } - FromCompositorMsg::GetBrowsingContext(pipeline_id, resp_chan) => { - debug!("constellation got get browsing context message"); - self.handle_get_browsing_context(pipeline_id, resp_chan); - } - FromCompositorMsg::GetPipeline(browsing_context_id, resp_chan) => { - debug!("constellation got get pipeline message"); - self.handle_get_pipeline(browsing_context_id, resp_chan); - } - FromCompositorMsg::GetFocusTopLevelBrowsingContext(resp_chan) => { - debug!("constellation got get focus browsing context message"); - let focus_browsing_context = self.focus_pipeline_id - .and_then(|pipeline_id| self.pipelines.get(&pipeline_id)) - .map(|pipeline| pipeline.top_level_browsing_context_id); - let _ = resp_chan.send(focus_browsing_context); - } - FromCompositorMsg::KeyEvent(ch, key, state, modifiers) => { - debug!("constellation got key event message"); - self.handle_key_msg(ch, key, state, modifiers); - } - // Load a new page from a typed url - // If there is already a pending page (self.pending_changes), it will not be overridden; - // However, if the id is not encompassed by another change, it will be. - FromCompositorMsg::LoadUrl(top_level_browsing_context_id, url) => { - debug!("constellation got URL load message from compositor"); - let load_data = LoadData::new(url, None, None, None); - let ctx_id = BrowsingContextId::from(top_level_browsing_context_id); - let pipeline_id = match self.browsing_contexts.get(&ctx_id) { - Some(ctx) => ctx.pipeline_id, - None => return warn!("LoadUrl for unknow browsing context: {:?}", top_level_browsing_context_id), - }; - self.handle_load_url_msg(top_level_browsing_context_id, pipeline_id, load_data, false); - } - FromCompositorMsg::IsReadyToSaveImage(pipeline_states) => { - let is_ready = self.handle_is_ready_to_save_image(pipeline_states); - debug!("Ready to save image {:?}.", is_ready); - if opts::get().is_running_problem_test { - println!("got ready to save image query, result is {:?}", is_ready); - } - let is_ready = is_ready == ReadyToSave::Ready; - self.compositor_proxy.send(ToCompositorMsg::IsReadyToSaveImageReply(is_ready)); - if opts::get().is_running_problem_test { - println!("sent response"); - } - } - // Create a new top level browsing context. Will use response_chan to return - // the browsing context id. - FromCompositorMsg::NewBrowser(url, response_chan) => { - debug!("constellation got NewBrowser message"); - self.handle_new_top_level_browsing_context(url, response_chan); - } - // Close a top level browsing context. - FromCompositorMsg::CloseBrowser(top_level_browsing_context_id) => { - debug!("constellation got CloseBrowser message"); - self.handle_close_top_level_browsing_context(top_level_browsing_context_id); - } - // Send frame tree to WebRender. Make it visible. - FromCompositorMsg::SelectBrowser(top_level_browsing_context_id) => { - self.send_frame_tree(top_level_browsing_context_id); - } - // Handle a forward or back request - FromCompositorMsg::TraverseHistory(top_level_browsing_context_id, direction) => { - debug!("constellation got traverse history message from compositor"); - self.handle_traverse_history_msg(top_level_browsing_context_id, direction); - } - FromCompositorMsg::WindowSize(top_level_browsing_context_id, new_size, size_type) => { - debug!("constellation got window resize message"); - self.handle_window_size_msg(top_level_browsing_context_id, new_size, size_type); - } - FromCompositorMsg::TickAnimation(pipeline_id, tick_type) => { - self.handle_tick_animation(pipeline_id, tick_type) - } - FromCompositorMsg::WebDriverCommand(command) => { - debug!("constellation got webdriver command message"); - self.handle_webdriver_msg(command); - } - FromCompositorMsg::Reload(top_level_browsing_context_id) => { - debug!("constellation got reload message"); - self.handle_reload_msg(top_level_browsing_context_id); - } - FromCompositorMsg::LogEntry(top_level_browsing_context_id, thread_name, entry) => { - self.handle_log_entry(top_level_browsing_context_id, thread_name, entry); - } - FromCompositorMsg::WebVREvents(pipeline_ids, events) => { - debug!("constellation got {:?} WebVR events", events.len()); - self.handle_webvr_events(pipeline_ids, events); - } - FromCompositorMsg::ForwardEvent(destination_pipeline_id, event) => { - self.forward_event(destination_pipeline_id, event); - } - FromCompositorMsg::SetCursor(cursor) => { - self.handle_set_cursor_msg(cursor) - } - } - } - - fn handle_request_from_script(&mut self, message: (PipelineId, FromScriptMsg)) { - let (source_pipeline_id, content) = message; - let source_top_ctx_id = match self.pipelines.get(&source_pipeline_id) - .map(|pipeline| pipeline.top_level_browsing_context_id) { - None => return warn!("ScriptMsg from closed pipeline {:?}.", source_pipeline_id), - Some(ctx) => ctx, - }; - - let source_is_top_level_pipeline = self.browsing_contexts - .get(&BrowsingContextId::from(source_top_ctx_id)) - .map(|ctx| ctx.pipeline_id == source_pipeline_id) - .unwrap_or(false); - - match content { - FromScriptMsg::PipelineExited => { - self.handle_pipeline_exited(source_pipeline_id); - } - FromScriptMsg::InitiateNavigateRequest(req_init, cancel_chan) => { - debug!("constellation got initiate navigate request message"); - self.handle_navigate_request(source_pipeline_id, req_init, cancel_chan); - } - FromScriptMsg::ScriptLoadedURLInIFrame(load_info) => { - debug!("constellation got iframe URL load message {:?} {:?} {:?}", - load_info.info.parent_pipeline_id, - load_info.old_pipeline_id, - load_info.info.new_pipeline_id); - self.handle_script_loaded_url_in_iframe_msg(load_info); - } - FromScriptMsg::ScriptNewIFrame(load_info, layout_sender) => { - debug!("constellation got loaded `about:blank` in iframe message {:?} {:?}", - load_info.parent_pipeline_id, - load_info.new_pipeline_id); - self.handle_script_new_iframe(load_info, layout_sender); - } - FromScriptMsg::ChangeRunningAnimationsState(animation_state) => { - self.handle_change_running_animations_state(source_pipeline_id, animation_state) - } - // Load a new page from a mouse click - // If there is already a pending page (self.pending_changes), it will not be overridden; - // However, if the id is not encompassed by another change, it will be. - FromScriptMsg::LoadUrl(load_data, replace) => { - debug!("constellation got URL load message from script"); - self.handle_load_url_msg(source_top_ctx_id, source_pipeline_id, load_data, replace); - } - FromScriptMsg::AbortLoadUrl => { - debug!("constellation got abort URL load message from script"); - self.handle_abort_load_url_msg(source_pipeline_id); - } - // A page loaded has completed all parsing, script, and reflow messages have been sent. - FromScriptMsg::LoadComplete => { - debug!("constellation got load complete message"); - self.handle_load_complete_msg(source_top_ctx_id, source_pipeline_id) - } - // Handle a forward or back request - FromScriptMsg::TraverseHistory(direction) => { - debug!("constellation got traverse history message from script"); - self.handle_traverse_history_msg(source_top_ctx_id, direction); - } - // Handle a joint session history length request. - FromScriptMsg::JointSessionHistoryLength(sender) => { - debug!("constellation got joint session history length message from script"); - self.handle_joint_session_history_length(source_top_ctx_id, sender); - } - // Notification that the new document is ready to become active - FromScriptMsg::ActivateDocument => { - debug!("constellation got activate document message"); - self.handle_activate_document_msg(source_pipeline_id); - } - // Update pipeline url after redirections - FromScriptMsg::SetFinalUrl(final_url) => { - // The script may have finished loading after we already started shutting down. - if let Some(ref mut pipeline) = self.pipelines.get_mut(&source_pipeline_id) { - debug!("constellation got set final url message"); - pipeline.url = final_url; - } else { - warn!("constellation got set final url message for dead pipeline"); - } - } - FromScriptMsg::PostMessage(browsing_context_id, origin, data) => { - debug!("constellation got postMessage message"); - self.handle_post_message_msg(browsing_context_id, origin, data); - } - FromScriptMsg::Focus => { - debug!("constellation got focus message"); - self.handle_focus_msg(source_pipeline_id); - } - FromScriptMsg::ForwardEvent(destination_pipeline_id, event) => { - self.forward_event(destination_pipeline_id, event); - } - FromScriptMsg::GetClipboardContents(sender) => { - let contents = match self.clipboard_ctx { - Some(ref mut ctx) => match ctx.get_contents() { - Ok(c) => c, - Err(e) => { - warn!("Error getting clipboard contents ({}), defaulting to empty string", e); - "".to_owned() - }, - }, - None => "".to_owned(), - }; - if let Err(e) = sender.send(contents.to_owned()) { - warn!("Failed to send clipboard ({})", e); - } - } - FromScriptMsg::SetClipboardContents(s) => { - if let Some(ref mut ctx) = self.clipboard_ctx { - if let Err(e) = ctx.set_contents(s) { - warn!("Error setting clipboard contents ({})", e); - } - } - } - FromScriptMsg::SetVisible(visible) => { - debug!("constellation got set visible messsage"); - self.handle_set_visible_msg(source_pipeline_id, visible); - } - FromScriptMsg::VisibilityChangeComplete(visible) => { - debug!("constellation got set visibility change complete message"); - self.handle_visibility_change_complete(source_pipeline_id, visible); - } - FromScriptMsg::RemoveIFrame(browsing_context_id, sender) => { - debug!("constellation got remove iframe message"); - let removed_pipeline_ids = self.handle_remove_iframe_msg(browsing_context_id); - if let Err(e) = sender.send(removed_pipeline_ids) { - warn!("Error replying to remove iframe ({})", e); - } - } - FromScriptMsg::NewFavicon(url) => { - debug!("constellation got new favicon message"); - if source_is_top_level_pipeline { - self.embedder_proxy.send(EmbedderMsg::NewFavicon(source_top_ctx_id, url)); - } - } - FromScriptMsg::HeadParsed => { - debug!("constellation got head parsed message"); - if source_is_top_level_pipeline { - self.embedder_proxy.send(EmbedderMsg::HeadParsed(source_top_ctx_id)); - } - } - FromScriptMsg::CreateCanvasPaintThread(size, sender) => { - debug!("constellation got create-canvas-paint-thread message"); - self.handle_create_canvas_paint_thread_msg(&size, sender) - } - FromScriptMsg::NodeStatus(message) => { - debug!("constellation got NodeStatus message"); - self.embedder_proxy.send(EmbedderMsg::Status(source_top_ctx_id, message)); - } - FromScriptMsg::SetDocumentState(state) => { - debug!("constellation got SetDocumentState message"); - self.document_states.insert(source_pipeline_id, state); - } - FromScriptMsg::Alert(message, sender) => { - debug!("constellation got Alert message"); - self.handle_alert(source_top_ctx_id, message, sender); - } - - FromScriptMsg::MoveTo(point) => { - self.embedder_proxy.send(EmbedderMsg::MoveTo(source_top_ctx_id, point)); - } - - FromScriptMsg::ResizeTo(size) => { - self.embedder_proxy.send(EmbedderMsg::ResizeTo(source_top_ctx_id, size)); - } - - FromScriptMsg::GetClientWindow(send) => { - self.compositor_proxy.send(ToCompositorMsg::GetClientWindow(send)); - } - FromScriptMsg::GetScreenSize(send) => { - self.compositor_proxy.send(ToCompositorMsg::GetScreenSize(send)); - } - FromScriptMsg::GetScreenAvailSize(send) => { - self.compositor_proxy.send(ToCompositorMsg::GetScreenAvailSize(send)); - } - - FromScriptMsg::Exit => { - self.compositor_proxy.send(ToCompositorMsg::Exit); - } - FromScriptMsg::LogEntry(thread_name, entry) => { - self.handle_log_entry(Some(source_top_ctx_id), thread_name, entry); - } - - FromScriptMsg::SetTitle(title) => { - if source_is_top_level_pipeline { - self.embedder_proxy.send(EmbedderMsg::ChangePageTitle(source_top_ctx_id, title)) - } - } - - FromScriptMsg::SendKeyEvent(ch, key, key_state, key_modifiers) => { - let event = EmbedderMsg::KeyEvent(Some(source_top_ctx_id), ch, key, key_state, key_modifiers); - self.embedder_proxy.send(event); - } - - FromScriptMsg::TouchEventProcessed(result) => { - self.compositor_proxy.send(ToCompositorMsg::TouchEventProcessed(result)) - } - FromScriptMsg::GetBrowsingContextId(pipeline_id, sender) => { - let result = self.pipelines.get(&pipeline_id).map(|pipeline| pipeline.browsing_context_id); - if let Err(e) = sender.send(result) { - warn!("Sending reply to get browsing context failed ({:?}).", e); - } - } - FromScriptMsg::GetParentInfo(pipeline_id, sender) => { - let result = self.pipelines.get(&pipeline_id).and_then(|pipeline| pipeline.parent_info); - if let Err(e) = sender.send(result) { - warn!("Sending reply to get parent info failed ({:?}).", e); - } - } - FromScriptMsg::RegisterServiceWorker(scope_things, scope) => { - debug!("constellation got store registration scope message"); - self.handle_register_serviceworker(scope_things, scope); - } - FromScriptMsg::ForwardDOMMessage(msg_vec, scope_url) => { - if let Some(ref mgr) = self.swmanager_chan { - let _ = mgr.send(ServiceWorkerMsg::ForwardDOMMessage(msg_vec, scope_url)); - } else { - warn!("Unable to forward DOMMessage for postMessage call"); - } - } - FromScriptMsg::BroadcastStorageEvent(storage, url, key, old_value, new_value) => { - self.handle_broadcast_storage_event(source_pipeline_id, storage, url, key, old_value, new_value); - } - FromScriptMsg::SetFullscreenState(state) => { - self.embedder_proxy.send(EmbedderMsg::SetFullscreenState(source_top_ctx_id, state)); - } - } - } - - fn handle_request_from_layout(&mut self, message: FromLayoutMsg) { - match message { - FromLayoutMsg::ChangeRunningAnimationsState(pipeline_id, animation_state) => { - self.handle_change_running_animations_state(pipeline_id, animation_state) - } - // Layout sends new sizes for all subframes. This needs to be reflected by all - // frame trees in the navigation context containing the subframe. - FromLayoutMsg::IFrameSizes(iframe_sizes) => { - debug!("constellation got iframe size message"); - self.handle_iframe_size_msg(iframe_sizes); - } - FromLayoutMsg::PendingPaintMetric(pipeline_id, epoch) => { - debug!("constellation got a pending paint metric message"); - self.handle_pending_paint_metric(pipeline_id, epoch); - } - FromLayoutMsg::SetCursor(cursor) => { - self.handle_set_cursor_msg(cursor) - } - FromLayoutMsg::ViewportConstrained(pipeline_id, constraints) => { - debug!("constellation got viewport-constrained event message"); - self.handle_viewport_constrained_msg(pipeline_id, constraints); - } - } - } - - fn handle_register_serviceworker(&self, scope_things: ScopeThings, scope: ServoUrl) { - if let Some(ref mgr) = self.swmanager_chan { - let _ = mgr.send(ServiceWorkerMsg::RegisterServiceWorker(scope_things, scope)); - } else { - warn!("sending scope info to service worker manager failed"); - } - } - - fn handle_broadcast_storage_event(&self, pipeline_id: PipelineId, storage: StorageType, url: ServoUrl, - key: Option, old_value: Option, new_value: Option) { - let origin = url.origin(); - for pipeline in self.pipelines.values() { - if (pipeline.id != pipeline_id) && (pipeline.url.origin() == origin) { - let msg = ConstellationControlMsg::DispatchStorageEvent( - pipeline.id, storage, url.clone(), key.clone(), old_value.clone(), new_value.clone() - ); - if let Err(err) = pipeline.event_loop.send(msg) { - warn!("Failed to broadcast storage event to pipeline {} ({:?}).", pipeline.id, err); - } - } - } - } - - fn handle_exit(&mut self) { - // TODO: add a timer, which forces shutdown if threads aren't responsive. - if self.shutting_down { return; } - self.shutting_down = true; - - self.mem_profiler_chan.send(mem::ProfilerMsg::Exit); - - // Close the top-level browsing contexts - let browsing_context_ids: Vec = self.browsing_contexts.values() - .filter(|browsing_context| browsing_context.is_top_level()) - .map(|browsing_context| browsing_context.id) - .collect(); - for browsing_context_id in browsing_context_ids { - debug!("Removing top-level browsing context {}.", browsing_context_id); - self.close_browsing_context(browsing_context_id, ExitPipelineMode::Normal); - } - - // Close any pending changes and pipelines - while let Some(pending) = self.pending_changes.pop() { - debug!("Removing pending browsing context {}.", pending.browsing_context_id); - self.close_browsing_context(pending.browsing_context_id, ExitPipelineMode::Normal); - debug!("Removing pending pipeline {}.", pending.new_pipeline_id); - self.close_pipeline(pending.new_pipeline_id, DiscardBrowsingContext::Yes, ExitPipelineMode::Normal); - } - - // In case there are browsing contexts which weren't attached, we close them. - let browsing_context_ids: Vec = self.browsing_contexts.keys().cloned().collect(); - for browsing_context_id in browsing_context_ids { - debug!("Removing detached browsing context {}.", browsing_context_id); - self.close_browsing_context(browsing_context_id, ExitPipelineMode::Normal); - } - - // In case there are pipelines which weren't attached to the pipeline tree, we close them. - let pipeline_ids: Vec = self.pipelines.keys().cloned().collect(); - for pipeline_id in pipeline_ids { - debug!("Removing detached pipeline {}.", pipeline_id); - self.close_pipeline(pipeline_id, DiscardBrowsingContext::Yes, ExitPipelineMode::Normal); - } - } - - fn handle_shutdown(&mut self) { - // At this point, there are no active pipelines, - // so we can safely block on other threads, without worrying about deadlock. - // Channels to receive signals when threads are done exiting. - let (core_sender, core_receiver) = ipc::channel().expect("Failed to create IPC channel!"); - let (storage_sender, storage_receiver) = ipc::channel().expect("Failed to create IPC channel!"); - - debug!("Exiting core resource threads."); - if let Err(e) = self.public_resource_threads.send(net_traits::CoreResourceMsg::Exit(core_sender)) { - warn!("Exit resource thread failed ({})", e); - } - - if let Some(ref chan) = self.debugger_chan { - debugger::shutdown_server(chan); - } - - if let Some(ref chan) = self.devtools_chan { - debug!("Exiting devtools."); - let msg = DevtoolsControlMsg::FromChrome(ChromeToDevtoolsControlMsg::ServerExitMsg); - if let Err(e) = chan.send(msg) { - warn!("Exit devtools failed ({})", e); - } - } - - debug!("Exiting storage resource threads."); - if let Err(e) = self.public_resource_threads.send(StorageThreadMsg::Exit(storage_sender)) { - warn!("Exit storage thread failed ({})", e); - } - - debug!("Exiting bluetooth thread."); - if let Err(e) = self.bluetooth_thread.send(BluetoothRequest::Exit) { - warn!("Exit bluetooth thread failed ({})", e); - } - - debug!("Exiting service worker manager thread."); - if let Some(mgr) = self.swmanager_chan.as_ref() { - if let Err(e) = mgr.send(ServiceWorkerMsg::Exit) { - warn!("Exit service worker manager failed ({})", e); - } - } - - if let Some(webgl_threads) = self.webgl_threads.as_ref() { - debug!("Exiting WebGL thread."); - if let Err(e) = webgl_threads.exit() { - warn!("Exit WebGL Thread failed ({})", e); - } - } - - if let Some(chan) = self.webvr_chan.as_ref() { - debug!("Exiting WebVR thread."); - if let Err(e) = chan.send(WebVRMsg::Exit) { - warn!("Exit WebVR thread failed ({})", e); - } - } - - debug!("Exiting timer scheduler."); - if let Err(e) = self.scheduler_chan.send(TimerSchedulerMsg::Exit) { - warn!("Exit timer scheduler failed ({})", e); - } - - debug!("Exiting font cache thread."); - self.font_cache_thread.exit(); - - // Receive exit signals from threads. - if let Err(e) = core_receiver.recv() { - warn!("Exit resource thread failed ({})", e); - } - if let Err(e) = storage_receiver.recv() { - warn!("Exit storage thread failed ({})", e); - } - - debug!("Asking compositor to complete shutdown."); - self.compositor_proxy.send(ToCompositorMsg::ShutdownComplete); - } - - fn handle_pipeline_exited(&mut self, pipeline_id: PipelineId) { - debug!("Pipeline {:?} exited.", pipeline_id); - self.pipelines.remove(&pipeline_id); - } - - fn handle_send_error(&mut self, pipeline_id: PipelineId, err: IpcError) { - // Treat send error the same as receiving a panic message - error!("Pipeline {} send error ({}).", pipeline_id, err); - let top_level_browsing_context_id = self.pipelines.get(&pipeline_id) - .map(|pipeline| pipeline.top_level_browsing_context_id); - if let Some(top_level_browsing_context_id) = top_level_browsing_context_id { - let reason = format!("Send failed ({})", err); - self.handle_panic(top_level_browsing_context_id, reason, None); - } - } - - fn handle_panic(&mut self, - top_level_browsing_context_id: TopLevelBrowsingContextId, - reason: String, - backtrace: Option) - { - if opts::get().hard_fail { - // It's quite difficult to make Servo exit cleanly if some threads have failed. - // Hard fail exists for test runners so we crash and that's good enough. - println!("Pipeline failed in hard-fail mode. Crashing!"); - process::exit(1); - } - - debug!("Panic handler for top-level browsing context {}: {}.", top_level_browsing_context_id, reason); - - let browsing_context_id = BrowsingContextId::from(top_level_browsing_context_id); - - self.embedder_proxy.send(EmbedderMsg::Panic(top_level_browsing_context_id, reason, backtrace)); - - let (window_size, pipeline_id) = { - let browsing_context = self.browsing_contexts.get(&browsing_context_id); - let window_size = browsing_context.and_then(|browsing_context| browsing_context.size); - let pipeline_id = browsing_context.map(|browsing_context| browsing_context.pipeline_id); - (window_size, pipeline_id) - }; - - let (pipeline_url, parent_info) = { - let pipeline = pipeline_id.and_then(|id| self.pipelines.get(&id)); - let pipeline_url = pipeline.map(|pipeline| pipeline.url.clone()); - let parent_info = pipeline.and_then(|pipeline| pipeline.parent_info); - (pipeline_url, parent_info) - }; - - self.close_browsing_context_children(browsing_context_id, - DiscardBrowsingContext::No, - ExitPipelineMode::Force); - - let failure_url = ServoUrl::parse("about:failure").expect("infallible"); - - if let Some(pipeline_url) = pipeline_url { - if pipeline_url == failure_url { - return error!("about:failure failed"); - } - } - - warn!("creating replacement pipeline for about:failure"); - - let new_pipeline_id = PipelineId::new(); - let load_data = LoadData::new(failure_url, None, None, None); - let sandbox = IFrameSandboxState::IFrameSandboxed; - self.new_pipeline(new_pipeline_id, browsing_context_id, top_level_browsing_context_id, parent_info, - window_size, load_data.clone(), sandbox, false); - self.add_pending_change(SessionHistoryChange { - top_level_browsing_context_id: top_level_browsing_context_id, - browsing_context_id: browsing_context_id, - new_pipeline_id: new_pipeline_id, - replace: None, - }); - } - - fn handle_log_entry(&mut self, - top_level_browsing_context_id: Option, - thread_name: Option, - entry: LogEntry) - { - debug!("Received log entry {:?}.", entry); - match (entry, top_level_browsing_context_id) { - (LogEntry::Panic(reason, backtrace), Some(top_level_browsing_context_id)) => { - self.handle_panic(top_level_browsing_context_id, reason, Some(backtrace)); - }, - (LogEntry::Panic(reason, _), _) | (LogEntry::Error(reason), _) | (LogEntry::Warn(reason), _) => { - // VecDeque::truncate is unstable - if WARNINGS_BUFFER_SIZE <= self.handled_warnings.len() { - self.handled_warnings.pop_front(); - } - self.handled_warnings.push_back((thread_name, reason)); - }, - } - } - - fn handle_webvr_events(&mut self, ids: Vec, events: Vec) { - for id in ids { - match self.pipelines.get_mut(&id) { - Some(ref pipeline) => { - // Notify script thread - let _ = pipeline.event_loop.send(ConstellationControlMsg::WebVREvents(id, events.clone())); - }, - None => warn!("constellation got webvr event for dead pipeline") - } - } - } - - fn forward_event(&mut self, destination_pipeline_id: PipelineId, event: CompositorEvent) { - let msg = ConstellationControlMsg::SendEvent(destination_pipeline_id, event); - let result = match self.pipelines.get(&destination_pipeline_id) { - None => { - debug!("Pipeline {:?} got event after closure.", destination_pipeline_id); - return; - } - Some(pipeline) => pipeline.event_loop.send(msg), - }; - if let Err(e) = result { - self.handle_send_error(destination_pipeline_id, e); - } - } - - fn handle_new_top_level_browsing_context(&mut self, url: ServoUrl, reply: IpcSender) { - let window_size = self.window_size.initial_viewport; - let pipeline_id = PipelineId::new(); - let top_level_browsing_context_id = TopLevelBrowsingContextId::new(); - if let Err(e) = reply.send(top_level_browsing_context_id) { - warn!("Failed to send newly created top level browsing context ({}).", e); - } - let browsing_context_id = BrowsingContextId::from(top_level_browsing_context_id); - let load_data = LoadData::new(url.clone(), None, None, None); - let sandbox = IFrameSandboxState::IFrameUnsandboxed; - if self.focus_pipeline_id.is_none() { - self.focus_pipeline_id = Some(pipeline_id); - } - self.joint_session_histories.insert(top_level_browsing_context_id, JointSessionHistory::new()); - self.new_pipeline(pipeline_id, - browsing_context_id, - top_level_browsing_context_id, - None, - Some(window_size), - load_data.clone(), - sandbox, - false); - self.add_pending_change(SessionHistoryChange { - top_level_browsing_context_id: top_level_browsing_context_id, - browsing_context_id: browsing_context_id, - new_pipeline_id: pipeline_id, - replace: None, - }); - } - - fn handle_close_top_level_browsing_context(&mut self, top_level_browsing_context_id: TopLevelBrowsingContextId) { - let browsing_context_id = BrowsingContextId::from(top_level_browsing_context_id); - self.close_browsing_context(browsing_context_id, ExitPipelineMode::Normal); - } - - fn handle_iframe_size_msg(&mut self, - iframe_sizes: Vec<(BrowsingContextId, TypedSize2D)>) { - for (browsing_context_id, size) in iframe_sizes { - let window_size = WindowSizeData { - initial_viewport: size, - device_pixel_ratio: self.window_size.device_pixel_ratio, - }; - - self.resize_browsing_context(window_size, WindowSizeType::Initial, browsing_context_id); - } - } - - fn handle_subframe_loaded(&mut self, pipeline_id: PipelineId) { - let (browsing_context_id, parent_id) = match self.pipelines.get(&pipeline_id) { - Some(pipeline) => match pipeline.parent_info { - Some(parent_id) => (pipeline.browsing_context_id, parent_id), - None => return debug!("Pipeline {} has no parent.", pipeline_id), - }, - None => return warn!("Pipeline {} loaded after closure.", pipeline_id), - }; - let msg = ConstellationControlMsg::DispatchIFrameLoadEvent { - target: browsing_context_id, - parent: parent_id, - child: pipeline_id, - }; - let result = match self.pipelines.get(&parent_id) { - Some(parent) => parent.event_loop.send(msg), - None => return warn!("Parent {} browsing context loaded after closure.", parent_id), - }; - if let Err(e) = result { - self.handle_send_error(parent_id, e); - } - } - - fn handle_navigate_request(&self, - id: PipelineId, - req_init: RequestInit, - cancel_chan: IpcReceiver<()>) { - let listener = NetworkListener::new( - req_init, - id, - self.public_resource_threads.clone(), - self.network_listener_sender.clone()); - - listener.initiate_fetch(Some(cancel_chan)); - } - - // The script thread associated with pipeline_id has loaded a URL in an iframe via script. This - // will result in a new pipeline being spawned and a child being added to - // the parent pipeline. This message is never the result of a - // page navigation. - fn handle_script_loaded_url_in_iframe_msg(&mut self, load_info: IFrameLoadInfoWithData) { - let (load_data, window_size, is_private) = { - let old_pipeline = load_info.old_pipeline_id - .and_then(|old_pipeline_id| self.pipelines.get(&old_pipeline_id)); - - let source_pipeline = match self.pipelines.get(&load_info.info.parent_pipeline_id) { - Some(source_pipeline) => source_pipeline, - None => return warn!("Script loaded url in closed iframe {}.", load_info.info.parent_pipeline_id), - }; - - // If no url is specified, reload. - let load_data = load_info.load_data.unwrap_or_else(|| { - let url = match old_pipeline { - Some(old_pipeline) => old_pipeline.url.clone(), - None => ServoUrl::parse("about:blank").expect("infallible"), - }; - - // TODO - loaddata here should have referrer info (not None, None) - LoadData::new(url, Some(source_pipeline.id), None, None) - }); - - let is_private = load_info.info.is_private || source_pipeline.is_private; - - let window_size = self.browsing_contexts.get(&load_info.info.browsing_context_id) - .and_then(|browsing_context| browsing_context.size); - - (load_data, window_size, is_private) - }; - - let replace = if load_info.info.replace { - self.browsing_contexts.get(&load_info.info.browsing_context_id) - .map(|browsing_context| NeedsToReload::No(browsing_context.pipeline_id)) - } else { - None - }; - - // Create the new pipeline, attached to the parent and push to pending changes - self.new_pipeline(load_info.info.new_pipeline_id, - load_info.info.browsing_context_id, - load_info.info.top_level_browsing_context_id, - Some(load_info.info.parent_pipeline_id), - window_size, - load_data.clone(), - load_info.sandbox, - is_private); - self.add_pending_change(SessionHistoryChange { - top_level_browsing_context_id: load_info.info.top_level_browsing_context_id, - browsing_context_id: load_info.info.browsing_context_id, - new_pipeline_id: load_info.info.new_pipeline_id, - replace, - }); - } - - fn handle_script_new_iframe(&mut self, - load_info: IFrameLoadInfo, - layout_sender: IpcSender) { - let IFrameLoadInfo { - parent_pipeline_id, - new_pipeline_id, - browsing_context_id, - top_level_browsing_context_id, - is_private, - .. - } = load_info; - - let url = ServoUrl::parse("about:blank").expect("infallible"); - - // TODO: Referrer? - let load_data = LoadData::new(url.clone(), Some(parent_pipeline_id), None, None); - - let pipeline = { - let parent_pipeline = match self.pipelines.get(&parent_pipeline_id) { - Some(parent_pipeline) => parent_pipeline, - None => return warn!("Script loaded url in closed iframe {}.", parent_pipeline_id), - }; - - let script_sender = parent_pipeline.event_loop.clone(); - - Pipeline::new(new_pipeline_id, - browsing_context_id, - top_level_browsing_context_id, - Some(parent_pipeline_id), - script_sender, - layout_sender, - self.compositor_proxy.clone(), - is_private || parent_pipeline.is_private, - url, - parent_pipeline.visible, - load_data) - }; - - assert!(!self.pipelines.contains_key(&new_pipeline_id)); - self.pipelines.insert(new_pipeline_id, pipeline); - - self.add_pending_change(SessionHistoryChange { - top_level_browsing_context_id: top_level_browsing_context_id, - browsing_context_id: browsing_context_id, - new_pipeline_id: new_pipeline_id, - replace: None, - }); - } - - fn handle_pending_paint_metric(&self, pipeline_id: PipelineId, epoch: Epoch) { - self.compositor_proxy.send(ToCompositorMsg::PendingPaintMetric(pipeline_id, epoch)) - } - - fn handle_set_cursor_msg(&mut self, cursor: CursorKind) { - self.embedder_proxy.send(EmbedderMsg::SetCursor(cursor)) - } - - fn handle_change_running_animations_state(&mut self, - pipeline_id: PipelineId, - animation_state: AnimationState) { - self.compositor_proxy.send(ToCompositorMsg::ChangeRunningAnimationsState(pipeline_id, - animation_state)) - } - - fn handle_tick_animation(&mut self, pipeline_id: PipelineId, tick_type: AnimationTickType) { - let result = match tick_type { - AnimationTickType::Script => { - let msg = ConstellationControlMsg::TickAllAnimations(pipeline_id); - match self.pipelines.get(&pipeline_id) { - Some(pipeline) => pipeline.event_loop.send(msg), - None => return warn!("Pipeline {:?} got script tick after closure.", pipeline_id), - } - } - AnimationTickType::Layout => { - let msg = LayoutControlMsg::TickAnimations; - match self.pipelines.get(&pipeline_id) { - Some(pipeline) => pipeline.layout_chan.send(msg), - None => return warn!("Pipeline {:?} got layout tick after closure.", pipeline_id), - } - } - }; - if let Err(e) = result { - self.handle_send_error(pipeline_id, e); - } - } - - fn handle_alert(&mut self, - top_level_browsing_context_id: TopLevelBrowsingContextId, - _message: String, - sender: IpcSender) { - // FIXME: forward alert event to embedder - // https://github.com/servo/servo/issues/19992 - let result = sender.send(true); - if let Err(e) = result { - let ctx_id = BrowsingContextId::from(top_level_browsing_context_id); - let pipeline_id = match self.browsing_contexts.get(&ctx_id) { - Some(ctx) => ctx.pipeline_id, - None => return warn!("Alert sent for unknown browsing context."), - }; - self.handle_send_error(pipeline_id, e); - } - } - - fn handle_load_url_msg(&mut self, top_level_browsing_context_id: TopLevelBrowsingContextId, source_id: PipelineId, - load_data: LoadData, replace: bool) { - self.load_url(top_level_browsing_context_id, source_id, load_data, replace); - } - - fn load_url(&mut self, top_level_browsing_context_id: TopLevelBrowsingContextId, source_id: PipelineId, - load_data: LoadData, replace: bool) -> Option { - // Allow the embedder to handle the url itself - let (chan, port) = ipc::channel().expect("Failed to create IPC channel!"); - let msg = EmbedderMsg::AllowNavigation(top_level_browsing_context_id, load_data.url.clone(), chan); - self.embedder_proxy.send(msg); - if let Ok(false) = port.recv() { - return None; - } - - debug!("Loading {} in pipeline {}.", load_data.url, source_id); - // If this load targets an iframe, its framing element may exist - // in a separate script thread than the framed document that initiated - // the new load. The framing element must be notified about the - // requested change so it can update its internal state. - // - // If replace is true, the current entry is replaced instead of a new entry being added. - let (browsing_context_id, parent_info) = match self.pipelines.get(&source_id) { - Some(pipeline) => (pipeline.browsing_context_id, pipeline.parent_info), - None => { - warn!("Pipeline {} loaded after closure.", source_id); - return None; - } - }; - match parent_info { - Some(parent_pipeline_id) => { - // Find the script thread for the pipeline containing the iframe - // and issue an iframe load through there. - let msg = ConstellationControlMsg::Navigate(parent_pipeline_id, - browsing_context_id, - load_data, - replace); - let result = match self.pipelines.get(&parent_pipeline_id) { - Some(parent_pipeline) => parent_pipeline.event_loop.send(msg), - None => { - warn!("Pipeline {:?} child loaded after closure", parent_pipeline_id); - return None; - }, - }; - if let Err(e) = result { - self.handle_send_error(parent_pipeline_id, e); - } - None - } - None => { - // Make sure no pending page would be overridden. - for change in &self.pending_changes { - if change.browsing_context_id == browsing_context_id { - // id that sent load msg is being changed already; abort - return None; - } - } - - if self.get_activity(source_id) == DocumentActivity::Inactive { - // Disregard this load if the navigating pipeline is not actually - // active. This could be caused by a delayed navigation (eg. from - // a timer) or a race between multiple navigations (such as an - // onclick handler on an anchor element). - return None; - } - - // Being here means either there are no pending changes, or none of the pending - // changes would be overridden by changing the subframe associated with source_id. - - // Create the new pipeline - let (top_level_id, window_size, pipeline_id) = match self.browsing_contexts.get(&browsing_context_id) { - Some(context) => (context.top_level_id, context.size, context.pipeline_id), - None => { - warn!("Browsing context {} loaded after closure.", browsing_context_id); - return None; - } - }; - - let replace = if replace { Some(NeedsToReload::No(pipeline_id)) } else { None }; - - let new_pipeline_id = PipelineId::new(); - let sandbox = IFrameSandboxState::IFrameUnsandboxed; - self.new_pipeline(new_pipeline_id, - browsing_context_id, - top_level_id, - None, - window_size, - load_data.clone(), - sandbox, - false); - self.add_pending_change(SessionHistoryChange { - top_level_browsing_context_id: top_level_id, - browsing_context_id: browsing_context_id, - new_pipeline_id: new_pipeline_id, - replace, - }); - Some(new_pipeline_id) - } - } - } - - fn handle_abort_load_url_msg(&mut self, new_pipeline_id: PipelineId) { - let pending_index = self.pending_changes.iter().rposition(|change| { - change.new_pipeline_id == new_pipeline_id - }); - - // If it is found, remove it from the pending changes. - if let Some(pending_index) = pending_index { - self.pending_changes.remove(pending_index); - self.close_pipeline(new_pipeline_id, DiscardBrowsingContext::No, ExitPipelineMode::Normal); - } - } - - fn handle_load_start_msg(&mut self, top_level_browsing_context_id: TopLevelBrowsingContextId, - pipeline_id: PipelineId) { - if self.pipelines.get(&pipeline_id).and_then(|p| p.parent_info).is_none() { - // Notify embedder top level document started loading. - self.embedder_proxy.send(EmbedderMsg::LoadStart(top_level_browsing_context_id)); - } - } - - fn handle_load_complete_msg(&mut self, top_level_browsing_context_id: TopLevelBrowsingContextId, - pipeline_id: PipelineId) { - let mut webdriver_reset = false; - if let Some((expected_pipeline_id, ref reply_chan)) = self.webdriver.load_channel { - debug!("Sending load to WebDriver"); - if expected_pipeline_id == pipeline_id { - let _ = reply_chan.send(webdriver_msg::LoadStatus::LoadComplete); - webdriver_reset = true; - } - } - if webdriver_reset { - self.webdriver.load_channel = None; - } - - // Notify the embedder that the TopLevelBrowsingContext current document - // has finished loading. - // We need to make sure the pipeline that has finished loading is the current - // pipeline and that no pending pipeline will replace the current one. - let pipeline_is_top_level_pipeline = self.browsing_contexts - .get(&BrowsingContextId::from(top_level_browsing_context_id)) - .map(|ctx| ctx.pipeline_id == pipeline_id) - .unwrap_or(false); - if pipeline_is_top_level_pipeline { - // Is there any pending pipeline that will replace the current top level pipeline - let current_top_level_pipeline_will_be_replaced = self.pending_changes.iter() - .any(|change| change.browsing_context_id == top_level_browsing_context_id); - - if !current_top_level_pipeline_will_be_replaced { - // Notify embedder and compositor top level document finished loading. - self.compositor_proxy.send(ToCompositorMsg::LoadComplete(top_level_browsing_context_id)); - self.embedder_proxy.send(EmbedderMsg::LoadComplete(top_level_browsing_context_id)); - } - } - self.handle_subframe_loaded(pipeline_id); - } - - fn handle_traverse_history_msg(&mut self, - top_level_browsing_context_id: TopLevelBrowsingContextId, - direction: TraversalDirection) - { - let mut browsing_context_changes = HashMap::::new(); - { - let session_history = self.joint_session_histories - .entry(top_level_browsing_context_id).or_insert(JointSessionHistory::new()); - - match direction { - TraversalDirection::Forward(forward) => { - let future_length = session_history.future.len(); - - if future_length < forward { - return warn!("Cannot traverse that far into the future."); - } - - for diff in session_history.future.drain(future_length - forward..).rev() { - match diff { - SessionHistoryDiff::BrowsingContextDiff { browsing_context_id, ref new_reloader, .. } => { - browsing_context_changes.insert(browsing_context_id, new_reloader.clone()); - } - } - session_history.past.push(diff); - } - }, - TraversalDirection::Back(back) => { - let past_length = session_history.past.len(); - - if past_length < back { - return warn!("Cannot traverse that far into the past."); - } - - for diff in session_history.past.drain(past_length - back..).rev() { - match diff { - SessionHistoryDiff::BrowsingContextDiff { browsing_context_id, ref old_reloader, .. } => { - browsing_context_changes.insert(browsing_context_id, old_reloader.clone()); - } - } - session_history.future.push(diff); - } - } - } - } - - for (browsing_context_id, pipeline_id) in browsing_context_changes.drain() { - self.update_browsing_context(browsing_context_id, pipeline_id); - } - - self.notify_history_changed(top_level_browsing_context_id); - - self.trim_history(top_level_browsing_context_id); - self.update_frame_tree_if_active(top_level_browsing_context_id); - } - - fn update_browsing_context(&mut self, browsing_context_id: BrowsingContextId, new_reloader: NeedsToReload) { - let new_pipeline_id = match new_reloader { - NeedsToReload::No(pipeline_id) => pipeline_id, - NeedsToReload::Yes(pipeline_id, load_data) => { - debug!("Reloading document {} in browsing context {}.", pipeline_id, browsing_context_id); - - // TODO: Save the sandbox state so it can be restored here. - let sandbox = IFrameSandboxState::IFrameUnsandboxed; - let new_pipeline_id = PipelineId::new(); - let (top_level_id, parent_info, window_size, is_private) = - match self.browsing_contexts.get(&browsing_context_id) - { - Some(browsing_context) => match self.pipelines.get(&browsing_context.pipeline_id) { - Some(pipeline) => ( - browsing_context.top_level_id, - pipeline.parent_info, - browsing_context.size, - pipeline.is_private - ), - None => ( - browsing_context.top_level_id, - None, - browsing_context.size, - false - ), - }, - None => return warn!("No browsing context to traverse!"), - }; - self.new_pipeline(new_pipeline_id, browsing_context_id, top_level_id, parent_info, - window_size, load_data.clone(), sandbox, is_private); - self.add_pending_change(SessionHistoryChange { - top_level_browsing_context_id: top_level_id, - browsing_context_id: browsing_context_id, - new_pipeline_id: new_pipeline_id, - replace: Some(NeedsToReload::Yes(pipeline_id, load_data.clone())) - }); - return; - }, - }; - - let old_pipeline_id = match self.browsing_contexts.get_mut(&browsing_context_id) { - Some(browsing_context) => { - let old_pipeline_id = browsing_context.pipeline_id; - browsing_context.update_current_entry(new_pipeline_id); - old_pipeline_id - }, - None => { - return warn!("Browsing context {} was closed during traversal", browsing_context_id); - } - }; - - let parent_info = self.pipelines.get(&old_pipeline_id).and_then(|pipeline| pipeline.parent_info); - - self.update_activity(old_pipeline_id); - self.update_activity(new_pipeline_id); - - if let Some(parent_pipeline_id) = parent_info { - let msg = ConstellationControlMsg::UpdatePipelineId(parent_pipeline_id, browsing_context_id, - new_pipeline_id, UpdatePipelineIdReason::Traversal); - let result = match self.pipelines.get(&parent_pipeline_id) { - None => return warn!("Pipeline {} child traversed after closure", parent_pipeline_id), - Some(pipeline) => pipeline.event_loop.send(msg), - }; - if let Err(e) = result { - self.handle_send_error(parent_pipeline_id, e); - } - } - } - - fn handle_joint_session_history_length(&self, - top_level_browsing_context_id: TopLevelBrowsingContextId, - sender: IpcSender) - { - let length = self.joint_session_histories.get(&top_level_browsing_context_id) - .map(JointSessionHistory::history_length) - .unwrap_or(1); - let _ = sender.send(length as u32); - } - - fn handle_key_msg(&mut self, ch: Option, key: Key, state: KeyState, mods: KeyModifiers) { - // Send to the explicitly focused pipeline. If it doesn't exist, fall back to sending to - // the compositor. - match self.focus_pipeline_id { - Some(pipeline_id) => { - let event = CompositorEvent::KeyEvent(ch, key, state, mods); - let msg = ConstellationControlMsg::SendEvent(pipeline_id, event); - let result = match self.pipelines.get(&pipeline_id) { - Some(pipeline) => pipeline.event_loop.send(msg), - None => return debug!("Pipeline {:?} got key event after closure.", pipeline_id), - }; - if let Err(e) = result { - self.handle_send_error(pipeline_id, e); - } - }, - None => { - let event = EmbedderMsg::KeyEvent(None, ch, key, state, mods); - self.embedder_proxy.clone().send(event); - } - } - } - - fn handle_reload_msg(&mut self, top_level_browsing_context_id: TopLevelBrowsingContextId) { - let browsing_context_id = BrowsingContextId::from(top_level_browsing_context_id); - let pipeline_id = match self.browsing_contexts.get(&browsing_context_id) { - Some(browsing_context) => browsing_context.pipeline_id, - None => return warn!("Browsing context {} got reload event after closure.", browsing_context_id), - }; - let msg = ConstellationControlMsg::Reload(pipeline_id); - let result = match self.pipelines.get(&pipeline_id) { - None => return warn!("Pipeline {} got reload event after closure.", pipeline_id), - Some(pipeline) => pipeline.event_loop.send(msg), - }; - if let Err(e) = result { - self.handle_send_error(pipeline_id, e); - } - } - - fn handle_post_message_msg(&mut self, - browsing_context_id: BrowsingContextId, - origin: Option, - data: Vec) - { - let pipeline_id = match self.browsing_contexts.get(&browsing_context_id) { - None => return warn!("postMessage to closed browsing_context {}.", browsing_context_id), - Some(browsing_context) => browsing_context.pipeline_id, - }; - let msg = ConstellationControlMsg::PostMessage(pipeline_id, origin, data); - let result = match self.pipelines.get(&pipeline_id) { - Some(pipeline) => pipeline.event_loop.send(msg), - None => return warn!("postMessage to closed pipeline {}.", pipeline_id), - }; - if let Err(e) = result { - self.handle_send_error(pipeline_id, e); - } - } - - fn handle_get_pipeline(&mut self, - browsing_context_id: BrowsingContextId, - resp_chan: IpcSender>) { - let current_pipeline_id = self.browsing_contexts.get(&browsing_context_id) - .map(|browsing_context| browsing_context.pipeline_id); - let pipeline_id_loaded = self.pending_changes.iter().rev() - .find(|x| x.browsing_context_id == browsing_context_id) - .map(|x| x.new_pipeline_id) - .or(current_pipeline_id); - if let Err(e) = resp_chan.send(pipeline_id_loaded) { - warn!("Failed get_pipeline response ({}).", e); - } - } - - fn handle_get_browsing_context(&mut self, - pipeline_id: PipelineId, - resp_chan: IpcSender>) { - let browsing_context_id = self.pipelines.get(&pipeline_id).map(|pipeline| pipeline.browsing_context_id); - if let Err(e) = resp_chan.send(browsing_context_id) { - warn!("Failed get_browsing_context response ({}).", e); - } - } - - fn focus_parent_pipeline(&mut self, pipeline_id: PipelineId) { - let (browsing_context_id, parent_info) = match self.pipelines.get(&pipeline_id) { - Some(pipeline) => (pipeline.browsing_context_id, pipeline.parent_info), - None => return warn!("Pipeline {:?} focus parent after closure.", pipeline_id), - }; - let parent_pipeline_id = match parent_info { - Some(info) => info, - None => return debug!("Pipeline {:?} focus has no parent.", pipeline_id), - }; - - // Send a message to the parent of the provided pipeline (if it exists) - // telling it to mark the iframe element as focused. - let msg = ConstellationControlMsg::FocusIFrame(parent_pipeline_id, browsing_context_id); - let result = match self.pipelines.get(&parent_pipeline_id) { - Some(pipeline) => pipeline.event_loop.send(msg), - None => return warn!("Pipeline {:?} focus after closure.", parent_pipeline_id), - }; - if let Err(e) = result { - self.handle_send_error(parent_pipeline_id, e); - } - self.focus_parent_pipeline(parent_pipeline_id); - } - - fn handle_focus_msg(&mut self, pipeline_id: PipelineId) { - self.focus_pipeline_id = Some(pipeline_id); - - // Focus parent iframes recursively - self.focus_parent_pipeline(pipeline_id); - } - - fn handle_remove_iframe_msg(&mut self, browsing_context_id: BrowsingContextId) -> Vec { - let result = self.all_descendant_browsing_contexts_iter(browsing_context_id) - .flat_map(|browsing_context| browsing_context.pipelines.iter().cloned()).collect(); - self.close_browsing_context(browsing_context_id, ExitPipelineMode::Normal); - result - } - - fn handle_set_visible_msg(&mut self, pipeline_id: PipelineId, visible: bool) { - let browsing_context_id = match self.pipelines.get(&pipeline_id) { - Some(pipeline) => pipeline.browsing_context_id, - None => return warn!("No browsing context associated with pipeline {:?}", pipeline_id), - }; - - let child_pipeline_ids: Vec = self.all_descendant_browsing_contexts_iter(browsing_context_id) - .flat_map(|browsing_context| browsing_context.pipelines.iter().cloned()).collect(); - - for id in child_pipeline_ids { - if let Some(pipeline) = self.pipelines.get_mut(&id) { - pipeline.change_visibility(visible); - } - } - } - - fn handle_visibility_change_complete(&mut self, pipeline_id: PipelineId, visibility: bool) { - let (browsing_context_id, parent_pipeline_info) = match self.pipelines.get(&pipeline_id) { - None => return warn!("Visibity change for closed pipeline {:?}.", pipeline_id), - Some(pipeline) => (pipeline.browsing_context_id, pipeline.parent_info), - }; - if let Some(parent_pipeline_id) = parent_pipeline_info { - let visibility_msg = ConstellationControlMsg::NotifyVisibilityChange(parent_pipeline_id, - browsing_context_id, - visibility); - let result = match self.pipelines.get(&parent_pipeline_id) { - None => return warn!("Parent pipeline {:?} closed", parent_pipeline_id), - Some(parent_pipeline) => parent_pipeline.event_loop.send(visibility_msg), - }; - - if let Err(e) = result { - self.handle_send_error(parent_pipeline_id, e); - } - } - } - - fn handle_create_canvas_paint_thread_msg( - &mut self, - size: &Size2D, - response_sender: IpcSender<(IpcSender, CanvasId)>) { - self.canvas_id.0 += 1; - let webrender_api = self.webrender_api_sender.clone(); - let sender = CanvasPaintThread::start(*size, webrender_api, - opts::get().enable_canvas_antialiasing, self.canvas_id.clone()); - if let Err(e) = response_sender.send((sender, self.canvas_id.clone())) { - warn!("Create canvas paint thread response failed ({})", e); - } - } - - fn handle_webdriver_msg(&mut self, msg: WebDriverCommandMsg) { - // Find the script channel for the given parent pipeline, - // and pass the event to that script thread. - match msg { - WebDriverCommandMsg::GetWindowSize(_, reply) => { - let _ = reply.send(self.window_size); - }, - WebDriverCommandMsg::SetWindowSize(top_level_browsing_context_id, size, reply) => { - self.webdriver.resize_channel = Some(reply); - self.embedder_proxy.send(EmbedderMsg::ResizeTo(top_level_browsing_context_id, size)); - }, - WebDriverCommandMsg::LoadUrl(top_level_browsing_context_id, load_data, reply) => { - self.load_url_for_webdriver(top_level_browsing_context_id, load_data, reply, false); - }, - WebDriverCommandMsg::Refresh(top_level_browsing_context_id, reply) => { - let browsing_context_id = BrowsingContextId::from(top_level_browsing_context_id); - let load_data = match self.browsing_contexts.get(&browsing_context_id) { - Some(browsing_context) => match self.pipelines.get(&browsing_context.pipeline_id) { - Some(pipeline) => pipeline.load_data.clone(), - None => return warn!("Pipeline {} refresh after closure.", browsing_context.pipeline_id), - }, - None => return warn!("Browsing context {} Refresh after closure.", browsing_context_id), - }; - self.load_url_for_webdriver(top_level_browsing_context_id, load_data, reply, true); - } - WebDriverCommandMsg::ScriptCommand(browsing_context_id, cmd) => { - let pipeline_id = match self.browsing_contexts.get(&browsing_context_id) { - Some(browsing_context) => browsing_context.pipeline_id, - None => return warn!("Browsing context {} ScriptCommand after closure.", browsing_context_id), - }; - let control_msg = ConstellationControlMsg::WebDriverScriptCommand(pipeline_id, cmd); - let result = match self.pipelines.get(&pipeline_id) { - Some(pipeline) => pipeline.event_loop.send(control_msg), - None => return warn!("Pipeline {:?} ScriptCommand after closure.", pipeline_id), - }; - if let Err(e) = result { - self.handle_send_error(pipeline_id, e); - } - }, - WebDriverCommandMsg::SendKeys(browsing_context_id, cmd) => { - let pipeline_id = match self.browsing_contexts.get(&browsing_context_id) { - Some(browsing_context) => browsing_context.pipeline_id, - None => return warn!("Browsing context {} SendKeys after closure.", browsing_context_id), - }; - let event_loop = match self.pipelines.get(&pipeline_id) { - Some(pipeline) => pipeline.event_loop.clone(), - None => return warn!("Pipeline {} SendKeys after closure.", pipeline_id), - }; - for (key, mods, state) in cmd { - let event = CompositorEvent::KeyEvent(None, key, state, mods); - let control_msg = ConstellationControlMsg::SendEvent(pipeline_id, event); - if let Err(e) = event_loop.send(control_msg) { - return self.handle_send_error(pipeline_id, e); - } - } - }, - WebDriverCommandMsg::TakeScreenshot(_, reply) => { - self.compositor_proxy.send(ToCompositorMsg::CreatePng(reply)); - }, - } - } - - fn notify_history_changed(&self, top_level_browsing_context_id: TopLevelBrowsingContextId) { - // Send a flat projection of the history. - // The final vector is a concatenation of the LoadData of the past entries, - // the current entry and the future entries. - // LoadData of inner frames are ignored and replaced with the LoadData of the parent. - - let session_history = match self.joint_session_histories.get(&top_level_browsing_context_id) { - Some(session_history) => session_history, - None => return warn!("Session history does not exist for {}", top_level_browsing_context_id), - }; - - let browsing_context_id = BrowsingContextId::from(top_level_browsing_context_id); - let browsing_context = match self.browsing_contexts.get(&browsing_context_id) { - Some(browsing_context) => browsing_context, - None => return warn!("notify_history_changed error after top-level browsing context closed."), - }; - - let current_load_data = match self.pipelines.get(&browsing_context.pipeline_id) { - Some(pipeline) => pipeline.load_data.clone(), - None => return warn!("Pipeline {} refresh after closure.", browsing_context.pipeline_id), - }; - - // If LoadData was ignored, use the LoadData of the previous SessionHistoryEntry, which - // is the LoadData of the parent browsing context. - let resolve_load_data_future = |previous_load_data: &mut LoadData, diff: &SessionHistoryDiff| { - let SessionHistoryDiff::BrowsingContextDiff { browsing_context_id, ref new_reloader, .. } = *diff; - - if browsing_context_id == top_level_browsing_context_id { - let load_data = match *new_reloader { - NeedsToReload::No(pipeline_id) => match self.pipelines.get(&pipeline_id) { - Some(pipeline) => pipeline.load_data.clone(), - None => previous_load_data.clone(), - }, - NeedsToReload::Yes(_, ref load_data) => load_data.clone(), - }; - *previous_load_data = load_data.clone(); - Some(load_data) - } else { - Some(previous_load_data.clone()) - } - }; - - let resolve_load_data_past = |previous_load_data: &mut LoadData, diff: &SessionHistoryDiff| { - let SessionHistoryDiff::BrowsingContextDiff { browsing_context_id, ref old_reloader, .. } = *diff; - - if browsing_context_id == top_level_browsing_context_id { - let load_data = match *old_reloader { - NeedsToReload::No(pipeline_id) => match self.pipelines.get(&pipeline_id) { - Some(pipeline) => pipeline.load_data.clone(), - None => previous_load_data.clone(), - }, - NeedsToReload::Yes(_, ref load_data) => load_data.clone(), - }; - *previous_load_data = load_data.clone(); - Some(load_data) - } else { - Some(previous_load_data.clone()) - } - }; - - let mut entries: Vec = session_history.past.iter().rev() - .scan(current_load_data.clone(), &resolve_load_data_past).collect(); - - entries.reverse(); - - let current_index = entries.len(); - - entries.push(current_load_data.clone()); - - entries.extend(session_history.future.iter().rev() - .scan(current_load_data.clone(), &resolve_load_data_future)); - - let msg = EmbedderMsg::HistoryChanged(top_level_browsing_context_id, entries, current_index); - self.embedder_proxy.send(msg); - } - - fn load_url_for_webdriver(&mut self, - top_level_browsing_context_id: TopLevelBrowsingContextId, - load_data: LoadData, - reply: IpcSender, - replace: bool) - { - let browsing_context_id = BrowsingContextId::from(top_level_browsing_context_id); - let pipeline_id = match self.browsing_contexts.get(&browsing_context_id) { - Some(browsing_context) => browsing_context.pipeline_id, - None => return warn!("Webdriver load for closed browsing context {}.", browsing_context_id), - }; - if let Some(new_pipeline_id) = self.load_url(top_level_browsing_context_id, pipeline_id, load_data, replace) { - self.webdriver.load_channel = Some((new_pipeline_id, reply)); - } - } - - fn change_session_history(&mut self, change: SessionHistoryChange) { - debug!("Setting browsing context {} to be pipeline {}.", change.browsing_context_id, change.new_pipeline_id); - - // If the currently focused pipeline is the one being changed (or a child - // of the pipeline being changed) then update the focus pipeline to be - // the replacement. - if self.focused_pipeline_is_descendant_of(change.browsing_context_id) { - self.focus_pipeline_id = Some(change.new_pipeline_id); - } - - - let (old_pipeline_id, top_level_id) = match self.browsing_contexts.get_mut(&change.browsing_context_id) { - Some(browsing_context) => { - debug!("Adding pipeline to existing browsing context."); - let old_pipeline_id = browsing_context.pipeline_id; - browsing_context.pipelines.insert(change.new_pipeline_id); - browsing_context.update_current_entry(change.new_pipeline_id); - (Some(old_pipeline_id), Some(browsing_context.top_level_id)) - }, - None => { - debug!("Adding pipeline to new browsing context."); - (None, None) - } - }; - - match old_pipeline_id { - None => { - self.new_browsing_context(change.browsing_context_id, - change.top_level_browsing_context_id, - change.new_pipeline_id); - self.update_activity(change.new_pipeline_id); - self.notify_history_changed(change.top_level_browsing_context_id); - }, - Some(old_pipeline_id) => { - // Deactivate the old pipeline, and activate the new one. - let pipelines_to_close = if let Some(replace_reloader) = change.replace { - let session_history = self.joint_session_histories - .entry(change.top_level_browsing_context_id).or_insert(JointSessionHistory::new()); - session_history.replace(replace_reloader.clone(), - NeedsToReload::No(change.new_pipeline_id)); - - match replace_reloader { - NeedsToReload::No(pipeline_id) => vec![pipeline_id], - NeedsToReload::Yes(..) => vec![], - } - } else { - let session_history = self.joint_session_histories - .entry(change.top_level_browsing_context_id).or_insert(JointSessionHistory::new()); - let diff = SessionHistoryDiff::BrowsingContextDiff { - browsing_context_id: change.browsing_context_id, - new_reloader: NeedsToReload::No(change.new_pipeline_id), - old_reloader: NeedsToReload::No(old_pipeline_id), - }; - - session_history.push_diff(diff).into_iter() - .map(|SessionHistoryDiff::BrowsingContextDiff { new_reloader, .. }| new_reloader) - .filter_map(|pipeline_id| pipeline_id.alive_pipeline_id()) - .collect::>() - }; - - self.update_activity(old_pipeline_id); - self.update_activity(change.new_pipeline_id); - - for pipeline_id in pipelines_to_close { - self.close_pipeline(pipeline_id, DiscardBrowsingContext::No, ExitPipelineMode::Normal); - } - - self.notify_history_changed(change.top_level_browsing_context_id); - } - } - - if let Some(top_level_id) = top_level_id { - self.trim_history(top_level_id); - } - - self.update_frame_tree_if_active(change.top_level_browsing_context_id); - } - - fn trim_history(&mut self, top_level_browsing_context_id: TopLevelBrowsingContextId) { - let pipelines_to_evict = { - let session_history = self.joint_session_histories.entry(top_level_browsing_context_id) - .or_insert(JointSessionHistory::new()); - - let history_length = PREFS.get("session-history.max-length").as_u64().unwrap_or(20) as usize; - - // The past is stored with older entries at the front. - // We reverse the iter so that newer entries are at the front and then - // skip _n_ entries and evict the remaining entries. - let mut pipelines_to_evict = session_history.past.iter().rev() - .map(|diff| diff.alive_old_pipeline()) - .skip(history_length) - .filter_map(|maybe_pipeline| maybe_pipeline) - .collect::>(); - - // The future is stored with oldest entries front, so we must - // reverse the iterator like we do for the `past`. - pipelines_to_evict.extend(session_history.future.iter().rev() - .map(|diff| diff.alive_new_pipeline()) - .skip(history_length) - .filter_map(|maybe_pipeline| maybe_pipeline)); - - pipelines_to_evict - }; - - let mut dead_pipelines = vec![]; - for evicted_id in pipelines_to_evict { - let load_data = match self.pipelines.get(&evicted_id) { - Some(pipeline) => pipeline.load_data.clone(), - None => continue, - }; - - dead_pipelines.push((evicted_id, NeedsToReload::Yes(evicted_id, load_data))); - self.close_pipeline(evicted_id, DiscardBrowsingContext::No, ExitPipelineMode::Normal); - } - - let session_history = self.joint_session_histories.entry(top_level_browsing_context_id) - .or_insert(JointSessionHistory::new()); - - for (alive_id, dead) in dead_pipelines { - session_history.replace(NeedsToReload::No(alive_id), dead); - } - } - - fn handle_activate_document_msg(&mut self, pipeline_id: PipelineId) { - debug!("Document ready to activate {}", pipeline_id); - - // Notify the parent (if there is one). - if let Some(pipeline) = self.pipelines.get(&pipeline_id) { - if let Some(parent_pipeline_id) = pipeline.parent_info { - if let Some(parent_pipeline) = self.pipelines.get(&parent_pipeline_id) { - let msg = ConstellationControlMsg::UpdatePipelineId(parent_pipeline_id, - pipeline.browsing_context_id, pipeline_id, UpdatePipelineIdReason::Navigation); - let _ = parent_pipeline.event_loop.send(msg); - } - } - } - - // Find the pending change whose new pipeline id is pipeline_id. - let pending_index = self.pending_changes.iter().rposition(|change| { - change.new_pipeline_id == pipeline_id - }); - - // If it is found, remove it from the pending changes, and make it - // the active document of its frame. - if let Some(pending_index) = pending_index { - let change = self.pending_changes.swap_remove(pending_index); - self.change_session_history(change); - } - } - - /// Called when the window is resized. - fn handle_window_size_msg(&mut self, - top_level_browsing_context_id: Option, - new_size: WindowSizeData, - size_type: WindowSizeType) - { - debug!("handle_window_size_msg: {:?}", new_size.initial_viewport.to_untyped()); - - if let Some(top_level_browsing_context_id) = top_level_browsing_context_id { - let browsing_context_id = BrowsingContextId::from(top_level_browsing_context_id); - self.resize_browsing_context(new_size, size_type, browsing_context_id); - } - - if let Some(resize_channel) = self.webdriver.resize_channel.take() { - let _ = resize_channel.send(new_size); - } - - self.window_size = new_size; - } - - /// Handle updating actual viewport / zoom due to @viewport rules - fn handle_viewport_constrained_msg(&mut self, - pipeline_id: PipelineId, - constraints: ViewportConstraints) { - self.compositor_proxy.send(ToCompositorMsg::ViewportConstrained(pipeline_id, constraints)); - } - - /// Checks the state of all script and layout pipelines to see if they are idle - /// and compares the current layout state to what the compositor has. This is used - /// to check if the output image is "stable" and can be written as a screenshot - /// for reftests. - /// Since this function is only used in reftests, we do not harden it against panic. - fn handle_is_ready_to_save_image(&mut self, pipeline_states: HashMap) -> ReadyToSave { - // Note that this function can panic, due to ipc-channel creation failure. - // avoiding this panic would require a mechanism for dealing - // with low-resource scenarios. - // - // If there is no focus browsing context yet, the initial page has - // not loaded, so there is nothing to save yet. - let top_level_browsing_context_id = self.focus_pipeline_id - .and_then(|pipeline_id| self.pipelines.get(&pipeline_id)) - .map(|pipeline| pipeline.top_level_browsing_context_id); - let top_level_browsing_context_id = match top_level_browsing_context_id { - Some(id) => id, - None => return ReadyToSave::NoTopLevelBrowsingContext, - }; - - // If there are pending loads, wait for those to complete. - if !self.pending_changes.is_empty() { - return ReadyToSave::PendingChanges; - } - - let (state_sender, state_receiver) = ipc::channel().expect("Failed to create IPC channel!"); - let (epoch_sender, epoch_receiver) = ipc::channel().expect("Failed to create IPC channel!"); - - // Step through the fully active browsing contexts, checking that the script - // thread is idle, and that the current epoch of the layout thread - // matches what the compositor has painted. If all these conditions - // are met, then the output image should not change and a reftest - // screenshot can safely be written. - for browsing_context in self.fully_active_browsing_contexts_iter(top_level_browsing_context_id) { - let pipeline_id = browsing_context.pipeline_id; - debug!("Checking readiness of browsing context {}, pipeline {}.", browsing_context.id, pipeline_id); - - let pipeline = match self.pipelines.get(&pipeline_id) { - None => { - warn!("Pipeline {} screenshot while closing.", pipeline_id); - continue; - }, - Some(pipeline) => pipeline, - }; - - // Check to see if there are any webfonts still loading. - // - // If GetWebFontLoadState returns false, either there are no - // webfonts loading, or there's a WebFontLoaded message waiting in - // script_chan's message queue. Therefore, we need to check this - // before we check whether the document is ready; otherwise, - // there's a race condition where a webfont has finished loading, - // but hasn't yet notified the document. - let msg = LayoutControlMsg::GetWebFontLoadState(state_sender.clone()); - if let Err(e) = pipeline.layout_chan.send(msg) { - warn!("Get web font failed ({})", e); - } - if state_receiver.recv().unwrap_or(true) { - return ReadyToSave::WebFontNotLoaded; - } - - // See if this pipeline has reached idle script state yet. - match self.document_states.get(&browsing_context.pipeline_id) { - Some(&DocumentState::Idle) => {} - Some(&DocumentState::Pending) | None => { - return ReadyToSave::DocumentLoading; - } - } - - // Check the visible rectangle for this pipeline. If the constellation has received a - // size for the pipeline, then its painting should be up to date. If the constellation - // *hasn't* received a size, it could be that the layer was hidden by script before the - // compositor discovered it, so we just don't check the layer. - if let Some(size) = browsing_context.size { - // If the rectangle for this pipeline is zero sized, it will - // never be painted. In this case, don't query the layout - // thread as it won't contribute to the final output image. - if size == TypedSize2D::zero() { - continue; - } - - // Get the epoch that the compositor has drawn for this pipeline. - let compositor_epoch = pipeline_states.get(&browsing_context.pipeline_id); - match compositor_epoch { - Some(compositor_epoch) => { - // Synchronously query the layout thread to see if the current - // epoch matches what the compositor has drawn. If they match - // (and script is idle) then this pipeline won't change again - // and can be considered stable. - let message = LayoutControlMsg::GetCurrentEpoch(epoch_sender.clone()); - if let Err(e) = pipeline.layout_chan.send(message) { - warn!("Failed to send GetCurrentEpoch ({}).", e); - } - match epoch_receiver.recv() { - Err(e) => warn!("Failed to receive current epoch ({}).", e), - Ok(layout_thread_epoch) => if layout_thread_epoch != *compositor_epoch { - return ReadyToSave::EpochMismatch; - }, - } - } - None => { - // The compositor doesn't know about this pipeline yet. - // Assume it hasn't rendered yet. - return ReadyToSave::PipelineUnknown; - } - } - } - } - - // All script threads are idle and layout epochs match compositor, so output image! - ReadyToSave::Ready - } - - /// Get the current activity of a pipeline. - fn get_activity(&self, pipeline_id: PipelineId) -> DocumentActivity { - let mut ancestor_id = pipeline_id; - loop { - if let Some(ancestor) = self.pipelines.get(&ancestor_id) { - if let Some(browsing_context) = self.browsing_contexts.get(&ancestor.browsing_context_id) { - if browsing_context.pipeline_id == ancestor_id { - if let Some(parent_id) = ancestor.parent_info { - ancestor_id = parent_id; - continue; - } else { - return DocumentActivity::FullyActive; - } - } - } - } - if pipeline_id == ancestor_id { - return DocumentActivity::Inactive; - } else { - return DocumentActivity::Active; - } - } - } - - /// Set the current activity of a pipeline. - fn set_activity(&self, pipeline_id: PipelineId, activity: DocumentActivity) { - debug!("Setting activity of {} to be {:?}.", pipeline_id, activity); - if let Some(pipeline) = self.pipelines.get(&pipeline_id) { - pipeline.set_activity(activity); - let child_activity = if activity == DocumentActivity::Inactive { - DocumentActivity::Active - } else { - activity - }; - for child_id in &pipeline.children { - if let Some(child) = self.browsing_contexts.get(child_id) { - self.set_activity(child.pipeline_id, child_activity); - } - } - } - } - - /// Update the current activity of a pipeline. - fn update_activity(&self, pipeline_id: PipelineId) { - self.set_activity(pipeline_id, self.get_activity(pipeline_id)); - } - - /// Handle updating the size of a browsing context. - /// This notifies every pipeline in the context of the new size. - fn resize_browsing_context(&mut self, - new_size: WindowSizeData, - size_type: WindowSizeType, - browsing_context_id: BrowsingContextId) - { - if let Some(browsing_context) = self.browsing_contexts.get_mut(&browsing_context_id) { - browsing_context.size = Some(new_size.initial_viewport); - } - - if let Some(browsing_context) = self.browsing_contexts.get(&browsing_context_id) { - // Send Resize (or ResizeInactive) messages to each - // pipeline in the frame tree. - let pipeline_id = browsing_context.pipeline_id; - let pipeline = match self.pipelines.get(&pipeline_id) { - None => return warn!("Pipeline {:?} resized after closing.", pipeline_id), - Some(pipeline) => pipeline, - }; - let _ = pipeline.event_loop.send(ConstellationControlMsg::Resize( - pipeline.id, - new_size, - size_type - )); - let pipelines = browsing_context.pipelines.iter() - .filter(|pipeline_id| **pipeline_id != pipeline.id) - .filter_map(|pipeline_id| self.pipelines.get(&pipeline_id)); - for pipeline in pipelines { - let _ = pipeline.event_loop.send(ConstellationControlMsg::ResizeInactive( - pipeline.id, - new_size - )); - } - } - - // Send resize message to any pending pipelines that aren't loaded yet. - for change in &self.pending_changes { - let pipeline_id = change.new_pipeline_id; - let pipeline = match self.pipelines.get(&pipeline_id) { - None => { warn!("Pending pipeline {:?} is closed", pipeline_id); continue; } - Some(pipeline) => pipeline, - }; - if pipeline.browsing_context_id == browsing_context_id { - let _ = pipeline.event_loop.send(ConstellationControlMsg::Resize( - pipeline.id, - new_size, - size_type - )); - } - } - } - - // Close a browsing context (and all children) - fn close_browsing_context(&mut self, browsing_context_id: BrowsingContextId, exit_mode: ExitPipelineMode) { - debug!("Closing browsing context {}.", browsing_context_id); - - self.close_browsing_context_children(browsing_context_id, DiscardBrowsingContext::Yes, exit_mode); - - let browsing_context = match self.browsing_contexts.remove(&browsing_context_id) { - None => return warn!("Closing browsing context {:?} twice.", browsing_context_id), - Some(browsing_context) => browsing_context, - }; - - if BrowsingContextId::from(browsing_context.top_level_id) == browsing_context_id { - self.event_loops.remove(&browsing_context.top_level_id); - } - - let parent_info = self.pipelines.get(&browsing_context.pipeline_id) - .and_then(|pipeline| pipeline.parent_info); - - if let Some(parent_pipeline_id) = parent_info { - match self.pipelines.get_mut(&parent_pipeline_id) { - None => return warn!("Pipeline {:?} child closed after parent.", parent_pipeline_id), - Some(parent_pipeline) => parent_pipeline.remove_child(browsing_context_id), - }; - } - debug!("Closed browsing context {:?}.", browsing_context_id); - } - - // Close the children of a browsing context - fn close_browsing_context_children(&mut self, - browsing_context_id: BrowsingContextId, - dbc: DiscardBrowsingContext, - exit_mode: ExitPipelineMode) - { - debug!("Closing browsing context children {}.", browsing_context_id); - // Store information about the pipelines to be closed. Then close the - // pipelines, before removing ourself from the browsing_contexts hash map. This - // ordering is vital - so that if close_pipeline() ends up closing - // any child browsing contexts, they can be removed from the parent browsing context correctly. - let mut pipelines_to_close: Vec = self.pending_changes.iter() - .filter(|change| change.browsing_context_id == browsing_context_id) - .map(|change| change.new_pipeline_id) - .collect(); - - if let Some(browsing_context) = self.browsing_contexts.get(&browsing_context_id) { - pipelines_to_close.extend(&browsing_context.pipelines) - } - - for pipeline_id in pipelines_to_close { - self.close_pipeline(pipeline_id, dbc, exit_mode); - } - - debug!("Closed browsing context children {}.", browsing_context_id); - } - - // Close all pipelines at and beneath a given browsing context - fn close_pipeline(&mut self, pipeline_id: PipelineId, dbc: DiscardBrowsingContext, exit_mode: ExitPipelineMode) { - debug!("Closing pipeline {:?}.", pipeline_id); - - // Sever connection to browsing context - let browsing_context_id = self.pipelines.get(&pipeline_id).map(|pipeline| pipeline.browsing_context_id); - if let Some(browsing_context) = browsing_context_id - .and_then(|browsing_context_id| self.browsing_contexts.get_mut(&browsing_context_id)) - { - browsing_context.pipelines.remove(&pipeline_id); - } - - // Store information about the browsing contexts to be closed. Then close the - // browsing contexts, before removing ourself from the pipelines hash map. This - // ordering is vital - so that if close_browsing_context() ends up closing - // any child pipelines, they can be removed from the parent pipeline correctly. - let browsing_contexts_to_close = { - let mut browsing_contexts_to_close = vec!(); - - if let Some(pipeline) = self.pipelines.get(&pipeline_id) { - browsing_contexts_to_close.extend_from_slice(&pipeline.children); - } - - browsing_contexts_to_close - }; - - // Remove any child browsing contexts - for child_browsing_context in &browsing_contexts_to_close { - self.close_browsing_context(*child_browsing_context, exit_mode); - } - - // Note, we don't remove the pipeline now, we wait for the message to come back from - // the pipeline. - let pipeline = match self.pipelines.get(&pipeline_id) { - Some(pipeline) => pipeline, - None => return warn!("Closing pipeline {:?} twice.", pipeline_id), - }; - - // Remove this pipeline from pending changes if it hasn't loaded yet. - let pending_index = self.pending_changes.iter().position(|change| { - change.new_pipeline_id == pipeline_id - }); - if let Some(pending_index) = pending_index { - self.pending_changes.remove(pending_index); - } - - // Inform script, compositor that this pipeline has exited. - match exit_mode { - ExitPipelineMode::Normal => pipeline.exit(dbc), - ExitPipelineMode::Force => pipeline.force_exit(dbc), - } - debug!("Closed pipeline {:?}.", pipeline_id); - } - - // Randomly close a pipeline -if --random-pipeline-closure-probability is set - fn maybe_close_random_pipeline(&mut self) { - match self.random_pipeline_closure { - Some((ref mut rng, probability)) => if probability <= rng.gen::() { return }, - _ => return, - }; - // In order to get repeatability, we sort the pipeline ids. - let mut pipeline_ids: Vec<&PipelineId> = self.pipelines.keys().collect(); - pipeline_ids.sort(); - if let Some((ref mut rng, probability)) = self.random_pipeline_closure { - if let Some(pipeline_id) = rng.choose(&*pipeline_ids) { - if let Some(pipeline) = self.pipelines.get(pipeline_id) { - if self.pending_changes.iter().any(|change| change.new_pipeline_id == pipeline.id) && - probability <= rng.gen::() { - // We tend not to close pending pipelines, as that almost always - // results in pipelines being closed early in their lifecycle, - // and not stressing the constellation as much. - // https://github.com/servo/servo/issues/18852 - info!("Not closing pending pipeline {}.", pipeline_id); - } else { - // Note that we deliberately do not do any of the tidying up - // associated with closing a pipeline. The constellation should cope! - warn!("Randomly closing pipeline {}.", pipeline_id); - pipeline.force_exit(DiscardBrowsingContext::No); - } - } - } - } - } - - // Convert a browsing context to a sendable form to pass to the compositor - fn browsing_context_to_sendable(&self, browsing_context_id: BrowsingContextId) -> Option { - self.browsing_contexts.get(&browsing_context_id).and_then(|browsing_context| { - self.pipelines.get(&browsing_context.pipeline_id).map(|pipeline| { - let mut frame_tree = SendableFrameTree { - pipeline: pipeline.to_sendable(), - size: browsing_context.size, - children: vec!(), - }; - - for child_browsing_context_id in &pipeline.children { - if let Some(child) = self.browsing_context_to_sendable(*child_browsing_context_id) { - frame_tree.children.push(child); - } - } - - frame_tree - }) - }) - } - - /// Re-send the frame tree to the compositor. - fn update_frame_tree_if_active(&mut self, top_level_browsing_context_id: TopLevelBrowsingContextId) { - // Only send the frame tree if it's the active one or if no frame tree - // has been sent yet. - if self.active_browser_id.is_none() || Some(top_level_browsing_context_id) == self.active_browser_id { - self.send_frame_tree(top_level_browsing_context_id); - } - - } - - /// Send the current frame tree to compositor - fn send_frame_tree(&mut self, top_level_browsing_context_id: TopLevelBrowsingContextId) { - self.active_browser_id = Some(top_level_browsing_context_id); - let browsing_context_id = BrowsingContextId::from(top_level_browsing_context_id); - - // Note that this function can panic, due to ipc-channel creation failure. - // avoiding this panic would require a mechanism for dealing - // with low-resource scenarios. - debug!("Sending frame tree for browsing context {}.", browsing_context_id); - if let Some(frame_tree) = self.browsing_context_to_sendable(browsing_context_id) { - self.compositor_proxy.send(ToCompositorMsg::SetFrameTree(frame_tree)); - } - } - - fn focused_pipeline_is_descendant_of(&self, browsing_context_id: BrowsingContextId) -> bool { - self.focus_pipeline_id.map_or(false, |pipeline_id| { - self.fully_active_descendant_browsing_contexts_iter(browsing_context_id) - .any(|browsing_context| browsing_context.pipeline_id == pipeline_id) - }) - } -} diff --git a/servo/components/constellation/event_loop.rs b/servo/components/constellation/event_loop.rs deleted file mode 100644 index 8d611144bce5..000000000000 --- a/servo/components/constellation/event_loop.rs +++ /dev/null @@ -1,46 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -//! This module contains the `EventLoop` type, which is the constellation's -//! view of a script thread. When an `EventLoop` is dropped, an `ExitScriptThread` -//! message is sent to the script thread, asking it to shut down. - -use ipc_channel::Error; -use ipc_channel::ipc::IpcSender; -use script_traits::ConstellationControlMsg; -use std::marker::PhantomData; -use std::rc::Rc; - -/// -pub struct EventLoop { - script_chan: IpcSender, - dont_send_or_sync: PhantomData>, -} - -impl Drop for EventLoop { - fn drop(&mut self) { - let _ = self.script_chan.send(ConstellationControlMsg::ExitScriptThread); - } -} - -impl EventLoop { - /// Create a new event loop from the channel to its script thread. - pub fn new(script_chan: IpcSender) -> Rc { - Rc::new(EventLoop { - script_chan: script_chan, - dont_send_or_sync: PhantomData, - }) - } - - /// Send a message to the event loop. - pub fn send(&self, msg: ConstellationControlMsg) -> Result<(), Error> { - self.script_chan.send(msg) - } - - /// The underlying channel to the script thread. - pub fn sender(&self) -> IpcSender { - self.script_chan.clone() - } -} - diff --git a/servo/components/constellation/lib.rs b/servo/components/constellation/lib.rs deleted file mode 100644 index 6ae9837e95fe..000000000000 --- a/servo/components/constellation/lib.rs +++ /dev/null @@ -1,55 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -#![deny(unsafe_code)] -#![cfg_attr(feature = "unstable", feature(conservative_impl_trait))] -#![feature(mpsc_select)] - -extern crate backtrace; -extern crate bluetooth_traits; -extern crate canvas; -extern crate canvas_traits; -extern crate clipboard; -extern crate compositing; -extern crate debugger; -extern crate devtools_traits; -extern crate euclid; -#[cfg(all(not(target_os = "windows"), not(target_os = "ios")))] -extern crate gaol; -extern crate gfx; -extern crate gfx_traits; -extern crate hyper; -extern crate ipc_channel; -extern crate layout_traits; -#[macro_use] -extern crate log; -extern crate metrics; -extern crate msg; -extern crate net; -extern crate net_traits; -extern crate profile_traits; -extern crate script_traits; -#[macro_use] extern crate serde; -extern crate servo_config; -extern crate servo_rand; -extern crate servo_remutex; -extern crate servo_url; -extern crate style_traits; -extern crate webrender_api; -extern crate webvr_traits; - -mod browsingcontext; -mod constellation; -mod event_loop; -mod network_listener; -mod pipeline; -#[cfg(all(not(target_os = "windows"), not(target_os = "ios")))] -mod sandboxing; -mod session_history; -mod timer_scheduler; - -pub use constellation::{Constellation, FromCompositorLogger, FromScriptLogger, InitialConstellationState}; -pub use pipeline::UnprivilegedPipelineContent; -#[cfg(all(not(target_os = "windows"), not(target_os = "ios")))] -pub use sandboxing::content_process_sandbox_profile; diff --git a/servo/components/constellation/network_listener.rs b/servo/components/constellation/network_listener.rs deleted file mode 100644 index a6adf9a4c5c0..000000000000 --- a/servo/components/constellation/network_listener.rs +++ /dev/null @@ -1,138 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -//! The listener that encapsulates all state for an in-progress document request. -//! Any redirects that are encountered are followed. Whenever a non-redirect -//! response is received, it is forwarded to the appropriate script thread. - -use hyper::header::Location; -use ipc_channel::ipc; -use ipc_channel::router::ROUTER; -use msg::constellation_msg::PipelineId; -use net::http_loader::{set_default_accept, set_default_accept_language}; -use net_traits::{CoreResourceMsg, FetchChannels, FetchMetadata, FetchResponseMsg}; -use net_traits::{IpcSend, NetworkError, ResourceThreads}; -use net_traits::request::{Destination, RequestInit}; -use net_traits::response::ResponseInit; -use std::sync::mpsc::Sender; - -pub struct NetworkListener { - res_init: Option, - req_init: RequestInit, - pipeline_id: PipelineId, - resource_threads: ResourceThreads, - sender: Sender<(PipelineId, FetchResponseMsg)>, - should_send: bool, -} - -impl NetworkListener { - pub fn new(req_init: RequestInit, - pipeline_id: PipelineId, - resource_threads: ResourceThreads, - sender: Sender<(PipelineId, FetchResponseMsg)>) -> NetworkListener { - NetworkListener { - res_init: None, - req_init, - pipeline_id, - resource_threads, - sender, - should_send: false - } - } - - pub fn initiate_fetch(&self, cancel_chan: Option>) { - let (ipc_sender, ipc_receiver) = ipc::channel().expect("Failed to create IPC channel!"); - - let mut listener = NetworkListener { - res_init: self.res_init.clone(), - req_init: self.req_init.clone(), - resource_threads: self.resource_threads.clone(), - sender: self.sender.clone(), - pipeline_id: self.pipeline_id.clone(), - should_send: false, - }; - - let msg = match self.res_init { - Some(ref res_init_) => CoreResourceMsg::FetchRedirect( - self.req_init.clone(), - res_init_.clone(), - ipc_sender, None), - None => { - set_default_accept(Destination::Document, &mut listener.req_init.headers); - set_default_accept_language(&mut listener.req_init.headers); - - CoreResourceMsg::Fetch( - listener.req_init.clone(), - FetchChannels::ResponseMsg(ipc_sender, cancel_chan)) - } - }; - - ROUTER.add_route(ipc_receiver.to_opaque(), Box::new(move |message| { - let msg = message.to(); - match msg { - Ok(FetchResponseMsg::ProcessResponse(res)) => listener.check_redirect(res), - Ok(msg_) => listener.send(msg_), - Err(e) => warn!("Error while receiving network listener message: {}", e), - }; - })); - - if let Err(e) = self.resource_threads.sender().send(msg) { - warn!("Resource thread unavailable ({})", e); - } - } - - fn check_redirect(&mut self, - message: Result<(FetchMetadata), NetworkError>) { - match message { - Ok(res_metadata) => { - let metadata = match res_metadata { - FetchMetadata::Filtered { ref unsafe_, .. } => unsafe_, - FetchMetadata::Unfiltered(ref m) => m, - }; - - match metadata.headers { - Some(ref headers) if headers.has::() => { - if self.req_init.url_list.is_empty() { - self.req_init.url_list.push(self.req_init.url.clone()); - } - self.req_init.url_list.push(metadata.final_url.clone()); - - self.req_init.referrer_url = metadata.referrer.clone(); - self.req_init.referrer_policy = metadata.referrer_policy; - - self.res_init = Some(ResponseInit { - url: metadata.final_url.clone(), - location_url: metadata.location_url.clone(), - headers: headers.clone().into_inner(), - referrer: metadata.referrer.clone(), - }); - - // XXXManishearth we don't have the cancel_chan anymore and - // can't use it here. - // - // Ideally the Fetch code would handle manual redirects on its own - self.initiate_fetch(None); - }, - _ => { - // Response should be processed by script thread. - self.should_send = true; - self.send(FetchResponseMsg::ProcessResponse(Ok(res_metadata.clone()))); - } - }; - }, - Err(e) => { - self.should_send = true; - self.send(FetchResponseMsg::ProcessResponse(Err(e))) - } - }; - } - - fn send(&mut self, msg: FetchResponseMsg) { - if self.should_send { - if let Err(e) = self.sender.send((self.pipeline_id, msg)) { - warn!("Failed to forward network message to pipeline {}: {:?}", self.pipeline_id, e); - } - } - } -} diff --git a/servo/components/constellation/pipeline.rs b/servo/components/constellation/pipeline.rs deleted file mode 100644 index 0e54e6649ba1..000000000000 --- a/servo/components/constellation/pipeline.rs +++ /dev/null @@ -1,639 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -use bluetooth_traits::BluetoothRequest; -use canvas_traits::webgl::WebGLPipeline; -use compositing::CompositionPipeline; -use compositing::CompositorProxy; -use compositing::compositor_thread::Msg as CompositorMsg; -use devtools_traits::{DevtoolsControlMsg, ScriptToDevtoolsControlMsg}; -use euclid::{TypedSize2D, TypedScale}; -use event_loop::EventLoop; -use gfx::font_cache_thread::FontCacheThread; -use ipc_channel::Error; -use ipc_channel::ipc::{self, IpcReceiver, IpcSender}; -use ipc_channel::router::ROUTER; -use layout_traits::LayoutThreadFactory; -use metrics::PaintTimeMetrics; -use msg::constellation_msg::{BrowsingContextId, TopLevelBrowsingContextId, PipelineId, PipelineNamespaceId}; -use net::image_cache::ImageCacheImpl; -use net_traits::{IpcSend, ResourceThreads}; -use net_traits::image_cache::ImageCache; -use profile_traits::mem as profile_mem; -use profile_traits::time; -use script_traits::{ConstellationControlMsg, DiscardBrowsingContext, ScriptToConstellationChan}; -use script_traits::{DocumentActivity, InitialScriptState}; -use script_traits::{LayoutControlMsg, LayoutMsg, LoadData}; -use script_traits::{NewLayoutInfo, SWManagerMsg, SWManagerSenders}; -use script_traits::{ScriptThreadFactory, TimerSchedulerMsg, WindowSizeData}; -use servo_config::opts::{self, Opts}; -use servo_config::prefs::{PREFS, Pref}; -use servo_url::ServoUrl; -use std::collections::HashMap; -#[cfg(not(windows))] -use std::env; -use std::ffi::OsStr; -use std::process; -use std::rc::Rc; -use std::sync::Arc; -use std::sync::mpsc::Sender; -use style_traits::CSSPixel; -use style_traits::DevicePixel; -use webrender_api; -use webvr_traits::WebVRMsg; - -/// A `Pipeline` is the constellation's view of a `Document`. Each pipeline has an -/// event loop (executed by a script thread) and a layout thread. A script thread -/// may be responsible for many pipelines, but a layout thread is only responsible -/// for one. -pub struct Pipeline { - /// The ID of the pipeline. - pub id: PipelineId, - - /// The ID of the browsing context that contains this Pipeline. - pub browsing_context_id: BrowsingContextId, - - /// The ID of the top-level browsing context that contains this Pipeline. - pub top_level_browsing_context_id: TopLevelBrowsingContextId, - - /// The parent pipeline of this one. `None` if this is a root pipeline. - /// TODO: move this field to `BrowsingContext`. - pub parent_info: Option, - - /// The event loop handling this pipeline. - pub event_loop: Rc, - - /// A channel to layout, for performing reflows and shutdown. - pub layout_chan: IpcSender, - - /// A channel to the compositor. - pub compositor_proxy: CompositorProxy, - - /// The most recently loaded URL in this pipeline. - /// Note that this URL can change, for example if the page navigates - /// to a hash URL. - pub url: ServoUrl, - - /// Whether this pipeline is currently running animations. Pipelines that are running - /// animations cause composites to be continually scheduled. - pub running_animations: bool, - - /// The child browsing contexts of this pipeline (these are iframes in the document). - pub children: Vec, - - /// Whether this pipeline is in private browsing mode. - /// TODO: move this field to `BrowsingContext`. - pub is_private: bool, - - /// Whether this pipeline should be treated as visible for the purposes of scheduling and - /// resource management. - pub visible: bool, - - /// The Load Data used to create this pipeline. - pub load_data: LoadData, -} - -/// Initial setup data needed to construct a pipeline. -/// -/// *DO NOT* add any Senders to this unless you absolutely know what you're doing, or pcwalton will -/// have to rewrite your code. Use IPC senders instead. -pub struct InitialPipelineState { - /// The ID of the pipeline to create. - pub id: PipelineId, - - /// The ID of the browsing context that contains this Pipeline. - pub browsing_context_id: BrowsingContextId, - - /// The ID of the top-level browsing context that contains this Pipeline. - pub top_level_browsing_context_id: TopLevelBrowsingContextId, - - /// The ID of the parent pipeline and frame type, if any. - /// If `None`, this is the root. - pub parent_info: Option, - - /// A channel to the associated constellation. - pub script_to_constellation_chan: ScriptToConstellationChan, - - /// A channel for the layout thread to send messages to the constellation. - pub layout_to_constellation_chan: IpcSender, - - /// A channel to schedule timer events. - pub scheduler_chan: IpcSender, - - /// A channel to the compositor. - pub compositor_proxy: CompositorProxy, - - /// A channel to the developer tools, if applicable. - pub devtools_chan: Option>, - - /// A channel to the bluetooth thread. - pub bluetooth_thread: IpcSender, - - /// A channel to the service worker manager thread - pub swmanager_thread: IpcSender, - - /// A channel to the font cache thread. - pub font_cache_thread: FontCacheThread, - - /// Channels to the resource-related threads. - pub resource_threads: ResourceThreads, - - /// A channel to the time profiler thread. - pub time_profiler_chan: time::ProfilerChan, - - /// A channel to the memory profiler thread. - pub mem_profiler_chan: profile_mem::ProfilerChan, - - /// Information about the initial window size. - pub window_size: Option>, - - /// Information about the device pixel ratio. - pub device_pixel_ratio: TypedScale, - - /// The event loop to run in, if applicable. - pub event_loop: Option>, - - /// Information about the page to load. - pub load_data: LoadData, - - - /// The ID of the pipeline namespace for this script thread. - pub pipeline_namespace_id: PipelineNamespaceId, - - /// Pipeline visibility to be inherited - pub prev_visibility: Option, - - /// Webrender api. - pub webrender_api_sender: webrender_api::RenderApiSender, - - /// The ID of the document processed by this script thread. - pub webrender_document: webrender_api::DocumentId, - - /// Whether this pipeline is considered private. - pub is_private: bool, - - /// A channel to the WebGL thread. - pub webgl_chan: Option, - - /// A channel to the webvr thread. - pub webvr_chan: Option>, -} - -impl Pipeline { - /// Starts a layout thread, and possibly a script thread, in - /// a new process if requested. - pub fn spawn(state: InitialPipelineState) -> Result - where LTF: LayoutThreadFactory, - STF: ScriptThreadFactory - { - // Note: we allow channel creation to panic, since recovering from this - // probably requires a general low-memory strategy. - let (pipeline_chan, pipeline_port) = ipc::channel() - .expect("Pipeline main chan"); - - let (layout_content_process_shutdown_chan, layout_content_process_shutdown_port) = - ipc::channel().expect("Pipeline layout content shutdown chan"); - - let device_pixel_ratio = state.device_pixel_ratio; - let window_size = state.window_size.map(|size| { - WindowSizeData { - initial_viewport: size, - device_pixel_ratio: device_pixel_ratio, - } - }); - - let url = state.load_data.url.clone(); - - let script_chan = match state.event_loop { - Some(script_chan) => { - let new_layout_info = NewLayoutInfo { - parent_info: state.parent_info, - new_pipeline_id: state.id, - browsing_context_id: state.browsing_context_id, - top_level_browsing_context_id: state.top_level_browsing_context_id, - load_data: state.load_data.clone(), - window_size: window_size, - pipeline_port: pipeline_port, - content_process_shutdown_chan: Some(layout_content_process_shutdown_chan.clone()), - layout_threads: PREFS.get("layout.threads").as_u64().expect("count") as usize, - }; - - if let Err(e) = script_chan.send(ConstellationControlMsg::AttachLayout(new_layout_info)) { - warn!("Sending to script during pipeline creation failed ({})", e); - } - script_chan - } - None => { - let (script_chan, script_port) = ipc::channel().expect("Pipeline script chan"); - - // Route messages coming from content to devtools as appropriate. - let script_to_devtools_chan = state.devtools_chan.as_ref().map(|devtools_chan| { - let (script_to_devtools_chan, script_to_devtools_port) = ipc::channel() - .expect("Pipeline script to devtools chan"); - let devtools_chan = (*devtools_chan).clone(); - ROUTER.add_route(script_to_devtools_port.to_opaque(), Box::new(move |message| { - match message.to::() { - Err(e) => error!("Cast to ScriptToDevtoolsControlMsg failed ({}).", e), - Ok(message) => if let Err(e) = devtools_chan.send(DevtoolsControlMsg::FromScript(message)) { - warn!("Sending to devtools failed ({})", e) - }, - } - })); - script_to_devtools_chan - }); - - let (script_content_process_shutdown_chan, script_content_process_shutdown_port) = - ipc::channel().expect("Pipeline script content process shutdown chan"); - - let unprivileged_pipeline_content = UnprivilegedPipelineContent { - id: state.id, - browsing_context_id: state.browsing_context_id, - top_level_browsing_context_id: state.top_level_browsing_context_id, - parent_info: state.parent_info, - script_to_constellation_chan: state.script_to_constellation_chan.clone(), - scheduler_chan: state.scheduler_chan, - devtools_chan: script_to_devtools_chan, - bluetooth_thread: state.bluetooth_thread, - swmanager_thread: state.swmanager_thread, - font_cache_thread: state.font_cache_thread, - resource_threads: state.resource_threads, - time_profiler_chan: state.time_profiler_chan, - mem_profiler_chan: state.mem_profiler_chan, - window_size: window_size, - layout_to_constellation_chan: state.layout_to_constellation_chan, - script_chan: script_chan.clone(), - load_data: state.load_data.clone(), - script_port: script_port, - opts: (*opts::get()).clone(), - prefs: PREFS.cloned(), - pipeline_port: pipeline_port, - pipeline_namespace_id: state.pipeline_namespace_id, - layout_content_process_shutdown_chan: layout_content_process_shutdown_chan, - layout_content_process_shutdown_port: layout_content_process_shutdown_port, - script_content_process_shutdown_chan: script_content_process_shutdown_chan, - script_content_process_shutdown_port: script_content_process_shutdown_port, - webrender_api_sender: state.webrender_api_sender, - webrender_document: state.webrender_document, - webgl_chan: state.webgl_chan, - webvr_chan: state.webvr_chan, - }; - - // Spawn the child process. - // - // Yes, that's all there is to it! - if opts::multiprocess() { - let _ = unprivileged_pipeline_content.spawn_multiprocess()?; - } else { - unprivileged_pipeline_content.start_all::(false); - } - - EventLoop::new(script_chan) - } - }; - - Ok(Pipeline::new(state.id, - state.browsing_context_id, - state.top_level_browsing_context_id, - state.parent_info, - script_chan, - pipeline_chan, - state.compositor_proxy, - state.is_private, - url, - state.prev_visibility.unwrap_or(true), - state.load_data)) - } - - /// Creates a new `Pipeline`, after the script and layout threads have been - /// spawned. - pub fn new(id: PipelineId, - browsing_context_id: BrowsingContextId, - top_level_browsing_context_id: TopLevelBrowsingContextId, - parent_info: Option, - event_loop: Rc, - layout_chan: IpcSender, - compositor_proxy: CompositorProxy, - is_private: bool, - url: ServoUrl, - visible: bool, - load_data: LoadData) - -> Pipeline { - let pipeline = Pipeline { - id: id, - browsing_context_id: browsing_context_id, - top_level_browsing_context_id: top_level_browsing_context_id, - parent_info: parent_info, - event_loop: event_loop, - layout_chan: layout_chan, - compositor_proxy: compositor_proxy, - url: url, - children: vec!(), - running_animations: false, - visible: visible, - is_private: is_private, - load_data: load_data, - }; - - pipeline.notify_visibility(); - - pipeline - } - - /// A normal exit of the pipeline, which waits for the compositor, - /// and delegates layout shutdown to the script thread. - pub fn exit(&self, discard_bc: DiscardBrowsingContext) { - debug!("pipeline {:?} exiting", self.id); - - // The compositor wants to know when pipelines shut down too. - // It may still have messages to process from these other threads - // before they can be safely shut down. - // It's OK for the constellation to block on the compositor, - // since the compositor never blocks on the constellation. - if let Ok((sender, receiver)) = ipc::channel() { - self.compositor_proxy.send(CompositorMsg::PipelineExited(self.id, sender)); - if let Err(e) = receiver.recv() { - warn!("Sending exit message failed ({}).", e); - } - } - - // Script thread handles shutting down layout, and layout handles shutting down the painter. - // For now, if the script thread has failed, we give up on clean shutdown. - let msg = ConstellationControlMsg::ExitPipeline(self.id, discard_bc); - if let Err(e) = self.event_loop.send(msg) { - warn!("Sending script exit message failed ({}).", e); - } - } - - /// A forced exit of the shutdown, which does not wait for the compositor, - /// or for the script thread to shut down layout. - pub fn force_exit(&self, discard_bc: DiscardBrowsingContext) { - let msg = ConstellationControlMsg::ExitPipeline(self.id, discard_bc); - if let Err(e) = self.event_loop.send(msg) { - warn!("Sending script exit message failed ({}).", e); - } - if let Err(e) = self.layout_chan.send(LayoutControlMsg::ExitNow) { - warn!("Sending layout exit message failed ({}).", e); - } - } - - /// Notify this pipeline of its activity. - pub fn set_activity(&self, activity: DocumentActivity) { - let msg = ConstellationControlMsg::SetDocumentActivity(self.id, activity); - if let Err(e) = self.event_loop.send(msg) { - warn!("Sending activity message failed ({}).", e); - } - } - - /// The compositor's view of a pipeline. - pub fn to_sendable(&self) -> CompositionPipeline { - CompositionPipeline { - id: self.id.clone(), - top_level_browsing_context_id: self.top_level_browsing_context_id.clone(), - script_chan: self.event_loop.sender(), - layout_chan: self.layout_chan.clone(), - } - } - - /// Add a new child browsing context. - pub fn add_child(&mut self, browsing_context_id: BrowsingContextId) { - self.children.push(browsing_context_id); - } - - /// Remove a child browsing context. - pub fn remove_child(&mut self, browsing_context_id: BrowsingContextId) { - match self.children.iter().position(|id| *id == browsing_context_id) { - None => return warn!("Pipeline remove child already removed ({:?}).", browsing_context_id), - Some(index) => self.children.remove(index), - }; - } - - /// Notify the script thread that this pipeline is visible. - fn notify_visibility(&self) { - let script_msg = ConstellationControlMsg::ChangeFrameVisibilityStatus(self.id, self.visible); - let compositor_msg = CompositorMsg::PipelineVisibilityChanged(self.id, self.visible); - let err = self.event_loop.send(script_msg); - if let Err(e) = err { - warn!("Sending visibility change failed ({}).", e); - } - self.compositor_proxy.send(compositor_msg); - } - - /// Change the visibility of this pipeline. - pub fn change_visibility(&mut self, visible: bool) { - if visible == self.visible { - return; - } - self.visible = visible; - self.notify_visibility(); - } - -} - -/// Creating a new pipeline may require creating a new event loop. -/// This is the data used to initialize the event loop. -/// TODO: simplify this, and unify it with `InitialPipelineState` if possible. -#[derive(Deserialize, Serialize)] -pub struct UnprivilegedPipelineContent { - id: PipelineId, - top_level_browsing_context_id: TopLevelBrowsingContextId, - browsing_context_id: BrowsingContextId, - parent_info: Option, - script_to_constellation_chan: ScriptToConstellationChan, - layout_to_constellation_chan: IpcSender, - scheduler_chan: IpcSender, - devtools_chan: Option>, - bluetooth_thread: IpcSender, - swmanager_thread: IpcSender, - font_cache_thread: FontCacheThread, - resource_threads: ResourceThreads, - time_profiler_chan: time::ProfilerChan, - mem_profiler_chan: profile_mem::ProfilerChan, - window_size: Option, - script_chan: IpcSender, - load_data: LoadData, - script_port: IpcReceiver, - opts: Opts, - prefs: HashMap, - pipeline_port: IpcReceiver, - pipeline_namespace_id: PipelineNamespaceId, - layout_content_process_shutdown_chan: IpcSender<()>, - layout_content_process_shutdown_port: IpcReceiver<()>, - script_content_process_shutdown_chan: IpcSender<()>, - script_content_process_shutdown_port: IpcReceiver<()>, - webrender_api_sender: webrender_api::RenderApiSender, - webrender_document: webrender_api::DocumentId, - webgl_chan: Option, - webvr_chan: Option>, -} - -impl UnprivilegedPipelineContent { - pub fn start_all(self, wait_for_completion: bool) - where LTF: LayoutThreadFactory, - STF: ScriptThreadFactory - { - let image_cache = Arc::new(ImageCacheImpl::new(self.webrender_api_sender.create_api())); - let paint_time_metrics = PaintTimeMetrics::new(self.id, - self.time_profiler_chan.clone(), - self.layout_to_constellation_chan.clone(), - self.script_chan.clone(), - self.load_data.url.clone()); - let layout_pair = STF::create(InitialScriptState { - id: self.id, - browsing_context_id: self.browsing_context_id, - top_level_browsing_context_id: self.top_level_browsing_context_id, - parent_info: self.parent_info, - control_chan: self.script_chan.clone(), - control_port: self.script_port, - script_to_constellation_chan: self.script_to_constellation_chan.clone(), - layout_to_constellation_chan: self.layout_to_constellation_chan.clone(), - scheduler_chan: self.scheduler_chan, - bluetooth_thread: self.bluetooth_thread, - resource_threads: self.resource_threads, - image_cache: image_cache.clone(), - time_profiler_chan: self.time_profiler_chan.clone(), - mem_profiler_chan: self.mem_profiler_chan.clone(), - devtools_chan: self.devtools_chan, - window_size: self.window_size, - pipeline_namespace_id: self.pipeline_namespace_id, - content_process_shutdown_chan: self.script_content_process_shutdown_chan, - webgl_chan: self.webgl_chan, - webvr_chan: self.webvr_chan, - webrender_document: self.webrender_document, - }, self.load_data.clone()); - - LTF::create(self.id, - self.top_level_browsing_context_id, - self.load_data.url, - self.parent_info.is_some(), - layout_pair, - self.pipeline_port, - self.layout_to_constellation_chan, - self.script_chan, - image_cache.clone(), - self.font_cache_thread, - self.time_profiler_chan, - self.mem_profiler_chan, - Some(self.layout_content_process_shutdown_chan), - self.webrender_api_sender, - self.webrender_document, - self.prefs.get("layout.threads").expect("exists").value() - .as_u64().expect("count") as usize, - paint_time_metrics); - - if wait_for_completion { - let _ = self.script_content_process_shutdown_port.recv(); - let _ = self.layout_content_process_shutdown_port.recv(); - } - } - - #[cfg(all(not(target_os = "windows"), not(target_os = "ios")))] - pub fn spawn_multiprocess(self) -> Result<(), Error> { - use gaol::sandbox::{self, Sandbox, SandboxMethods}; - use ipc_channel::ipc::IpcOneShotServer; - use sandboxing::content_process_sandbox_profile; - - impl CommandMethods for sandbox::Command { - fn arg(&mut self, arg: T) - where T: AsRef { - self.arg(arg); - } - - fn env(&mut self, key: T, val: U) - where T: AsRef, U: AsRef { - self.env(key, val); - } - } - - // Note that this function can panic, due to process creation, - // avoiding this panic would require a mechanism for dealing - // with low-resource scenarios. - let (server, token) = - IpcOneShotServer::>::new() - .expect("Failed to create IPC one-shot server."); - - // If there is a sandbox, use the `gaol` API to create the child process. - if opts::get().sandbox { - let mut command = sandbox::Command::me().expect("Failed to get current sandbox."); - self.setup_common(&mut command, token); - - let profile = content_process_sandbox_profile(); - let _ = Sandbox::new(profile) - .start(&mut command) - .expect("Failed to start sandboxed child process!"); - } else { - let path_to_self = env::current_exe() - .expect("Failed to get current executor."); - let mut child_process = process::Command::new(path_to_self); - self.setup_common(&mut child_process, token); - let _ = child_process.spawn().expect("Failed to start unsandboxed child process!"); - } - - let (_receiver, sender) = server.accept().expect("Server failed to accept."); - sender.send(self)?; - - Ok(()) - } - - #[cfg(any(target_os = "windows", target_os = "ios"))] - pub fn spawn_multiprocess(self) -> Result<(), Error> { - error!("Multiprocess is not supported on Windows or iOS."); - process::exit(1); - } - - #[cfg(not(windows))] - fn setup_common(&self, command: &mut C, token: String) { - C::arg(command, "--content-process"); - C::arg(command, token); - - if let Ok(value) = env::var("RUST_BACKTRACE") { - C::env(command, "RUST_BACKTRACE", value); - } - - if let Ok(value) = env::var("RUST_LOG") { - C::env(command, "RUST_LOG", value); - } - } - - pub fn script_to_constellation_chan(&self) -> &ScriptToConstellationChan { - &self.script_to_constellation_chan - } - - pub fn opts(&self) -> Opts { - self.opts.clone() - } - - pub fn prefs(&self) -> HashMap { - self.prefs.clone() - } - - pub fn swmanager_senders(&self) -> SWManagerSenders { - SWManagerSenders { - swmanager_sender: self.swmanager_thread.clone(), - resource_sender: self.resource_threads.sender() - } - } -} - -/// A trait to unify commands launched as multiprocess with or without a sandbox. -trait CommandMethods { - /// A command line argument. - fn arg(&mut self, arg: T) - where T: AsRef; - - /// An environment variable. - fn env(&mut self, key: T, val: U) - where T: AsRef, U: AsRef; -} - -impl CommandMethods for process::Command { - fn arg(&mut self, arg: T) - where T: AsRef { - self.arg(arg); - } - - fn env(&mut self, key: T, val: U) - where T: AsRef, U: AsRef { - self.env(key, val); - } -} diff --git a/servo/components/constellation/sandboxing.rs b/servo/components/constellation/sandboxing.rs deleted file mode 100644 index a51fd4b8ef1b..000000000000 --- a/servo/components/constellation/sandboxing.rs +++ /dev/null @@ -1,42 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -use gaol::profile::{Operation, PathPattern, Profile}; -use servo_config::resource_files; -use std::path::PathBuf; - -/// Our content process sandbox profile on Mac. As restrictive as possible. -#[cfg(target_os = "macos")] -pub fn content_process_sandbox_profile() -> Profile { - use gaol::platform; - Profile::new(vec![ - Operation::FileReadAll(PathPattern::Literal(PathBuf::from("/dev/urandom"))), - Operation::FileReadAll(PathPattern::Subpath(resource_files::resources_dir_path() - .expect("Cannot find resource dir"))), - Operation::FileReadAll(PathPattern::Subpath(PathBuf::from("/Library/Fonts"))), - Operation::FileReadAll(PathPattern::Subpath(PathBuf::from("/System/Library/Fonts"))), - Operation::FileReadAll(PathPattern::Subpath(PathBuf::from( - "/System/Library/Frameworks/ApplicationServices.framework"))), - Operation::FileReadAll(PathPattern::Subpath(PathBuf::from( - "/System/Library/Frameworks/CoreGraphics.framework"))), - Operation::FileReadMetadata(PathPattern::Literal(PathBuf::from("/"))), - Operation::FileReadMetadata(PathPattern::Literal(PathBuf::from("/Library"))), - Operation::FileReadMetadata(PathPattern::Literal(PathBuf::from("/System"))), - Operation::FileReadMetadata(PathPattern::Literal(PathBuf::from("/etc"))), - Operation::SystemInfoRead, - Operation::PlatformSpecific(platform::macos::Operation::MachLookup( - b"com.apple.FontServer".to_vec())), - ]).expect("Failed to create sandbox profile!") -} - -/// Our content process sandbox profile on Linux. As restrictive as possible. -#[cfg(not(target_os = "macos"))] -pub fn content_process_sandbox_profile() -> Profile { - Profile::new(vec![ - Operation::FileReadAll(PathPattern::Literal(PathBuf::from("/dev/urandom"))), - Operation::FileReadAll(PathPattern::Subpath(resource_files::resources_dir_path() - .expect("Cannot find resource dir"))), - ]).expect("Failed to create sandbox profile!") -} - diff --git a/servo/components/constellation/session_history.rs b/servo/components/constellation/session_history.rs deleted file mode 100644 index 67210a450b97..000000000000 --- a/servo/components/constellation/session_history.rs +++ /dev/null @@ -1,164 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -use msg::constellation_msg::{BrowsingContextId, PipelineId, TopLevelBrowsingContextId}; -use script_traits::LoadData; -use std::{fmt, mem}; -use std::cmp::PartialEq; - -/// Represents the joint session history -/// https://html.spec.whatwg.org/multipage/#joint-session-history -#[derive(Debug)] -pub struct JointSessionHistory { - /// Diffs used to traverse to past entries. Oldest entries are at the back, - /// the most recent entries are at the front. - pub past: Vec, - - /// Diffs used to traverse to future entries. Oldest entries are at the back, - /// the most recent entries are at the front. - pub future: Vec, -} - -impl JointSessionHistory { - pub fn new() -> JointSessionHistory { - JointSessionHistory { - past: Vec::new(), - future: Vec::new(), - } - } - - pub fn history_length(&self) -> usize { - self.past.len() + 1 + self.future.len() - } - - pub fn push_diff(&mut self, diff: SessionHistoryDiff) -> Vec { - self.past.push(diff); - mem::replace(&mut self.future, vec![]) - } - - pub fn replace(&mut self, old_reloader: NeedsToReload, new_reloader: NeedsToReload) { - for diff in self.past.iter_mut().chain(self.future.iter_mut()) { - diff.replace(&old_reloader, &new_reloader); - } - } -} - -/// Represents a pending change in a session history, that will be applied -/// once the new pipeline has loaded and completed initial layout / paint. -pub struct SessionHistoryChange { - /// The browsing context to change. - pub browsing_context_id: BrowsingContextId, - - /// The top-level browsing context ancestor. - pub top_level_browsing_context_id: TopLevelBrowsingContextId, - - /// The pipeline for the document being loaded. - pub new_pipeline_id: PipelineId, - - /// The old pipeline that the new pipeline should replace. - pub replace: Option, -} - -/// Represents a pipeline or discarded pipeline in a history entry. -#[derive(Clone, Debug)] -pub enum NeedsToReload { - /// Represents a pipeline that has not been discarded - No(PipelineId), - /// Represents a pipeline that has been discarded and must be reloaded with the given `LoadData` - /// if ever traversed to. - Yes(PipelineId, LoadData), -} - -impl fmt::Display for NeedsToReload { - fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { - match *self { - NeedsToReload::No(pipeline_id) => write!(fmt, "Alive({})", pipeline_id), - NeedsToReload::Yes(pipeline_id, ..) => write!(fmt, "Dead({})", pipeline_id), - } - } -} - -impl NeedsToReload { - pub fn alive_pipeline_id(&self) -> Option { - match *self { - NeedsToReload::No(pipeline_id) => Some(pipeline_id), - NeedsToReload::Yes(..) => None, - } - } -} - -// Custom `PartialEq` that only compares the `PipelineId`s of the same variants while ignoring `LoadData` -impl PartialEq for NeedsToReload { - fn eq(&self, other: &NeedsToReload) -> bool { - match *self { - NeedsToReload::No(pipeline_id) => { - match *other { - NeedsToReload::No(other_pipeline_id) => pipeline_id == other_pipeline_id, - _ => false, - } - }, - NeedsToReload::Yes(pipeline_id, _) => { - match *other { - NeedsToReload::Yes(other_pipeline_id, _) => pipeline_id == other_pipeline_id, - _ => false, - } - } - } - } -} - - -/// Represents a the difference between two adjacent session history entries. -#[derive(Debug)] -pub enum SessionHistoryDiff { - /// Represents a diff where the active pipeline of an entry changed. - BrowsingContextDiff { - /// The browsing context whose pipeline changed - browsing_context_id: BrowsingContextId, - /// The previous pipeline (used when traversing into the past) - old_reloader: NeedsToReload, - /// The next pipeline (used when traversing into the future) - new_reloader: NeedsToReload, - }, -} - -impl SessionHistoryDiff { - /// Returns the old pipeline id if that pipeline is still alive, otherwise returns `None` - pub fn alive_old_pipeline(&self) -> Option { - match *self { - SessionHistoryDiff::BrowsingContextDiff { ref old_reloader, .. } => { - match *old_reloader { - NeedsToReload::No(pipeline_id) => Some(pipeline_id), - NeedsToReload::Yes(..) => None, - } - } - } - } - - /// Returns the new pipeline id if that pipeline is still alive, otherwise returns `None` - pub fn alive_new_pipeline(&self) -> Option { - match *self { - SessionHistoryDiff::BrowsingContextDiff { ref new_reloader, .. } => { - match *new_reloader { - NeedsToReload::No(pipeline_id) => Some(pipeline_id), - NeedsToReload::Yes(..) => None, - } - } - } - } - - /// Replaces all occurances of the replaced pipeline with a new pipeline - pub fn replace(&mut self, replaced_reloader: &NeedsToReload, reloader: &NeedsToReload) { - match *self { - SessionHistoryDiff::BrowsingContextDiff { ref mut old_reloader, ref mut new_reloader, .. } => { - if *old_reloader == *replaced_reloader { - *old_reloader = reloader.clone(); - } - if *new_reloader == *replaced_reloader { - *new_reloader = reloader.clone(); - } - } - } - } -} diff --git a/servo/components/constellation/timer_scheduler.rs b/servo/components/constellation/timer_scheduler.rs deleted file mode 100644 index 2ed0005957ed..000000000000 --- a/servo/components/constellation/timer_scheduler.rs +++ /dev/null @@ -1,128 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -use ipc_channel::ipc::{self, IpcSender}; -use script_traits::{TimerEvent, TimerEventRequest, TimerSchedulerMsg}; -use std::cmp::{self, Ord}; -use std::collections::BinaryHeap; -use std::sync::mpsc; -use std::sync::mpsc::TryRecvError::{Disconnected, Empty}; -use std::thread; -use std::time::{Duration, Instant}; - -pub struct TimerScheduler; - -struct ScheduledEvent { - request: TimerEventRequest, - for_time: Instant, -} - -impl Ord for ScheduledEvent { - fn cmp(&self, other: &ScheduledEvent) -> cmp::Ordering { - self.for_time.cmp(&other.for_time).reverse() - } -} - -impl PartialOrd for ScheduledEvent { - fn partial_cmp(&self, other: &ScheduledEvent) -> Option { - Some(self.cmp(other)) - } -} - -impl Eq for ScheduledEvent {} -impl PartialEq for ScheduledEvent { - fn eq(&self, other: &ScheduledEvent) -> bool { - self as *const ScheduledEvent == other as *const ScheduledEvent - } -} - -impl TimerScheduler { - pub fn start() -> IpcSender { - let (req_ipc_sender, req_ipc_receiver) = ipc::channel().expect("Channel creation failed."); - let (req_sender, req_receiver) = mpsc::sync_channel(1); - - // We could do this much more directly with recv_timeout - // (https://github.com/rust-lang/rfcs/issues/962). - - // util::thread doesn't give us access to the JoinHandle, which we need for park/unpark, - // so we use the builder directly. - let timeout_thread = thread::Builder::new() - .name(String::from("TimerScheduler")) - .spawn(move || { - // We maintain a priority queue of future events, sorted by due time. - let mut scheduled_events = BinaryHeap::::new(); - loop { - let now = Instant::now(); - // Dispatch any events whose due time is past - loop { - match scheduled_events.peek() { - // Dispatch the event if its due time is past - Some(event) if event.for_time <= now => { - let TimerEventRequest(ref sender, source, id, _) = event.request; - let _ = sender.send(TimerEvent(source, id)); - }, - // Otherwise, we're done dispatching events - _ => break, - } - // Remove the event from the priority queue - // (Note this only executes when the first event has been dispatched - scheduled_events.pop(); - } - // Look to see if there are any incoming events - match req_receiver.try_recv() { - // If there is an event, add it to the priority queue - Ok(TimerSchedulerMsg::Request(req)) => { - let TimerEventRequest(_, _, _, delay) = req; - let schedule = Instant::now() + Duration::from_millis(delay.get()); - let event = ScheduledEvent { request: req, for_time: schedule }; - scheduled_events.push(event); - }, - // If there is no incoming event, park the thread, - // it will either be unparked when a new event arrives, - // or by a timeout. - Err(Empty) => match scheduled_events.peek() { - None => thread::park(), - Some(event) => thread::park_timeout(event.for_time - now), - }, - // If the channel is closed or we are shutting down, we are done. - Ok(TimerSchedulerMsg::Exit) | - Err(Disconnected) => break, - } - } - // This thread can terminate if the req_ipc_sender is dropped. - warn!("TimerScheduler thread terminated."); - }) - .expect("Thread creation failed.") - .thread() - .clone(); - - // A proxy that just routes incoming IPC requests over the MPSC channel to the timeout thread, - // and unparks the timeout thread each time. Note that if unpark is called while the timeout - // thread isn't parked, this causes the next call to thread::park by the timeout thread - // not to block. This means that the timeout thread won't park when there is a request - // waiting in the MPSC channel buffer. - thread::Builder::new() - .name(String::from("TimerProxy")) - .spawn(move || { - while let Ok(req) = req_ipc_receiver.recv() { - let mut shutting_down = false; - match req { - TimerSchedulerMsg::Exit => shutting_down = true, - _ => {} - } - let _ = req_sender.send(req); - timeout_thread.unpark(); - if shutting_down { - break; - } - } - // This thread can terminate if the req_ipc_sender is dropped. - warn!("TimerProxy thread terminated."); - }) - .expect("Thread creation failed."); - - // Return the IPC sender - req_ipc_sender - } -} diff --git a/servo/components/debugger/Cargo.toml b/servo/components/debugger/Cargo.toml deleted file mode 100644 index 0f04322c80e7..000000000000 --- a/servo/components/debugger/Cargo.toml +++ /dev/null @@ -1,15 +0,0 @@ -[package] -name = "debugger" -version = "0.0.1" -authors = ["The Servo Project Developers"] -license = "MPL-2.0" -publish = false - -[lib] -name = "debugger" -path = "lib.rs" -crate_type = ["rlib"] - -[dependencies] -log = "0.4" -ws = "0.7.3" diff --git a/servo/components/debugger/lib.rs b/servo/components/debugger/lib.rs deleted file mode 100644 index ec0e5ba0e800..000000000000 --- a/servo/components/debugger/lib.rs +++ /dev/null @@ -1,68 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -#[macro_use] -extern crate log; -extern crate ws; - -use std::sync::mpsc; -use std::sync::mpsc::channel; -use std::thread; -use ws::{Builder, CloseCode, Handler, Handshake}; - -enum Message { - ShutdownServer, -} - -pub struct Sender(mpsc::Sender); - -struct Connection { - sender: ws::Sender -} - -impl Handler for Connection { - fn on_open(&mut self, _: Handshake) -> ws::Result<()> { - debug!("Connection opened."); - Ok(()) - } - - fn on_close(&mut self, _: CloseCode, _: &str) { - debug!("Connection closed."); - } - - fn on_message(&mut self, message: ws::Message) -> ws::Result<()> { - self.sender.send(message) - } -} - -pub fn start_server(port: u16) -> Sender { - debug!("Starting server."); - let (sender, receiver) = channel(); - thread::Builder::new().name("debugger".to_owned()).spawn(move || { - let socket = Builder::new().build(|sender: ws::Sender| { - Connection { sender: sender } - }).unwrap(); - let sender = socket.broadcaster(); - thread::Builder::new().name("debugger-websocket".to_owned()).spawn(move || { - socket.listen(("127.0.0.1", port)).unwrap(); - }).expect("Thread spawning failed"); - while let Ok(message) = receiver.recv() { - match message { - Message::ShutdownServer => { - break; - } - } - } - sender.shutdown().unwrap(); - }).expect("Thread spawning failed"); - Sender(sender) -} - -pub fn shutdown_server(sender: &Sender) { - debug!("Shutting down server."); - let &Sender(ref sender) = sender; - if let Err(_) = sender.send(Message::ShutdownServer) { - warn!("Failed to shut down server."); - } -} diff --git a/servo/components/deny_public_fields/Cargo.toml b/servo/components/deny_public_fields/Cargo.toml deleted file mode 100644 index 45c291aa061f..000000000000 --- a/servo/components/deny_public_fields/Cargo.toml +++ /dev/null @@ -1,14 +0,0 @@ -[package] -name = "deny_public_fields" -version = "0.0.1" -authors = ["The Servo Project Developers"] -license = "MPL-2.0" -publish = false - -[lib] -path = "lib.rs" -proc-macro = true - -[dependencies] -syn = "0.12.12" -synstructure = "0.7" diff --git a/servo/components/deny_public_fields/lib.rs b/servo/components/deny_public_fields/lib.rs deleted file mode 100644 index 8d5feb39cbec..000000000000 --- a/servo/components/deny_public_fields/lib.rs +++ /dev/null @@ -1,25 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -extern crate proc_macro; -extern crate syn; -#[macro_use] -extern crate synstructure; - -use std::str::FromStr; - -decl_derive!([DenyPublicFields] => deny_public_fields_derive); - -fn deny_public_fields_derive(s: synstructure::Structure) -> proc_macro::TokenStream { - s.each(|binding| { - if binding.ast().vis != syn::Visibility::Inherited { - panic!("Field `{}` should not be public", - binding.ast().ident.as_ref().unwrap_or(&binding.binding)); - } - - "".to_owned() - }); - - proc_macro::TokenStream::from_str("").unwrap() -} diff --git a/servo/components/devtools/Cargo.toml b/servo/components/devtools/Cargo.toml deleted file mode 100644 index fb80f609d848..000000000000 --- a/servo/components/devtools/Cargo.toml +++ /dev/null @@ -1,21 +0,0 @@ -[package] -name = "devtools" -version = "0.0.1" -authors = ["The Servo Project Developers"] -license = "MPL-2.0" -publish = false - -[lib] -name = "devtools" -path = "lib.rs" - -[dependencies] -devtools_traits = {path = "../devtools_traits"} -hyper = "0.10" -hyper_serde = "0.8" -ipc-channel = "0.10" -log = "0.4" -msg = {path = "../msg"} -serde = "1.0" -serde_json = "1.0" -time = "0.1" diff --git a/servo/components/devtools/actor.rs b/servo/components/devtools/actor.rs deleted file mode 100644 index f2ee6398e9bb..000000000000 --- a/servo/components/devtools/actor.rs +++ /dev/null @@ -1,189 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -/// General actor system infrastructure. - -use devtools_traits::PreciseTime; -use serde_json::{Map, Value}; -use std::any::Any; -use std::cell::{Cell, RefCell}; -use std::collections::HashMap; -use std::mem::replace; -use std::net::TcpStream; -use std::sync::{Arc, Mutex}; - -#[derive(PartialEq)] -pub enum ActorMessageStatus { - Processed, - Ignored, -} - -/// A common trait for all devtools actors that encompasses an immutable name -/// and the ability to process messages that are directed to particular actors. -/// TODO: ensure the name is immutable -pub trait Actor: Any + ActorAsAny { - fn handle_message(&self, - registry: &ActorRegistry, - msg_type: &str, - msg: &Map, - stream: &mut TcpStream) -> Result; - fn name(&self) -> String; -} - -pub trait ActorAsAny { - fn actor_as_any(&self) -> &Any; - fn actor_as_any_mut(&mut self) -> &mut Any; -} - -impl ActorAsAny for T { - fn actor_as_any(&self) -> &Any { self } - fn actor_as_any_mut(&mut self) -> &mut Any { self } -} - -/// A list of known, owned actors. -pub struct ActorRegistry { - actors: HashMap>, - new_actors: RefCell>>, - old_actors: RefCell>, - script_actors: RefCell>, - shareable: Option>>, - next: Cell, - start_stamp: PreciseTime, -} - -impl ActorRegistry { - /// Create an empty registry. - pub fn new() -> ActorRegistry { - ActorRegistry { - actors: HashMap::new(), - new_actors: RefCell::new(vec!()), - old_actors: RefCell::new(vec!()), - script_actors: RefCell::new(HashMap::new()), - shareable: None, - next: Cell::new(0), - start_stamp: PreciseTime::now(), - } - } - - /// Creating shareable registry - pub fn create_shareable(self) -> Arc> { - if let Some(shareable) = self.shareable { - return shareable; - } - - let shareable = Arc::new(Mutex::new(self)); - { - let mut lock = shareable.lock(); - let registry = lock.as_mut().unwrap(); - registry.shareable = Some(shareable.clone()); - } - shareable - } - - /// Get shareable registry through threads - pub fn shareable(&self) -> Arc> { - self.shareable.as_ref().unwrap().clone() - } - - /// Get start stamp when registry was started - pub fn start_stamp(&self) -> PreciseTime { - self.start_stamp.clone() - } - - pub fn register_script_actor(&self, script_id: String, actor: String) { - debug!("registering {} ({})", actor, script_id); - let mut script_actors = self.script_actors.borrow_mut(); - script_actors.insert(script_id, actor); - } - - pub fn script_to_actor(&self, script_id: String) -> String { - if script_id.is_empty() { - return "".to_owned(); - } - self.script_actors.borrow().get(&script_id).unwrap().clone() - } - - pub fn script_actor_registered(&self, script_id: String) -> bool { - self.script_actors.borrow().contains_key(&script_id) - } - - pub fn actor_to_script(&self, actor: String) -> String { - for (key, value) in &*self.script_actors.borrow() { - debug!("checking {}", value); - if *value == actor { - return key.to_owned(); - } - } - panic!("couldn't find actor named {}", actor) - } - - /// Create a unique name based on a monotonically increasing suffix - pub fn new_name(&self, prefix: &str) -> String { - let suffix = self.next.get(); - self.next.set(suffix + 1); - format!("{}{}", prefix, suffix) - } - - /// Add an actor to the registry of known actors that can receive messages. - pub fn register(&mut self, actor: Box) { - self.actors.insert(actor.name(), actor); - } - - pub fn register_later(&self, actor: Box) { - let mut actors = self.new_actors.borrow_mut(); - actors.push(actor); - } - - /// Find an actor by registered name - pub fn find<'a, T: Any>(&'a self, name: &str) -> &'a T { - let actor = self.actors.get(name).unwrap(); - actor.actor_as_any().downcast_ref::().unwrap() - } - - /// Find an actor by registered name - pub fn find_mut<'a, T: Any>(&'a mut self, name: &str) -> &'a mut T { - let actor = self.actors.get_mut(name).unwrap(); - actor.actor_as_any_mut().downcast_mut::().unwrap() - } - - /// Attempt to process a message as directed by its `to` property. If the actor is not - /// found or does not indicate that it knew how to process the message, ignore the failure. - pub fn handle_message(&mut self, - msg: &Map, - stream: &mut TcpStream) - -> Result<(), ()> { - let to = msg.get("to").unwrap().as_str().unwrap(); - - match self.actors.get(to) { - None => debug!("message received for unknown actor \"{}\"", to), - Some(actor) => { - let msg_type = msg.get("type").unwrap().as_str().unwrap(); - if actor.handle_message(self, msg_type, msg, stream)? - != ActorMessageStatus::Processed { - debug!("unexpected message type \"{}\" found for actor \"{}\"", - msg_type, to); - } - } - } - let new_actors = replace(&mut *self.new_actors.borrow_mut(), vec!()); - for actor in new_actors.into_iter() { - self.actors.insert(actor.name().to_owned(), actor); - } - - let old_actors = replace(&mut *self.old_actors.borrow_mut(), vec!()); - for name in old_actors { - self.drop_actor(name); - } - Ok(()) - } - - pub fn drop_actor(&mut self, name: String) { - self.actors.remove(&name); - } - - pub fn drop_actor_later(&self, name: String) { - let mut actors = self.old_actors.borrow_mut(); - actors.push(name); - } -} diff --git a/servo/components/devtools/actors/console.rs b/servo/components/devtools/actors/console.rs deleted file mode 100644 index 295ebca489bc..000000000000 --- a/servo/components/devtools/actors/console.rs +++ /dev/null @@ -1,257 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -//! Liberally derived from the [Firefox JS implementation] -//! (http://mxr.mozilla.org/mozilla-central/source/toolkit/devtools/server/actors/webconsole.js). -//! Mediates interaction between the remote web console and equivalent functionality (object -//! inspection, JS evaluation, autocompletion) in Servo. - -use actor::{Actor, ActorMessageStatus, ActorRegistry}; -use actors::object::ObjectActor; -use devtools_traits::{CachedConsoleMessageTypes, DevtoolScriptControlMsg}; -use devtools_traits::CachedConsoleMessage; -use devtools_traits::EvaluateJSReply::{ActorValue, BooleanValue, StringValue}; -use devtools_traits::EvaluateJSReply::{NullValue, NumberValue, VoidValue}; -use ipc_channel::ipc::{self, IpcSender}; -use msg::constellation_msg::PipelineId; -use protocol::JsonPacketStream; -use serde_json::{self, Map, Number, Value}; -use std::cell::RefCell; -use std::net::TcpStream; - -trait EncodableConsoleMessage { - fn encode(&self) -> serde_json::Result; -} - -impl EncodableConsoleMessage for CachedConsoleMessage { - fn encode(&self) -> serde_json::Result { - match *self { - CachedConsoleMessage::PageError(ref a) => serde_json::to_string(a), - CachedConsoleMessage::ConsoleAPI(ref a) => serde_json::to_string(a), - } - } -} - -#[derive(Serialize)] -struct StartedListenersTraits { - customNetworkRequest: bool, -} - -#[derive(Serialize)] -struct StartedListenersReply { - from: String, - nativeConsoleAPI: bool, - startedListeners: Vec, - traits: StartedListenersTraits, -} - -#[derive(Serialize)] -struct GetCachedMessagesReply { - from: String, - messages: Vec>, -} - -#[derive(Serialize)] -struct StopListenersReply { - from: String, - stoppedListeners: Vec, -} - -#[derive(Serialize)] -struct AutocompleteReply { - from: String, - matches: Vec, - matchProp: String, -} - -#[derive(Serialize)] -struct EvaluateJSReply { - from: String, - input: String, - result: Value, - timestamp: u64, - exception: Value, - exceptionMessage: String, - helperResult: Value, -} - -#[derive(Serialize)] -struct SetPreferencesReply { - from: String, - updated: Vec, -} - -pub struct ConsoleActor { - pub name: String, - pub pipeline: PipelineId, - pub script_chan: IpcSender, - pub streams: RefCell>, -} - -impl Actor for ConsoleActor { - fn name(&self) -> String { - self.name.clone() - } - - fn handle_message(&self, - registry: &ActorRegistry, - msg_type: &str, - msg: &Map, - stream: &mut TcpStream) -> Result { - Ok(match msg_type { - "getCachedMessages" => { - let str_types = msg.get("messageTypes").unwrap().as_array().unwrap().into_iter().map(|json_type| { - json_type.as_str().unwrap() - }); - let mut message_types = CachedConsoleMessageTypes::empty(); - for str_type in str_types { - match str_type { - "PageError" => message_types.insert(CachedConsoleMessageTypes::PAGE_ERROR), - "ConsoleAPI" => message_types.insert(CachedConsoleMessageTypes::CONSOLE_API), - s => debug!("unrecognized message type requested: \"{}\"", s), - }; - }; - let (chan, port) = ipc::channel().unwrap(); - self.script_chan.send(DevtoolScriptControlMsg::GetCachedMessages( - self.pipeline, message_types, chan)).unwrap(); - let messages = port.recv().map_err(|_| ())?.into_iter().map(|message| { - let json_string = message.encode().unwrap(); - let json = serde_json::from_str::(&json_string).unwrap(); - json.as_object().unwrap().to_owned() - }).collect(); - - let msg = GetCachedMessagesReply { - from: self.name(), - messages: messages, - }; - stream.write_json_packet(&msg); - ActorMessageStatus::Processed - } - - "startListeners" => { - //TODO: actually implement listener filters that support starting/stopping - let msg = StartedListenersReply { - from: self.name(), - nativeConsoleAPI: true, - startedListeners: - vec!("PageError".to_owned(), "ConsoleAPI".to_owned()), - traits: StartedListenersTraits { - customNetworkRequest: true, - } - }; - stream.write_json_packet(&msg); - ActorMessageStatus::Processed - } - - "stopListeners" => { - //TODO: actually implement listener filters that support starting/stopping - let msg = StopListenersReply { - from: self.name(), - stoppedListeners: msg.get("listeners") - .unwrap() - .as_array() - .unwrap_or(&vec!()) - .iter() - .map(|listener| listener.as_str().unwrap().to_owned()) - .collect(), - }; - stream.write_json_packet(&msg); - ActorMessageStatus::Processed - } - - //TODO: implement autocompletion like onAutocomplete in - // http://mxr.mozilla.org/mozilla-central/source/toolkit/devtools/server/actors/webconsole.js - "autocomplete" => { - let msg = AutocompleteReply { - from: self.name(), - matches: vec!(), - matchProp: "".to_owned(), - }; - stream.write_json_packet(&msg); - ActorMessageStatus::Processed - } - - "evaluateJS" => { - let input = msg.get("text").unwrap().as_str().unwrap().to_owned(); - let (chan, port) = ipc::channel().unwrap(); - self.script_chan.send(DevtoolScriptControlMsg::EvaluateJS( - self.pipeline, input.clone(), chan)).unwrap(); - - //TODO: extract conversion into protocol module or some other useful place - let result = match port.recv().map_err(|_| ())? { - VoidValue => { - let mut m = Map::new(); - m.insert("type".to_owned(), Value::String("undefined".to_owned())); - Value::Object(m) - } - NullValue => { - let mut m = Map::new(); - m.insert("type".to_owned(), Value::String("null".to_owned())); - Value::Object(m) - } - BooleanValue(val) => Value::Bool(val), - NumberValue(val) => { - if val.is_nan() { - let mut m = Map::new(); - m.insert("type".to_owned(), Value::String("NaN".to_owned())); - Value::Object(m) - } else if val.is_infinite() { - let mut m = Map::new(); - if val < 0. { - m.insert("type".to_owned(), Value::String("-Infinity".to_owned())); - } else { - m.insert("type".to_owned(), Value::String("Infinity".to_owned())); - } - Value::Object(m) - } else if val == 0. && val.is_sign_negative() { - let mut m = Map::new(); - m.insert("type".to_owned(), Value::String("-0".to_owned())); - Value::Object(m) - } else { - Value::Number(Number::from_f64(val).unwrap()) - } - } - StringValue(s) => Value::String(s), - ActorValue { class, uuid } => { - //TODO: make initial ActorValue message include these properties? - let mut m = Map::new(); - let actor = ObjectActor::new(registry, uuid); - - m.insert("type".to_owned(), Value::String("object".to_owned())); - m.insert("class".to_owned(), Value::String(class)); - m.insert("actor".to_owned(), Value::String(actor)); - m.insert("extensible".to_owned(), Value::Bool(true)); - m.insert("frozen".to_owned(), Value::Bool(false)); - m.insert("sealed".to_owned(), Value::Bool(false)); - Value::Object(m) - } - }; - - //TODO: catch and return exception values from JS evaluation - let msg = EvaluateJSReply { - from: self.name(), - input: input, - result: result, - timestamp: 0, - exception: Value::Object(Map::new()), - exceptionMessage: "".to_owned(), - helperResult: Value::Object(Map::new()), - }; - stream.write_json_packet(&msg); - ActorMessageStatus::Processed - } - - "setPreferences" => { - let msg = SetPreferencesReply { - from: self.name(), - updated: vec![], - }; - stream.write_json_packet(&msg); - ActorMessageStatus::Processed - } - - _ => ActorMessageStatus::Ignored - }) - } -} diff --git a/servo/components/devtools/actors/framerate.rs b/servo/components/devtools/actors/framerate.rs deleted file mode 100644 index 39776c131cbe..000000000000 --- a/servo/components/devtools/actors/framerate.rs +++ /dev/null @@ -1,100 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -use actor::{Actor, ActorMessageStatus, ActorRegistry}; -use actors::timeline::HighResolutionStamp; -use devtools_traits::DevtoolScriptControlMsg; -use ipc_channel::ipc::IpcSender; -use msg::constellation_msg::PipelineId; -use serde_json::{Map, Value}; -use std::mem; -use std::net::TcpStream; -use time::precise_time_ns; - -pub struct FramerateActor { - name: String, - pipeline: PipelineId, - script_sender: IpcSender, - start_time: Option, - is_recording: bool, - ticks: Vec, -} - -impl Actor for FramerateActor { - fn name(&self) -> String { - self.name.clone() - } - - - fn handle_message(&self, - _registry: &ActorRegistry, - _msg_type: &str, - _msg: &Map, - _stream: &mut TcpStream) -> Result { - Ok(ActorMessageStatus::Ignored) - } -} - -impl FramerateActor { - /// return name of actor - pub fn create(registry: &ActorRegistry, - pipeline_id: PipelineId, - script_sender: IpcSender) -> String { - let actor_name = registry.new_name("framerate"); - let mut actor = FramerateActor { - name: actor_name.clone(), - pipeline: pipeline_id, - script_sender: script_sender, - start_time: None, - is_recording: false, - ticks: Vec::new(), - }; - - actor.start_recording(); - registry.register_later(Box::new(actor)); - actor_name - } - - pub fn add_tick(&mut self, tick: f64) { - self.ticks.push(HighResolutionStamp::wrap(tick)); - - if self.is_recording { - let msg = DevtoolScriptControlMsg::RequestAnimationFrame(self.pipeline, - self.name()); - self.script_sender.send(msg).unwrap(); - } - } - - pub fn take_pending_ticks(&mut self) -> Vec { - mem::replace(&mut self.ticks, Vec::new()) - } - - fn start_recording(&mut self) { - if self.is_recording { - return; - } - - self.start_time = Some(precise_time_ns()); - self.is_recording = true; - - let msg = DevtoolScriptControlMsg::RequestAnimationFrame(self.pipeline, - self.name()); - self.script_sender.send(msg).unwrap(); - } - - fn stop_recording(&mut self) { - if !self.is_recording { - return; - } - self.is_recording = false; - self.start_time = None; - } - -} - -impl Drop for FramerateActor { - fn drop(&mut self) { - self.stop_recording(); - } -} diff --git a/servo/components/devtools/actors/inspector.rs b/servo/components/devtools/actors/inspector.rs deleted file mode 100644 index 22a69421ad85..000000000000 --- a/servo/components/devtools/actors/inspector.rs +++ /dev/null @@ -1,629 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -//! Liberally derived from the [Firefox JS implementation] -//! (http://mxr.mozilla.org/mozilla-central/source/toolkit/devtools/server/actors/inspector.js). - -use actor::{Actor, ActorMessageStatus, ActorRegistry}; -use devtools_traits::{ComputedNodeLayout, DevtoolScriptControlMsg, NodeInfo}; -use devtools_traits::DevtoolScriptControlMsg::{GetChildren, GetDocumentElement, GetRootNode}; -use devtools_traits::DevtoolScriptControlMsg::{GetLayout, ModifyAttribute}; -use ipc_channel::ipc::{self, IpcSender}; -use msg::constellation_msg::PipelineId; -use protocol::JsonPacketStream; -use serde_json::{self, Map, Value}; -use std::cell::RefCell; -use std::net::TcpStream; - -pub struct InspectorActor { - pub name: String, - pub walker: RefCell>, - pub pageStyle: RefCell>, - pub highlighter: RefCell>, - pub script_chan: IpcSender, - pub pipeline: PipelineId, -} - -#[derive(Serialize)] -struct GetHighlighterReply { - highligter: HighlighterMsg, // sic. - from: String, -} - -#[derive(Serialize)] -struct HighlighterMsg { - actor: String, -} - -struct HighlighterActor { - name: String, -} - -pub struct NodeActor { - pub name: String, - script_chan: IpcSender, - pipeline: PipelineId, -} - -#[derive(Serialize)] -struct ShowBoxModelReply { - from: String, -} - -#[derive(Serialize)] -struct HideBoxModelReply { - from: String, -} - -impl Actor for HighlighterActor { - fn name(&self) -> String { - self.name.clone() - } - - fn handle_message(&self, - _registry: &ActorRegistry, - msg_type: &str, - _msg: &Map, - stream: &mut TcpStream) -> Result { - Ok(match msg_type { - "showBoxModel" => { - let msg = ShowBoxModelReply { - from: self.name(), - }; - stream.write_json_packet(&msg); - ActorMessageStatus::Processed - } - - "hideBoxModel" => { - let msg = HideBoxModelReply { - from: self.name(), - }; - stream.write_json_packet(&msg); - ActorMessageStatus::Processed - } - - _ => ActorMessageStatus::Ignored, - }) - } -} - -#[derive(Serialize)] -struct ModifyAttributeReply { - from: String, -} - -impl Actor for NodeActor { - fn name(&self) -> String { - self.name.clone() - } - - fn handle_message(&self, - registry: &ActorRegistry, - msg_type: &str, - msg: &Map, - stream: &mut TcpStream) -> Result { - Ok(match msg_type { - "modifyAttributes" => { - let target = msg.get("to").unwrap().as_str().unwrap(); - let mods = msg.get("modifications").unwrap().as_array().unwrap(); - let modifications = mods.iter().map(|json_mod| { - serde_json::from_str(&serde_json::to_string(json_mod).unwrap()).unwrap() - }).collect(); - - self.script_chan.send(ModifyAttribute(self.pipeline, - registry.actor_to_script(target.to_owned()), - modifications)) - .unwrap(); - let reply = ModifyAttributeReply { - from: self.name(), - }; - stream.write_json_packet(&reply); - ActorMessageStatus::Processed - } - - _ => ActorMessageStatus::Ignored, - }) - } -} - -#[derive(Serialize)] -struct GetWalkerReply { - from: String, - walker: WalkerMsg, -} - -#[derive(Serialize)] -struct WalkerMsg { - actor: String, - root: NodeActorMsg, -} - -#[derive(Serialize)] -struct AttrMsg { - namespace: String, - name: String, - value: String, -} - -#[derive(Serialize)] -struct NodeActorMsg { - actor: String, - baseURI: String, - parent: String, - nodeType: u16, - namespaceURI: String, - nodeName: String, - numChildren: usize, - - name: String, - publicId: String, - systemId: String, - - attrs: Vec, - - pseudoClassLocks: Vec, - - isDisplayed: bool, - - hasEventListeners: bool, - - isDocumentElement: bool, - - shortValue: String, - incompleteValue: bool, -} - -trait NodeInfoToProtocol { - fn encode(self, - actors: &ActorRegistry, - display: bool, - script_chan: IpcSender, - pipeline: PipelineId) -> NodeActorMsg; -} - -impl NodeInfoToProtocol for NodeInfo { - fn encode(self, - actors: &ActorRegistry, - display: bool, - script_chan: IpcSender, - pipeline: PipelineId) -> NodeActorMsg { - let actor_name = if !actors.script_actor_registered(self.uniqueId.clone()) { - let name = actors.new_name("node"); - let node_actor = NodeActor { - name: name.clone(), - script_chan: script_chan, - pipeline: pipeline.clone(), - }; - actors.register_script_actor(self.uniqueId, name.clone()); - actors.register_later(Box::new(node_actor)); - name - } else { - actors.script_to_actor(self.uniqueId) - }; - - NodeActorMsg { - actor: actor_name, - baseURI: self.baseURI, - parent: actors.script_to_actor(self.parent.clone()), - nodeType: self.nodeType, - namespaceURI: self.namespaceURI, - nodeName: self.nodeName, - numChildren: self.numChildren, - - name: self.name, - publicId: self.publicId, - systemId: self.systemId, - - attrs: self.attrs.into_iter().map(|attr| { - AttrMsg { - namespace: attr.namespace, - name: attr.name, - value: attr.value, - } - }).collect(), - - pseudoClassLocks: vec!(), //TODO get this data from script - - isDisplayed: display, - - hasEventListeners: false, //TODO get this data from script - - isDocumentElement: self.isDocumentElement, - - shortValue: self.shortValue, - incompleteValue: self.incompleteValue, - } - } -} - -struct WalkerActor { - name: String, - script_chan: IpcSender, - pipeline: PipelineId, -} - -#[derive(Serialize)] -struct QuerySelectorReply { - from: String, -} - -#[derive(Serialize)] -struct DocumentElementReply { - from: String, - node: NodeActorMsg, -} - -#[derive(Serialize)] -struct ClearPseudoclassesReply { - from: String, -} - -#[derive(Serialize)] -struct ChildrenReply { - hasFirst: bool, - hasLast: bool, - nodes: Vec, - from: String, -} - -impl Actor for WalkerActor { - fn name(&self) -> String { - self.name.clone() - } - - fn handle_message(&self, - registry: &ActorRegistry, - msg_type: &str, - msg: &Map, - stream: &mut TcpStream) -> Result { - Ok(match msg_type { - "querySelector" => { - let msg = QuerySelectorReply { - from: self.name(), - }; - stream.write_json_packet(&msg); - ActorMessageStatus::Processed - } - - "documentElement" => { - let (tx, rx) = ipc::channel().unwrap(); - self.script_chan.send(GetDocumentElement(self.pipeline, tx)).unwrap(); - let doc_elem_info = rx.recv().unwrap().ok_or(())?; - let node = doc_elem_info.encode(registry, true, self.script_chan.clone(), self.pipeline); - - let msg = DocumentElementReply { - from: self.name(), - node: node, - }; - stream.write_json_packet(&msg); - ActorMessageStatus::Processed - } - - "clearPseudoClassLocks" => { - let msg = ClearPseudoclassesReply { - from: self.name(), - }; - stream.write_json_packet(&msg); - ActorMessageStatus::Processed - } - - "children" => { - let target = msg.get("node").unwrap().as_str().unwrap(); - let (tx, rx) = ipc::channel().unwrap(); - self.script_chan.send(GetChildren(self.pipeline, - registry.actor_to_script(target.to_owned()), - tx)) - .unwrap(); - let children = rx.recv().unwrap().ok_or(())?; - - let msg = ChildrenReply { - hasFirst: true, - hasLast: true, - nodes: children.into_iter().map(|child| { - child.encode(registry, true, self.script_chan.clone(), self.pipeline) - }).collect(), - from: self.name(), - }; - stream.write_json_packet(&msg); - ActorMessageStatus::Processed - } - - _ => ActorMessageStatus::Ignored, - }) - } -} - -#[derive(Serialize)] -struct GetPageStyleReply { - from: String, - pageStyle: PageStyleMsg, -} - -#[derive(Serialize)] -struct PageStyleMsg { - actor: String, -} - -struct PageStyleActor { - name: String, - script_chan: IpcSender, - pipeline: PipelineId, -} - -#[derive(Serialize)] -struct GetAppliedReply { - entries: Vec, - rules: Vec, - sheets: Vec, - from: String, -} - -#[derive(Serialize)] -struct GetComputedReply { - computed: Vec, //XXX all css props - from: String, -} - -#[derive(Serialize)] -struct AppliedEntry { - rule: String, - pseudoElement: Value, - isSystem: bool, - matchedSelectors: Vec, -} - -#[derive(Serialize)] -struct AppliedRule { - actor: String, - #[serde(rename = "type")] - type_: String, - href: String, - cssText: String, - line: u32, - column: u32, - parentStyleSheet: String, -} - -#[derive(Serialize)] -struct AppliedSheet { - actor: String, - href: String, - nodeHref: String, - disabled: bool, - title: String, - system: bool, - styleSheetIndex: isize, - ruleCount: usize, -} - -#[derive(Serialize)] -struct GetLayoutReply { - from: String, - - display: String, - position: String, - #[serde(rename = "z-index")] - zIndex: String, - #[serde(rename = "box-sizing")] - boxSizing: String, - - // Would be nice to use a proper struct, blocked by - // https://github.com/serde-rs/serde/issues/43 - autoMargins: serde_json::value::Value, - #[serde(rename = "margin-top")] - marginTop: String, - #[serde(rename = "margin-right")] - marginRight: String, - #[serde(rename = "margin-bottom")] - marginBottom: String, - #[serde(rename = "margin-left")] - marginLeft: String, - - #[serde(rename = "border-top-width")] - borderTopWidth: String, - #[serde(rename = "border-right-width")] - borderRightWidth: String, - #[serde(rename = "border-bottom-width")] - borderBottomWidth: String, - #[serde(rename = "border-left-width")] - borderLeftWidth: String, - - #[serde(rename = "padding-top")] - paddingTop: String, - #[serde(rename = "padding-right")] - paddingRight: String, - #[serde(rename = "padding-bottom")] - paddingBottom: String, - #[serde(rename = "padding-left")] - paddingLeft: String, - - width: f32, - height: f32, -} - -impl Actor for PageStyleActor { - fn name(&self) -> String { - self.name.clone() - } - - fn handle_message(&self, - registry: &ActorRegistry, - msg_type: &str, - msg: &Map, - stream: &mut TcpStream) -> Result { - Ok(match msg_type { - "getApplied" => { - //TODO: query script for relevant applied styles to node (msg.node) - let msg = GetAppliedReply { - entries: vec!(), - rules: vec!(), - sheets: vec!(), - from: self.name(), - }; - stream.write_json_packet(&msg); - ActorMessageStatus::Processed - } - - "getComputed" => { - //TODO: query script for relevant computed styles on node (msg.node) - let msg = GetComputedReply { - computed: vec!(), - from: self.name(), - }; - stream.write_json_packet(&msg); - ActorMessageStatus::Processed - } - - //TODO: query script for box layout properties of node (msg.node) - "getLayout" => { - let target = msg.get("node").unwrap().as_str().unwrap(); - let (tx, rx) = ipc::channel().unwrap(); - self.script_chan.send(GetLayout(self.pipeline, - registry.actor_to_script(target.to_owned()), - tx)) - .unwrap(); - let ComputedNodeLayout { - display, position, zIndex, boxSizing, - autoMargins, marginTop, marginRight, marginBottom, marginLeft, - borderTopWidth, borderRightWidth, borderBottomWidth, borderLeftWidth, - paddingTop, paddingRight, paddingBottom, paddingLeft, - width, height, - } = rx.recv().unwrap().ok_or(())?; - - let auto_margins = msg.get("autoMargins") - .and_then(&Value::as_bool).unwrap_or(false); - - // http://mxr.mozilla.org/mozilla-central/source/toolkit/devtools/server/actors/styles.js - let msg = GetLayoutReply { - from: self.name(), - display: display, - position: position, - zIndex: zIndex, - boxSizing: boxSizing, - autoMargins: if auto_margins { - let mut m = Map::new(); - let auto = serde_json::value::Value::String("auto".to_owned()); - if autoMargins.top { m.insert("top".to_owned(), auto.clone()); } - if autoMargins.right { m.insert("right".to_owned(), auto.clone()); } - if autoMargins.bottom { m.insert("bottom".to_owned(), auto.clone()); } - if autoMargins.left { m.insert("left".to_owned(), auto.clone()); } - serde_json::value::Value::Object(m) - } else { - serde_json::value::Value::Null - }, - marginTop: marginTop, - marginRight: marginRight, - marginBottom: marginBottom, - marginLeft: marginLeft, - borderTopWidth: borderTopWidth, - borderRightWidth: borderRightWidth, - borderBottomWidth: borderBottomWidth, - borderLeftWidth: borderLeftWidth, - paddingTop: paddingTop, - paddingRight: paddingRight, - paddingBottom: paddingBottom, - paddingLeft: paddingLeft, - width: width, - height: height, - }; - let msg = serde_json::to_string(&msg).unwrap(); - let msg = serde_json::from_str::(&msg).unwrap(); - stream.write_json_packet(&msg); - ActorMessageStatus::Processed - } - - _ => ActorMessageStatus::Ignored, - }) - } -} - -impl Actor for InspectorActor { - fn name(&self) -> String { - self.name.clone() - } - - fn handle_message(&self, - registry: &ActorRegistry, - msg_type: &str, - _msg: &Map, - stream: &mut TcpStream) -> Result { - Ok(match msg_type { - "getWalker" => { - if self.walker.borrow().is_none() { - let walker = WalkerActor { - name: registry.new_name("walker"), - script_chan: self.script_chan.clone(), - pipeline: self.pipeline, - }; - let mut walker_name = self.walker.borrow_mut(); - *walker_name = Some(walker.name()); - registry.register_later(Box::new(walker)); - } - - let (tx, rx) = ipc::channel().unwrap(); - self.script_chan.send(GetRootNode(self.pipeline, tx)).unwrap(); - let root_info = rx.recv().unwrap().ok_or(())?; - - let node = root_info.encode(registry, false, self.script_chan.clone(), self.pipeline); - - let msg = GetWalkerReply { - from: self.name(), - walker: WalkerMsg { - actor: self.walker.borrow().clone().unwrap(), - root: node, - } - }; - stream.write_json_packet(&msg); - ActorMessageStatus::Processed - } - - "getPageStyle" => { - if self.pageStyle.borrow().is_none() { - let style = PageStyleActor { - name: registry.new_name("pageStyle"), - script_chan: self.script_chan.clone(), - pipeline: self.pipeline, - }; - let mut pageStyle = self.pageStyle.borrow_mut(); - *pageStyle = Some(style.name()); - registry.register_later(Box::new(style)); - } - - let msg = GetPageStyleReply { - from: self.name(), - pageStyle: PageStyleMsg { - actor: self.pageStyle.borrow().clone().unwrap(), - }, - }; - stream.write_json_packet(&msg); - ActorMessageStatus::Processed - } - - //TODO: this is an old message; try adding highlightable to the root traits instead - // and support getHighlighter instead - //"highlight" => {} - "getHighlighter" => { - if self.highlighter.borrow().is_none() { - let highlighter_actor = HighlighterActor { - name: registry.new_name("highlighter"), - }; - let mut highlighter = self.highlighter.borrow_mut(); - *highlighter = Some(highlighter_actor.name()); - registry.register_later(Box::new(highlighter_actor)); - } - - let msg = GetHighlighterReply { - from: self.name(), - highligter: HighlighterMsg { - actor: self.highlighter.borrow().clone().unwrap(), - }, - }; - stream.write_json_packet(&msg); - ActorMessageStatus::Processed - } - - _ => ActorMessageStatus::Ignored, - }) - } -} diff --git a/servo/components/devtools/actors/memory.rs b/servo/components/devtools/actors/memory.rs deleted file mode 100644 index 518358ea69b9..000000000000 --- a/servo/components/devtools/actors/memory.rs +++ /dev/null @@ -1,66 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -use actor::{Actor, ActorMessageStatus, ActorRegistry}; -use serde_json::{Map, Value}; -use std::net::TcpStream; - -#[derive(Serialize)] -pub struct TimelineMemoryReply { - jsObjectSize: u64, - jsStringSize: u64, - jsOtherSize: u64, - domSize: u64, - styleSize: u64, - otherSize: u64, - totalSize: u64, - jsMilliseconds: f64, - nonJSMilliseconds: f64, -} - -pub struct MemoryActor { - pub name: String, -} - -impl Actor for MemoryActor { - fn name(&self) -> String { - self.name.clone() - } - - fn handle_message(&self, - _registry: &ActorRegistry, - _msg_type: &str, - _msg: &Map, - _stream: &mut TcpStream) -> Result { - Ok(ActorMessageStatus::Ignored) - } -} - -impl MemoryActor { - /// return name of actor - pub fn create(registry: &ActorRegistry) -> String { - let actor_name = registry.new_name("memory"); - let actor = MemoryActor { - name: actor_name.clone() - }; - - registry.register_later(Box::new(actor)); - actor_name - } - - pub fn measure(&self) -> TimelineMemoryReply { - //TODO: - TimelineMemoryReply { - jsObjectSize: 1, - jsStringSize: 1, - jsOtherSize: 1, - domSize: 1, - styleSize: 1, - otherSize: 1, - totalSize: 1, - jsMilliseconds: 1.1, - nonJSMilliseconds: 1.1, - } - } -} diff --git a/servo/components/devtools/actors/network_event.rs b/servo/components/devtools/actors/network_event.rs deleted file mode 100644 index 0906971821a6..000000000000 --- a/servo/components/devtools/actors/network_event.rs +++ /dev/null @@ -1,469 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -//! Liberally derived from the [Firefox JS implementation] -//! (http://mxr.mozilla.org/mozilla-central/source/toolkit/devtools/server/actors/webconsole.js). -//! Handles interaction with the remote web console on network events (HTTP requests, responses) in Servo. - -use actor::{Actor, ActorMessageStatus, ActorRegistry}; -use devtools_traits::HttpRequest as DevtoolsHttpRequest; -use devtools_traits::HttpResponse as DevtoolsHttpResponse; -use hyper::header::{ContentType, Cookie}; -use hyper::header::Headers; -use hyper::http::RawStatus; -use hyper::method::Method; -use protocol::JsonPacketStream; -use serde_json::{Map, Value}; -use std::borrow::Cow; -use std::net::TcpStream; -use time; -use time::Tm; - -struct HttpRequest { - url: String, - method: Method, - headers: Headers, - body: Option>, - startedDateTime: Tm, - timeStamp: i64, - connect_time: u64, - send_time: u64, -} - -struct HttpResponse { - headers: Option, - status: Option, - body: Option> -} - -pub struct NetworkEventActor { - pub name: String, - request: HttpRequest, - response: HttpResponse, - is_xhr: bool, -} - -#[derive(Serialize)] -pub struct EventActor { - pub actor: String, - pub url: String, - pub method: String, - pub startedDateTime: String, - pub timeStamp: i64, - pub isXHR: bool, - pub private: bool -} - -#[derive(Serialize)] -pub struct ResponseCookiesMsg { - pub cookies: usize, -} - -#[derive(Serialize)] -pub struct ResponseStartMsg { - pub httpVersion: String, - pub remoteAddress: String, - pub remotePort: u32, - pub status: String, - pub statusText: String, - pub headersSize: usize, - pub discardResponseBody: bool, -} - -#[derive(Serialize)] -pub struct ResponseContentMsg { - pub mimeType: String, - pub contentSize: u32, - pub transferredSize: u32, - pub discardResponseBody: bool, -} - - -#[derive(Serialize)] -pub struct ResponseHeadersMsg { - pub headers: usize, - pub headersSize: usize, -} - - -#[derive(Serialize)] -pub struct RequestCookiesMsg { - pub cookies: usize, -} - -#[derive(Serialize)] -pub struct RequestHeadersMsg { - headers: usize, - headersSize: usize, -} - -#[derive(Serialize)] -struct GetRequestHeadersReply { - from: String, - headers: Vec
, - headerSize: usize, - rawHeaders: String -} - -#[derive(Serialize)] -struct Header { - name: String, - value: String, -} - -#[derive(Serialize)] -struct GetResponseHeadersReply { - from: String, - headers: Vec
, - headerSize: usize, - rawHeaders: String -} - -#[derive(Serialize)] -struct GetResponseContentReply { - from: String, - content: Option>, - contentDiscarded: bool, -} - -#[derive(Serialize)] -struct GetRequestPostDataReply { - from: String, - postData: Option>, - postDataDiscarded: bool -} - -#[derive(Serialize)] -struct GetRequestCookiesReply { - from: String, - cookies: Vec -} - -#[derive(Serialize)] -struct GetResponseCookiesReply { - from: String, - cookies: Vec -} - -#[derive(Serialize)] -struct Timings { - blocked: u32, - dns: u32, - connect: u64, - send: u64, - wait: u32, - receive: u32, -} - -#[derive(Serialize)] -struct GetEventTimingsReply { - from: String, - timings: Timings, - totalTime: u64, -} - -#[derive(Serialize)] -struct SecurityInfo { - state: String, -} - -#[derive(Serialize)] -struct GetSecurityInfoReply { - from: String, - securityInfo: SecurityInfo, -} - -impl Actor for NetworkEventActor { - fn name(&self) -> String { - self.name.clone() - } - - fn handle_message(&self, - _registry: &ActorRegistry, - msg_type: &str, - _msg: &Map, - stream: &mut TcpStream) -> Result { - Ok(match msg_type { - "getRequestHeaders" => { - let mut headers = Vec::new(); - let mut rawHeadersString = "".to_owned(); - let mut headersSize = 0; - for item in self.request.headers.iter() { - let name = item.name(); - let value = item.value_string(); - rawHeadersString = rawHeadersString + name + ":" + &value + "\r\n"; - headersSize += name.len() + value.len(); - headers.push(Header { name: name.to_owned(), value: value.to_owned() }); - } - let msg = GetRequestHeadersReply { - from: self.name(), - headers: headers, - headerSize: headersSize, - rawHeaders: rawHeadersString, - }; - stream.write_json_packet(&msg); - ActorMessageStatus::Processed - } - "getRequestCookies" => { - let mut cookies = Vec::new(); - if let Some(req_cookies) = self.request.headers.get_raw("Cookie") { - for cookie in &*req_cookies { - if let Ok(cookie_value) = String::from_utf8(cookie.clone()) { - cookies = cookie_value.into_bytes(); - } - } - } - - let msg = GetRequestCookiesReply { - from: self.name(), - cookies: cookies, - }; - stream.write_json_packet(&msg); - ActorMessageStatus::Processed - } - "getRequestPostData" => { - let msg = GetRequestPostDataReply { - from: self.name(), - postData: self.request.body.clone(), - postDataDiscarded: false, - }; - stream.write_json_packet(&msg); - ActorMessageStatus::Processed - } - "getResponseHeaders" => { - if let Some(ref response_headers) = self.response.headers { - let mut headers = vec![]; - let mut rawHeadersString = "".to_owned(); - let mut headersSize = 0; - for item in response_headers.iter() { - let name = item.name(); - let value = item.value_string(); - headers.push(Header { - name: name.to_owned(), - value: value.clone(), - }); - headersSize += name.len() + value.len(); - rawHeadersString.push_str(name); - rawHeadersString.push_str(":"); - rawHeadersString.push_str(&value); - rawHeadersString.push_str("\r\n"); - } - let msg = GetResponseHeadersReply { - from: self.name(), - headers: headers, - headerSize: headersSize, - rawHeaders: rawHeadersString, - }; - stream.write_json_packet(&msg); - } - ActorMessageStatus::Processed - } - "getResponseCookies" => { - let mut cookies = Vec::new(); - if let Some(res_cookies) = self.request.headers.get_raw("set-cookie") { - for cookie in &*res_cookies { - if let Ok(cookie_value) = String::from_utf8(cookie.clone()) { - cookies = cookie_value.into_bytes(); - } - } - } - - let msg = GetResponseCookiesReply { - from: self.name(), - cookies: cookies, - }; - stream.write_json_packet(&msg); - ActorMessageStatus::Processed - } - "getResponseContent" => { - let msg = GetResponseContentReply { - from: self.name(), - content: self.response.body.clone(), - contentDiscarded: self.response.body.is_none(), - }; - stream.write_json_packet(&msg); - ActorMessageStatus::Processed - } - "getEventTimings" => { - // TODO: This is a fake timings msg - let timingsObj = Timings { - blocked: 0, - dns: 0, - connect: self.request.connect_time, - send: self.request.send_time, - wait: 0, - receive: 0, - }; - let total = timingsObj.connect + timingsObj.send; - // TODO: Send the correct values for all these fields. - let msg = GetEventTimingsReply { - from: self.name(), - timings: timingsObj, - totalTime: total, - }; - stream.write_json_packet(&msg); - ActorMessageStatus::Processed - } - "getSecurityInfo" => { - // TODO: Send the correct values for securityInfo. - let msg = GetSecurityInfoReply { - from: self.name(), - securityInfo: SecurityInfo { - state: "insecure".to_owned() - }, - }; - stream.write_json_packet(&msg); - ActorMessageStatus::Processed - } - _ => ActorMessageStatus::Ignored - }) - } -} - -impl NetworkEventActor { - pub fn new(name: String) -> NetworkEventActor { - NetworkEventActor { - name: name, - request: HttpRequest { - url: String::new(), - method: Method::Get, - headers: Headers::new(), - body: None, - startedDateTime: time::now(), - timeStamp: time::get_time().sec, - send_time: 0, - connect_time: 0, - }, - response: HttpResponse { - headers: None, - status: None, - body: None, - }, - is_xhr: false, - } - } - - pub fn add_request(&mut self, request: DevtoolsHttpRequest) { - self.request.url = request.url.as_str().to_owned(); - self.request.method = request.method.clone(); - self.request.headers = request.headers.clone(); - self.request.body = request.body; - self.request.startedDateTime = request.startedDateTime; - self.request.timeStamp = request.timeStamp; - self.request.connect_time = request.connect_time; - self.request.send_time = request.send_time; - self.is_xhr = request.is_xhr; - } - - pub fn add_response(&mut self, response: DevtoolsHttpResponse) { - self.response.headers = response.headers.clone(); - self.response.status = response.status.as_ref().map(|&(s, ref st)| { - let status_text = String::from_utf8_lossy(st).into_owned(); - RawStatus(s, Cow::from(status_text)) - }); - self.response.body = response.body.clone(); - } - - pub fn event_actor(&self) -> EventActor { - // TODO: Send the correct values for startedDateTime, isXHR, private - EventActor { - actor: self.name(), - url: self.request.url.clone(), - method: format!("{}", self.request.method), - startedDateTime: format!("{}", self.request.startedDateTime.rfc3339()), - timeStamp: self.request.timeStamp, - isXHR: self.is_xhr, - private: false, - } - } - - pub fn response_start(&self) -> ResponseStartMsg { - // TODO: Send the correct values for all these fields. - let hSizeOption = self.response.headers.as_ref().map(|headers| headers.len()); - let hSize = hSizeOption.unwrap_or(0); - let (status_code, status_message) = self.response.status.as_ref(). - map_or((0, "".to_owned()), |&RawStatus(ref code, ref text)| (*code, text.clone().into_owned())); - // TODO: Send the correct values for remoteAddress and remotePort and http_version. - ResponseStartMsg { - httpVersion: "HTTP/1.1".to_owned(), - remoteAddress: "63.245.217.43".to_owned(), - remotePort: 443, - status: status_code.to_string(), - statusText: status_message, - headersSize: hSize, - discardResponseBody: false - } - } - - pub fn response_content(&self) -> ResponseContentMsg { - let mut mString = "".to_owned(); - if let Some(ref headers) = self.response.headers { - mString = match headers.get() { - Some(&ContentType(ref mime)) => mime.to_string(), - None => "".to_owned() - }; - } - // TODO: Set correct values when response's body is sent to the devtools in http_loader. - ResponseContentMsg { - mimeType: mString, - contentSize: 0, - transferredSize: 0, - discardResponseBody: true, - } - } - - pub fn response_cookies(&self) -> ResponseCookiesMsg { - let mut cookies_size = 0; - if let Some(ref headers) = self.response.headers { - cookies_size = match headers.get() { - Some(&Cookie(ref cookie)) => cookie.len(), - None => 0 - }; - } - ResponseCookiesMsg { - cookies: cookies_size, - } - } - - pub fn response_headers(&self) -> ResponseHeadersMsg { - let mut headers_size = 0; - let mut headers_byte_count = 0; - if let Some(ref headers) = self.response.headers { - headers_size = headers.len(); - for item in headers.iter() { - headers_byte_count += item.name().len() + item.value_string().len(); - } - - } - ResponseHeadersMsg { - headers: headers_size, - headersSize: headers_byte_count, - } - } - - pub fn request_headers(&self) -> RequestHeadersMsg { - let size = self.request - .headers - .iter() - .fold(0, |acc, h| acc + h.name().len() + h.value_string().len()); - RequestHeadersMsg { - headers: self.request.headers.len(), - headersSize: size, - } - } - - pub fn request_cookies(&self) -> RequestCookiesMsg { - let cookies_size = match self.request.headers.get() { - Some(&Cookie(ref cookie)) => cookie.len(), - None => 0 - }; - RequestCookiesMsg { - cookies: cookies_size, - } - } - - pub fn total_time(&self) -> u64 { - self.request.connect_time + self.request.send_time - } -} diff --git a/servo/components/devtools/actors/object.rs b/servo/components/devtools/actors/object.rs deleted file mode 100644 index 943adf8b5fcd..000000000000 --- a/servo/components/devtools/actors/object.rs +++ /dev/null @@ -1,44 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -use actor::{Actor, ActorMessageStatus, ActorRegistry}; -use serde_json::{Map, Value}; -use std::net::TcpStream; - -pub struct ObjectActor { - pub name: String, - pub uuid: String, -} - -impl Actor for ObjectActor { - fn name(&self) -> String { - self.name.clone() - } - fn handle_message(&self, - _: &ActorRegistry, - _: &str, - _: &Map, - _: &mut TcpStream) -> Result { - Ok(ActorMessageStatus::Ignored) - } -} - -impl ObjectActor { - pub fn new(registry: &ActorRegistry, uuid: String) -> String { - if !registry.script_actor_registered(uuid.clone()) { - let name = registry.new_name("object"); - let actor = ObjectActor { - name: name.clone(), - uuid: uuid.clone(), - }; - - registry.register_script_actor(uuid, name.clone()); - registry.register_later(Box::new(actor)); - - name - } else { - registry.script_to_actor(uuid) - } - } -} diff --git a/servo/components/devtools/actors/performance.rs b/servo/components/devtools/actors/performance.rs deleted file mode 100644 index c246cb26fa44..000000000000 --- a/servo/components/devtools/actors/performance.rs +++ /dev/null @@ -1,118 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -use actor::{Actor, ActorMessageStatus, ActorRegistry}; -use protocol::{ActorDescription, JsonPacketStream, Method}; -use serde_json::{Map, Value}; -use std::net::TcpStream; - -pub struct PerformanceActor { - name: String, -} - -#[derive(Serialize)] -struct PerformanceFeatures { - withMarkers: bool, - withMemory: bool, - withTicks: bool, - withAllocations: bool, - withJITOptimizations: bool, -} - -#[derive(Serialize)] -struct PerformanceTraits { - features: PerformanceFeatures, -} - -#[derive(Serialize)] -struct ConnectReply { - from: String, - traits: PerformanceTraits, -} - -#[derive(Serialize)] -struct CanCurrentlyRecordReply { - from: String, - value: SuccessMsg, -} - -#[derive(Serialize)] -struct SuccessMsg { - success: bool, - errors: Vec, -} - -#[derive(Serialize)] -enum Error {} - -impl Actor for PerformanceActor { - fn name(&self) -> String { - self.name.clone() - } - - fn handle_message(&self, - _registry: &ActorRegistry, - msg_type: &str, - _msg: &Map, - stream: &mut TcpStream) -> Result { - Ok(match msg_type { - "connect" => { - let msg = ConnectReply { - from: self.name(), - traits: PerformanceTraits { - features: PerformanceFeatures { - withMarkers: true, - withMemory: true, - withTicks: true, - withAllocations: true, - withJITOptimizations: true, - }, - }, - }; - stream.write_json_packet(&msg); - ActorMessageStatus::Processed - }, - "canCurrentlyRecord" => { - let msg = CanCurrentlyRecordReply { - from: self.name(), - value: SuccessMsg { - success: true, - errors: vec![], - } - }; - stream.write_json_packet(&msg); - ActorMessageStatus::Processed - } - _ => ActorMessageStatus::Ignored, - }) - } -} - -impl PerformanceActor { - pub fn new(name: String) -> PerformanceActor { - PerformanceActor { - name: name, - } - } - - pub fn description() -> ActorDescription { - ActorDescription { - category: "actor", - typeName: "performance", - methods: vec![ - Method { - name: "canCurrentlyRecord", - request: Value::Object(vec![ - ("type".to_owned(), Value::String("canCurrentlyRecord".to_owned())), - ].into_iter().collect()), - response: Value::Object(vec![ - ("value".to_owned(), Value::Object(vec![ - ("_retval".to_owned(), Value::String("json".to_owned())), - ].into_iter().collect())), - ].into_iter().collect()), - }, - ], - } - } -} diff --git a/servo/components/devtools/actors/profiler.rs b/servo/components/devtools/actors/profiler.rs deleted file mode 100644 index a80e3c0018bc..000000000000 --- a/servo/components/devtools/actors/profiler.rs +++ /dev/null @@ -1,33 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -use actor::{Actor, ActorMessageStatus, ActorRegistry}; -use serde_json::{Map, Value}; -use std::net::TcpStream; - -pub struct ProfilerActor { - name: String, -} - -impl Actor for ProfilerActor { - fn name(&self) -> String { - self.name.clone() - } - - fn handle_message(&self, - _registry: &ActorRegistry, - _msg_type: &str, - _msg: &Map, - _stream: &mut TcpStream) -> Result { - Ok(ActorMessageStatus::Ignored) - } -} - -impl ProfilerActor { - pub fn new(name: String) -> ProfilerActor { - ProfilerActor { - name: name, - } - } -} diff --git a/servo/components/devtools/actors/root.rs b/servo/components/devtools/actors/root.rs deleted file mode 100644 index 20629ea7a7b8..000000000000 --- a/servo/components/devtools/actors/root.rs +++ /dev/null @@ -1,125 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -/// Liberally derived from the [Firefox JS implementation] -/// (http://mxr.mozilla.org/mozilla-central/source/toolkit/devtools/server/actors/root.js). -/// Connection point for all new remote devtools interactions, providing lists of know actors -/// that perform more specific actions (tabs, addons, browser chrome, etc.) - -use actor::{Actor, ActorMessageStatus, ActorRegistry}; -use actors::performance::PerformanceActor; -use actors::tab::{TabActor, TabActorMsg}; -use protocol::{ActorDescription, JsonPacketStream}; -use serde_json::{Map, Value}; -use std::net::TcpStream; - -#[derive(Serialize)] -struct ActorTraits { - sources: bool, - highlightable: bool, - customHighlighters: bool, - networkMonitor: bool, -} - -#[derive(Serialize)] -struct ListAddonsReply { - from: String, - addons: Vec, -} - -#[derive(Serialize)] -enum AddonMsg {} - -#[derive(Serialize)] -struct ListTabsReply { - from: String, - selected: u32, - tabs: Vec, -} - -#[derive(Serialize)] -pub struct RootActorMsg { - from: String, - applicationType: String, - traits: ActorTraits, -} - -#[derive(Serialize)] -pub struct ProtocolDescriptionReply { - from: String, - types: Types, -} - -#[derive(Serialize)] -pub struct Types { - performance: ActorDescription, -} - -pub struct RootActor { - pub tabs: Vec, -} - -impl Actor for RootActor { - fn name(&self) -> String { - "root".to_owned() - } - - fn handle_message(&self, - registry: &ActorRegistry, - msg_type: &str, - _msg: &Map, - stream: &mut TcpStream) -> Result { - Ok(match msg_type { - "listAddons" => { - let actor = ListAddonsReply { - from: "root".to_owned(), - addons: vec![], - }; - stream.write_json_packet(&actor); - ActorMessageStatus::Processed - } - - //https://wiki.mozilla.org/Remote_Debugging_Protocol#Listing_Browser_Tabs - "listTabs" => { - let actor = ListTabsReply { - from: "root".to_owned(), - selected: 0, - tabs: self.tabs.iter().map(|tab| { - registry.find::(tab).encodable() - }).collect() - }; - stream.write_json_packet(&actor); - ActorMessageStatus::Processed - } - - "protocolDescription" => { - let msg = ProtocolDescriptionReply { - from: self.name(), - types: Types { - performance: PerformanceActor::description(), - }, - }; - stream.write_json_packet(&msg); - ActorMessageStatus::Processed - } - - _ => ActorMessageStatus::Ignored - }) - } -} - -impl RootActor { - pub fn encodable(&self) -> RootActorMsg { - RootActorMsg { - from: "root".to_owned(), - applicationType: "browser".to_owned(), - traits: ActorTraits { - sources: true, - highlightable: true, - customHighlighters: true, - networkMonitor: true - }, - } - } -} diff --git a/servo/components/devtools/actors/tab.rs b/servo/components/devtools/actors/tab.rs deleted file mode 100644 index 916c53193868..000000000000 --- a/servo/components/devtools/actors/tab.rs +++ /dev/null @@ -1,169 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -//! Liberally derived from the [Firefox JS implementation] -//! (http://mxr.mozilla.org/mozilla-central/source/toolkit/devtools/server/actors/webbrowser.js). -//! Connection point for remote devtools that wish to investigate a particular tab's contents. -//! Supports dynamic attaching and detaching which control notifications of navigation, etc. - -use actor::{Actor, ActorMessageStatus, ActorRegistry}; -use actors::console::ConsoleActor; -use devtools_traits::DevtoolScriptControlMsg::{self, WantsLiveNotifications}; -use protocol::JsonPacketStream; -use serde_json::{Map, Value}; -use std::net::TcpStream; - -#[derive(Serialize)] -struct TabTraits; - -#[derive(Serialize)] -struct TabAttachedReply { - from: String, - #[serde(rename = "type")] - type_: String, - threadActor: String, - cacheDisabled: bool, - javascriptEnabled: bool, - traits: TabTraits, -} - -#[derive(Serialize)] -struct TabDetachedReply { - from: String, - #[serde(rename = "type")] - type_: String, -} - -#[derive(Serialize)] -struct ReconfigureReply { - from: String -} - -#[derive(Serialize)] -struct ListFramesReply { - from: String, - frames: Vec, -} - -#[derive(Serialize)] -struct FrameMsg { - id: u32, - url: String, - title: String, - parentID: u32, -} - -#[derive(Serialize)] -pub struct TabActorMsg { - actor: String, - title: String, - url: String, - outerWindowID: u32, - consoleActor: String, - inspectorActor: String, - timelineActor: String, - profilerActor: String, - performanceActor: String, -} - -pub struct TabActor { - pub name: String, - pub title: String, - pub url: String, - pub console: String, - pub inspector: String, - pub timeline: String, - pub profiler: String, - pub performance: String, - pub thread: String, -} - -impl Actor for TabActor { - fn name(&self) -> String { - self.name.clone() - } - - fn handle_message(&self, - registry: &ActorRegistry, - msg_type: &str, - msg: &Map, - stream: &mut TcpStream) -> Result { - Ok(match msg_type { - "reconfigure" => { - if let Some(options) = msg.get("options").and_then(|o| o.as_object()) { - if let Some(val) = options.get("performReload") { - if val.as_bool().unwrap_or(false) { - let console_actor = registry.find::(&self.console); - let _ = console_actor.script_chan.send( - DevtoolScriptControlMsg::Reload(console_actor.pipeline)); - } - } - } - stream.write_json_packet(&ReconfigureReply { from: self.name() }); - ActorMessageStatus::Processed - } - - // https://wiki.mozilla.org/Remote_Debugging_Protocol#Listing_Browser_Tabs - // (see "To attach to a _tabActor_") - "attach" => { - let msg = TabAttachedReply { - from: self.name(), - type_: "tabAttached".to_owned(), - threadActor: self.thread.clone(), - cacheDisabled: false, - javascriptEnabled: true, - traits: TabTraits, - }; - let console_actor = registry.find::(&self.console); - console_actor.streams.borrow_mut().push(stream.try_clone().unwrap()); - stream.write_json_packet(&msg); - console_actor.script_chan.send( - WantsLiveNotifications(console_actor.pipeline, true)).unwrap(); - ActorMessageStatus::Processed - } - - //FIXME: The current implementation won't work for multiple connections. Need to ensure 105 - // that the correct stream is removed. - "detach" => { - let msg = TabDetachedReply { - from: self.name(), - type_: "detached".to_owned(), - }; - let console_actor = registry.find::(&self.console); - console_actor.streams.borrow_mut().pop(); - stream.write_json_packet(&msg); - console_actor.script_chan.send( - WantsLiveNotifications(console_actor.pipeline, false)).unwrap(); - ActorMessageStatus::Processed - } - - "listFrames" => { - let msg = ListFramesReply { - from: self.name(), - frames: vec!(), - }; - stream.write_json_packet(&msg); - ActorMessageStatus::Processed - } - - _ => ActorMessageStatus::Ignored - }) - } -} - -impl TabActor { - pub fn encodable(&self) -> TabActorMsg { - TabActorMsg { - actor: self.name(), - title: self.title.clone(), - url: self.url.clone(), - outerWindowID: 0, //FIXME: this should probably be the pipeline id - consoleActor: self.console.clone(), - inspectorActor: self.inspector.clone(), - timelineActor: self.timeline.clone(), - profilerActor: self.profiler.clone(), - performanceActor: self.performance.clone(), - } - } -} diff --git a/servo/components/devtools/actors/thread.rs b/servo/components/devtools/actors/thread.rs deleted file mode 100644 index 7be5bc55f232..000000000000 --- a/servo/components/devtools/actors/thread.rs +++ /dev/null @@ -1,111 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -use actor::{Actor, ActorMessageStatus, ActorRegistry}; -use protocol::JsonPacketStream; -use serde_json::{Map, Value}; -use std::net::TcpStream; - -#[derive(Serialize)] -struct ThreadAttachedReply { - from: String, - #[serde(rename = "type")] - type_: String, - actor: String, - poppedFrames: Vec, - why: WhyMsg, -} - -#[derive(Serialize)] -enum PoppedFrameMsg {} - -#[derive(Serialize)] -struct WhyMsg { - #[serde(rename = "type")] - type_: String, -} - -#[derive(Serialize)] -struct ThreadResumedReply { - from: String, - #[serde(rename = "type")] - type_: String, -} - -#[derive(Serialize)] -struct ReconfigureReply { - from: String -} - -#[derive(Serialize)] -struct SourcesReply { - from: String, - sources: Vec, -} - -#[derive(Serialize)] -enum Source {} - -pub struct ThreadActor { - name: String, -} - -impl ThreadActor { - pub fn new(name: String) -> ThreadActor { - ThreadActor { - name: name, - } - } -} - -impl Actor for ThreadActor { - fn name(&self) -> String { - self.name.clone() - } - - fn handle_message(&self, - registry: &ActorRegistry, - msg_type: &str, - _msg: &Map, - stream: &mut TcpStream) -> Result { - Ok(match msg_type { - "attach" => { - let msg = ThreadAttachedReply { - from: self.name(), - type_: "paused".to_owned(), - actor: registry.new_name("pause"), - poppedFrames: vec![], - why: WhyMsg { type_: "attached".to_owned() }, - }; - stream.write_json_packet(&msg); - ActorMessageStatus::Processed - }, - - "resume" => { - let msg = ThreadResumedReply { - from: self.name(), - type_: "resumed".to_owned(), - }; - stream.write_json_packet(&msg); - ActorMessageStatus::Processed - }, - - "reconfigure" => { - stream.write_json_packet(&ReconfigureReply { from: self.name() }); - ActorMessageStatus::Processed - } - - "sources" => { - let msg = SourcesReply { - from: self.name(), - sources: vec![], - }; - stream.write_json_packet(&msg); - ActorMessageStatus::Processed - } - - _ => ActorMessageStatus::Ignored, - }) - } -} diff --git a/servo/components/devtools/actors/timeline.rs b/servo/components/devtools/actors/timeline.rs deleted file mode 100644 index 0ea57ad8dbbe..000000000000 --- a/servo/components/devtools/actors/timeline.rs +++ /dev/null @@ -1,326 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -use actor::{Actor, ActorMessageStatus, ActorRegistry}; -use actors::framerate::FramerateActor; -use actors::memory::{MemoryActor, TimelineMemoryReply}; -use devtools_traits::{PreciseTime, TimelineMarker, TimelineMarkerType}; -use devtools_traits::DevtoolScriptControlMsg; -use devtools_traits::DevtoolScriptControlMsg::{DropTimelineMarkers, SetTimelineMarkers}; -use ipc_channel::ipc::{self, IpcReceiver, IpcSender}; -use msg::constellation_msg::PipelineId; -use protocol::JsonPacketStream; -use serde::{Serialize, Serializer}; -use serde_json::{Map, Value}; -use std::cell::RefCell; -use std::net::TcpStream; -use std::sync::{Arc, Mutex}; -use std::thread; -use std::time::Duration; - -pub struct TimelineActor { - name: String, - script_sender: IpcSender, - marker_types: Vec, - pipeline: PipelineId, - is_recording: Arc>, - stream: RefCell>, - - framerate_actor: RefCell>, - memory_actor: RefCell>, -} - -struct Emitter { - from: String, - stream: TcpStream, - registry: Arc>, - start_stamp: PreciseTime, - - framerate_actor: Option, - memory_actor: Option, -} - -#[derive(Serialize)] -struct IsRecordingReply { - from: String, - value: bool -} - -#[derive(Serialize)] -struct StartReply { - from: String, - value: HighResolutionStamp, -} - -#[derive(Serialize)] -struct StopReply { - from: String, - value: HighResolutionStamp, -} - -#[derive(Serialize)] -struct TimelineMarkerReply { - name: String, - start: HighResolutionStamp, - end: HighResolutionStamp, - stack: Option>, - endStack: Option>, -} - -#[derive(Serialize)] -struct MarkersEmitterReply { - #[serde(rename = "type")] - type_: String, - markers: Vec, - from: String, - endTime: HighResolutionStamp, -} - -#[derive(Serialize)] -struct MemoryEmitterReply { - #[serde(rename = "type")] - type_: String, - from: String, - delta: HighResolutionStamp, - measurement: TimelineMemoryReply, -} - -#[derive(Serialize)] -struct FramerateEmitterReply { - #[serde(rename = "type")] - type_: String, - from: String, - delta: HighResolutionStamp, - timestamps: Vec, -} - -/// HighResolutionStamp is struct that contains duration in milliseconds -/// with accuracy to microsecond that shows how much time has passed since -/// actor registry inited -/// analog https://w3c.github.io/hr-time/#sec-DOMHighResTimeStamp -pub struct HighResolutionStamp(f64); - -impl HighResolutionStamp { - pub fn new(start_stamp: PreciseTime, time: PreciseTime) -> HighResolutionStamp { - let duration = start_stamp.to(time).num_microseconds() - .expect("Too big duration in microseconds"); - HighResolutionStamp(duration as f64 / 1000 as f64) - } - - pub fn wrap(time: f64) -> HighResolutionStamp { - HighResolutionStamp(time) - } -} - -impl Serialize for HighResolutionStamp { - fn serialize(&self, s: S) -> Result { - self.0.serialize(s) - } -} - -static DEFAULT_TIMELINE_DATA_PULL_TIMEOUT: u64 = 200; //ms - -impl TimelineActor { - pub fn new(name: String, - pipeline: PipelineId, - script_sender: IpcSender) -> TimelineActor { - let marker_types = vec!(TimelineMarkerType::Reflow, - TimelineMarkerType::DOMEvent); - - TimelineActor { - name: name, - pipeline: pipeline, - marker_types: marker_types, - script_sender: script_sender, - is_recording: Arc::new(Mutex::new(false)), - stream: RefCell::new(None), - - framerate_actor: RefCell::new(None), - memory_actor: RefCell::new(None), - } - } - - fn pull_timeline_data(&self, receiver: IpcReceiver>, mut emitter: Emitter) { - let is_recording = self.is_recording.clone(); - - if !*is_recording.lock().unwrap() { - return; - } - - thread::Builder::new().name("PullTimelineMarkers".to_owned()).spawn(move || { - loop { - if !*is_recording.lock().unwrap() { - break; - } - - let mut markers = vec![]; - while let Ok(Some(marker)) = receiver.try_recv() { - markers.push(emitter.marker(marker)); - } - emitter.send(markers); - - thread::sleep(Duration::from_millis(DEFAULT_TIMELINE_DATA_PULL_TIMEOUT)); - } - }).expect("Thread spawning failed"); - } -} - -impl Actor for TimelineActor { - fn name(&self) -> String { - self.name.clone() - } - - fn handle_message(&self, - registry: &ActorRegistry, - msg_type: &str, - msg: &Map, - stream: &mut TcpStream) -> Result { - Ok(match msg_type { - "start" => { - **self.is_recording.lock().as_mut().unwrap() = true; - - let (tx, rx) = ipc::channel::>().unwrap(); - self.script_sender.send(SetTimelineMarkers(self.pipeline, - self.marker_types.clone(), - tx)).unwrap(); - - *self.stream.borrow_mut() = stream.try_clone().ok(); - - // init memory actor - if let Some(with_memory) = msg.get("withMemory") { - if let Some(true) = with_memory.as_bool() { - *self.memory_actor.borrow_mut() = Some(MemoryActor::create(registry)); - } - } - - // init framerate actor - if let Some(with_ticks) = msg.get("withTicks") { - if let Some(true) = with_ticks.as_bool() { - let framerate_actor = Some(FramerateActor::create( - registry, - self.pipeline.clone(), - self.script_sender.clone())); - *self.framerate_actor.borrow_mut() = framerate_actor; - } - } - - let emitter = Emitter::new(self.name(), registry.shareable(), - registry.start_stamp(), - stream.try_clone().unwrap(), - self.memory_actor.borrow().clone(), - self.framerate_actor.borrow().clone()); - - self.pull_timeline_data(rx, emitter); - - let msg = StartReply { - from: self.name(), - value: HighResolutionStamp::new(registry.start_stamp(), PreciseTime::now()), - }; - stream.write_json_packet(&msg); - ActorMessageStatus::Processed - } - - "stop" => { - let msg = StopReply { - from: self.name(), - value: HighResolutionStamp::new(registry.start_stamp(), PreciseTime::now()), - }; - - stream.write_json_packet(&msg); - self.script_sender.send(DropTimelineMarkers(self.pipeline, self.marker_types.clone())).unwrap(); - - if let Some(ref actor_name) = *self.framerate_actor.borrow() { - registry.drop_actor_later(actor_name.clone()); - } - - if let Some(ref actor_name) = *self.memory_actor.borrow() { - registry.drop_actor_later(actor_name.clone()); - } - - **self.is_recording.lock().as_mut().unwrap() = false; - self.stream.borrow_mut().take(); - ActorMessageStatus::Processed - } - - "isRecording" => { - let msg = IsRecordingReply { - from: self.name(), - value: self.is_recording.lock().unwrap().clone() - }; - - stream.write_json_packet(&msg); - ActorMessageStatus::Processed - } - - _ => { - ActorMessageStatus::Ignored - } - }) - } -} - -impl Emitter { - pub fn new(name: String, - registry: Arc>, - start_stamp: PreciseTime, - stream: TcpStream, - memory_actor_name: Option, - framerate_actor_name: Option) -> Emitter { - Emitter { - from: name, - stream: stream, - registry: registry, - start_stamp: start_stamp, - - framerate_actor: framerate_actor_name, - memory_actor: memory_actor_name, - } - } - - fn marker(&self, payload: TimelineMarker) -> TimelineMarkerReply { - TimelineMarkerReply { - name: payload.name, - start: HighResolutionStamp::new(self.start_stamp, payload.start_time), - end: HighResolutionStamp::new(self.start_stamp, payload.end_time), - stack: payload.start_stack, - endStack: payload.end_stack, - } - } - - fn send(&mut self, markers: Vec) { - let end_time = PreciseTime::now(); - let reply = MarkersEmitterReply { - type_: "markers".to_owned(), - markers: markers, - from: self.from.clone(), - endTime: HighResolutionStamp::new(self.start_stamp, end_time), - }; - self.stream.write_json_packet(&reply); - - if let Some(ref actor_name) = self.framerate_actor { - let mut lock = self.registry.lock(); - let registry = lock.as_mut().unwrap(); - let framerate_actor = registry.find_mut::(actor_name); - let framerateReply = FramerateEmitterReply { - type_: "framerate".to_owned(), - from: framerate_actor.name(), - delta: HighResolutionStamp::new(self.start_stamp, end_time), - timestamps: framerate_actor.take_pending_ticks(), - }; - self.stream.write_json_packet(&framerateReply); - } - - if let Some(ref actor_name) = self.memory_actor { - let registry = self.registry.lock().unwrap(); - let memory_actor = registry.find::(actor_name); - let memoryReply = MemoryEmitterReply { - type_: "memory".to_owned(), - from: memory_actor.name(), - delta: HighResolutionStamp::new(self.start_stamp, end_time), - measurement: memory_actor.measure(), - }; - self.stream.write_json_packet(&memoryReply); - } - } -} diff --git a/servo/components/devtools/actors/worker.rs b/servo/components/devtools/actors/worker.rs deleted file mode 100644 index 1beead719dcc..000000000000 --- a/servo/components/devtools/actors/worker.rs +++ /dev/null @@ -1,27 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -use actor::{Actor, ActorMessageStatus, ActorRegistry}; -use devtools_traits::WorkerId; -use serde_json::{Map, Value}; -use std::net::TcpStream; - -pub struct WorkerActor { - pub name: String, - pub console: String, - pub id: WorkerId, -} - -impl Actor for WorkerActor { - fn name(&self) -> String { - self.name.clone() - } - fn handle_message(&self, - _: &ActorRegistry, - _: &str, - _: &Map, - _: &mut TcpStream) -> Result { - Ok(ActorMessageStatus::Processed) - } -} diff --git a/servo/components/devtools/lib.rs b/servo/components/devtools/lib.rs deleted file mode 100644 index 31a98d7d5a69..000000000000 --- a/servo/components/devtools/lib.rs +++ /dev/null @@ -1,535 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -//! An actor-based remote devtools server implementation. Only tested with -//! nightly Firefox versions at time of writing. Largely based on -//! reverse-engineering of Firefox chrome devtool logs and reading of -//! [code](http://mxr.mozilla.org/mozilla-central/source/toolkit/devtools/server/). - -#![crate_name = "devtools"] -#![crate_type = "rlib"] - -#![allow(non_snake_case)] -#![deny(unsafe_code)] - -extern crate devtools_traits; -extern crate hyper; -extern crate ipc_channel; -#[macro_use] -extern crate log; -extern crate msg; -#[macro_use] extern crate serde; -extern crate serde_json; -extern crate time; - -use actor::{Actor, ActorRegistry}; -use actors::console::ConsoleActor; -use actors::framerate::FramerateActor; -use actors::inspector::InspectorActor; -use actors::network_event::{EventActor, NetworkEventActor, ResponseStartMsg}; -use actors::performance::PerformanceActor; -use actors::profiler::ProfilerActor; -use actors::root::RootActor; -use actors::tab::TabActor; -use actors::thread::ThreadActor; -use actors::timeline::TimelineActor; -use actors::worker::WorkerActor; -use devtools_traits::{ChromeToDevtoolsControlMsg, ConsoleMessage, DevtoolsControlMsg}; -use devtools_traits::{DevtoolScriptControlMsg, DevtoolsPageInfo, LogLevel, NetworkEvent}; -use devtools_traits::{ScriptToDevtoolsControlMsg, WorkerId}; -use ipc_channel::ipc::IpcSender; -use msg::constellation_msg::PipelineId; -use protocol::JsonPacketStream; -use std::borrow::ToOwned; -use std::cell::RefCell; -use std::collections::HashMap; -use std::collections::hash_map::Entry::{Occupied, Vacant}; -use std::net::{Shutdown, TcpListener, TcpStream}; -use std::sync::{Arc, Mutex}; -use std::sync::mpsc::{Receiver, Sender, channel}; -use std::thread; -use time::precise_time_ns; - -mod actor; -/// Corresponds to http://mxr.mozilla.org/mozilla-central/source/toolkit/devtools/server/actors/ -mod actors { - pub mod console; - pub mod framerate; - pub mod inspector; - pub mod memory; - pub mod network_event; - pub mod object; - pub mod performance; - pub mod profiler; - pub mod root; - pub mod tab; - pub mod thread; - pub mod timeline; - pub mod worker; -} -mod protocol; - -#[derive(Serialize)] -struct ConsoleAPICall { - from: String, - #[serde(rename = "type")] - type_: String, - message: ConsoleMsg, -} - -#[derive(Serialize)] -struct ConsoleMsg { - level: String, - timeStamp: u64, - arguments: Vec, - filename: String, - lineNumber: usize, - columnNumber: usize, -} - -#[derive(Serialize)] -struct NetworkEventMsg { - from: String, - #[serde(rename = "type")] - type_: String, - eventActor: EventActor, -} - -#[derive(Serialize)] -struct NetworkEventUpdateMsg { - from: String, - #[serde(rename = "type")] - type_: String, - updateType: String, -} - -#[derive(Serialize)] -struct EventTimingsUpdateMsg { - totalTime: u64, -} - -#[derive(Serialize)] -struct SecurityInfoUpdateMsg { - state: String, -} - -#[derive(Serialize)] -struct ResponseStartUpdateMsg { - from: String, - #[serde(rename = "type")] - type_: String, - updateType: String, - response: ResponseStartMsg, -} - -/// Spin up a devtools server that listens for connections on the specified port. -pub fn start_server(port: u16) -> Sender { - let (sender, receiver) = channel(); - { - let sender = sender.clone(); - thread::Builder::new().name("Devtools".to_owned()).spawn(move || { - run_server(sender, receiver, port) - }).expect("Thread spawning failed"); - } - sender -} - -fn run_server(sender: Sender, - receiver: Receiver, - port: u16) { - let listener = TcpListener::bind(&("127.0.0.1", port)).unwrap(); - - let mut registry = ActorRegistry::new(); - - let root = Box::new(RootActor { - tabs: vec!(), - }); - - registry.register(root); - registry.find::("root"); - - let actors = registry.create_shareable(); - - let mut accepted_connections: Vec = Vec::new(); - - let mut actor_pipelines: HashMap = HashMap::new(); - let mut actor_requests: HashMap = HashMap::new(); - - let mut actor_workers: HashMap<(PipelineId, WorkerId), String> = HashMap::new(); - - - /// Process the input from a single devtools client until EOF. - fn handle_client(actors: Arc>, mut stream: TcpStream) { - debug!("connection established to {}", stream.peer_addr().unwrap()); - { - let actors = actors.lock().unwrap(); - let msg = actors.find::("root").encodable(); - stream.write_json_packet(&msg); - } - - 'outer: loop { - match stream.read_json_packet() { - Ok(Some(json_packet)) => { - if let Err(()) = actors.lock().unwrap().handle_message(json_packet.as_object().unwrap(), - &mut stream) { - debug!("error: devtools actor stopped responding"); - let _ = stream.shutdown(Shutdown::Both); - break 'outer - } - } - Ok(None) => { - debug!("error: EOF"); - break 'outer - } - Err(err_msg) => { - debug!("error: {}", err_msg); - break 'outer - } - } - } - } - - fn handle_framerate_tick(actors: Arc>, actor_name: String, tick: f64) { - let mut actors = actors.lock().unwrap(); - let framerate_actor = actors.find_mut::(&actor_name); - framerate_actor.add_tick(tick); - } - - // We need separate actor representations for each script global that exists; - // clients can theoretically connect to multiple globals simultaneously. - // TODO: move this into the root or tab modules? - fn handle_new_global(actors: Arc>, - ids: (PipelineId, Option), - script_sender: IpcSender, - actor_pipelines: &mut HashMap, - actor_workers: &mut HashMap<(PipelineId, WorkerId), String>, - page_info: DevtoolsPageInfo) { - let mut actors = actors.lock().unwrap(); - - let (pipeline, worker_id) = ids; - - //TODO: move all this actor creation into a constructor method on TabActor - let (tab, console, inspector, timeline, profiler, performance, thread) = { - let console = ConsoleActor { - name: actors.new_name("console"), - script_chan: script_sender.clone(), - pipeline: pipeline, - streams: RefCell::new(Vec::new()), - }; - let inspector = InspectorActor { - name: actors.new_name("inspector"), - walker: RefCell::new(None), - pageStyle: RefCell::new(None), - highlighter: RefCell::new(None), - script_chan: script_sender.clone(), - pipeline: pipeline, - }; - - let timeline = TimelineActor::new(actors.new_name("timeline"), - pipeline, - script_sender); - - let profiler = ProfilerActor::new(actors.new_name("profiler")); - let performance = PerformanceActor::new(actors.new_name("performance")); - - let thread = ThreadActor::new(actors.new_name("context")); - - let DevtoolsPageInfo { title, url } = page_info; - let tab = TabActor { - name: actors.new_name("tab"), - title: String::from(title), - url: url.into_string(), - console: console.name(), - inspector: inspector.name(), - timeline: timeline.name(), - profiler: profiler.name(), - performance: performance.name(), - thread: thread.name(), - }; - - let root = actors.find_mut::("root"); - root.tabs.push(tab.name.clone()); - - (tab, console, inspector, timeline, profiler, performance, thread) - }; - - if let Some(id) = worker_id { - let worker = WorkerActor { - name: actors.new_name("worker"), - console: console.name(), - id: id, - }; - actor_workers.insert((pipeline, id), worker.name.clone()); - actors.register(Box::new(worker)); - } - - actor_pipelines.insert(pipeline, tab.name.clone()); - actors.register(Box::new(tab)); - actors.register(Box::new(console)); - actors.register(Box::new(inspector)); - actors.register(Box::new(timeline)); - actors.register(Box::new(profiler)); - actors.register(Box::new(performance)); - actors.register(Box::new(thread)); - } - - fn handle_console_message(actors: Arc>, - id: PipelineId, - worker_id: Option, - console_message: ConsoleMessage, - actor_pipelines: &HashMap, - actor_workers: &HashMap<(PipelineId, WorkerId), String>) { - let console_actor_name = match find_console_actor(actors.clone(), id, worker_id, actor_workers, - actor_pipelines) { - Some(name) => name, - None => return, - }; - let actors = actors.lock().unwrap(); - let console_actor = actors.find::(&console_actor_name); - let msg = ConsoleAPICall { - from: console_actor.name.clone(), - type_: "consoleAPICall".to_owned(), - message: ConsoleMsg { - level: match console_message.logLevel { - LogLevel::Debug => "debug", - LogLevel::Info => "info", - LogLevel::Warn => "warn", - LogLevel::Error => "error", - _ => "log" - }.to_owned(), - timeStamp: precise_time_ns(), - arguments: vec!(console_message.message), - filename: console_message.filename, - lineNumber: console_message.lineNumber, - columnNumber: console_message.columnNumber, - }, - }; - for stream in &mut *console_actor.streams.borrow_mut() { - stream.write_json_packet(&msg); - } - } - - fn find_console_actor(actors: Arc>, - id: PipelineId, - worker_id: Option, - actor_workers: &HashMap<(PipelineId, WorkerId), String>, - actor_pipelines: &HashMap) -> Option { - let actors = actors.lock().unwrap(); - if let Some(worker_id) = worker_id { - let actor_name = (*actor_workers).get(&(id, worker_id))?; - Some(actors.find::(actor_name).console.clone()) - } else { - let actor_name = (*actor_pipelines).get(&id)?; - Some(actors.find::(actor_name).console.clone()) - } - } - - fn handle_network_event(actors: Arc>, - mut connections: Vec, - actor_pipelines: &HashMap, - actor_requests: &mut HashMap, - actor_workers: &HashMap<(PipelineId, WorkerId), String>, - pipeline_id: PipelineId, - request_id: String, - network_event: NetworkEvent) { - let console_actor_name = match find_console_actor(actors.clone(), pipeline_id, None, - actor_workers, actor_pipelines) { - Some(name) => name, - None => return, - }; - let netevent_actor_name = find_network_event_actor(actors.clone(), actor_requests, request_id.clone()); - let mut actors = actors.lock().unwrap(); - let actor = actors.find_mut::(&netevent_actor_name); - - match network_event { - NetworkEvent::HttpRequest(httprequest) => { - //Store the request information in the actor - actor.add_request(httprequest); - - //Send a networkEvent message to the client - let msg = NetworkEventMsg { - from: console_actor_name, - type_: "networkEvent".to_owned(), - eventActor: actor.event_actor(), - }; - for stream in &mut connections { - stream.write_json_packet(&msg); - } - - } - NetworkEvent::HttpResponse(httpresponse) => { - //Store the response information in the actor - actor.add_response(httpresponse); - - let msg = NetworkEventUpdateMsg { - from: netevent_actor_name.clone(), - type_: "networkEventUpdate".to_owned(), - updateType: "requestHeaders".to_owned(), - }; - for stream in &mut connections { - stream.write_merged_json_packet(&msg, &actor.request_headers()); - } - - let msg = NetworkEventUpdateMsg { - from: netevent_actor_name.clone(), - type_: "networkEventUpdate".to_owned(), - updateType: "requestCookies".to_owned(), - }; - for stream in &mut connections { - stream.write_merged_json_packet(&msg, &actor.request_cookies()); - } - - //Send a networkEventUpdate (responseStart) to the client - let msg = ResponseStartUpdateMsg { - from: netevent_actor_name.clone(), - type_: "networkEventUpdate".to_owned(), - updateType: "responseStart".to_owned(), - response: actor.response_start() - }; - - for stream in &mut connections { - stream.write_json_packet(&msg); - } - let msg = NetworkEventUpdateMsg { - from: netevent_actor_name.clone(), - type_: "networkEventUpdate".to_owned(), - updateType: "eventTimings".to_owned(), - }; - let extra = EventTimingsUpdateMsg { - totalTime: actor.total_time(), - }; - for stream in &mut connections { - stream.write_merged_json_packet(&msg, &extra); - } - - let msg = NetworkEventUpdateMsg { - from: netevent_actor_name.clone(), - type_: "networkEventUpdate".to_owned(), - updateType: "securityInfo".to_owned(), - }; - let extra = SecurityInfoUpdateMsg { - state: "insecure".to_owned(), - }; - for stream in &mut connections { - stream.write_merged_json_packet(&msg, &extra); - } - - let msg = NetworkEventUpdateMsg { - from: netevent_actor_name.clone(), - type_: "networkEventUpdate".to_owned(), - updateType: "responseContent".to_owned(), - }; - for stream in &mut connections { - stream.write_merged_json_packet(&msg, &actor.response_content()); - } - - let msg = NetworkEventUpdateMsg { - from: netevent_actor_name.clone(), - type_: "networkEventUpdate".to_owned(), - updateType: "responseCookies".to_owned(), - }; - for stream in &mut connections { - stream.write_merged_json_packet(&msg, &actor.response_cookies()); - } - - let msg = NetworkEventUpdateMsg { - from: netevent_actor_name.clone(), - type_: "networkEventUpdate".to_owned(), - updateType: "responseHeaders".to_owned(), - }; - for stream in &mut connections { - stream.write_merged_json_packet(&msg, &actor.response_headers()); - } - } - } - } - - // Find the name of NetworkEventActor corresponding to request_id - // Create a new one if it does not exist, add it to the actor_requests hashmap - fn find_network_event_actor(actors: Arc>, - actor_requests: &mut HashMap, - request_id: String) -> String { - let mut actors = actors.lock().unwrap(); - match (*actor_requests).entry(request_id) { - Occupied(name) => { - //TODO: Delete from map like Firefox does? - name.into_mut().clone() - } - Vacant(entry) => { - let actor_name = actors.new_name("netevent"); - let actor = NetworkEventActor::new(actor_name.clone()); - entry.insert(actor_name.clone()); - actors.register(Box::new(actor)); - actor_name - } - } - } - - let sender_clone = sender.clone(); - thread::Builder::new().name("DevtoolsClientAcceptor".to_owned()).spawn(move || { - // accept connections and process them, spawning a new thread for each one - for stream in listener.incoming() { - // connection succeeded - sender_clone.send(DevtoolsControlMsg::FromChrome( - ChromeToDevtoolsControlMsg::AddClient(stream.unwrap()))).unwrap(); - } - }).expect("Thread spawning failed"); - - while let Ok(msg) = receiver.recv() { - match msg { - DevtoolsControlMsg::FromChrome(ChromeToDevtoolsControlMsg::AddClient(stream)) => { - let actors = actors.clone(); - accepted_connections.push(stream.try_clone().unwrap()); - thread::Builder::new().name("DevtoolsClientHandler".to_owned()).spawn(move || { - handle_client(actors, stream.try_clone().unwrap()) - }).expect("Thread spawning failed"); - } - DevtoolsControlMsg::FromScript(ScriptToDevtoolsControlMsg::FramerateTick( - actor_name, tick)) => - handle_framerate_tick(actors.clone(), actor_name, tick), - DevtoolsControlMsg::FromScript(ScriptToDevtoolsControlMsg::NewGlobal( - ids, script_sender, pageinfo)) => - handle_new_global(actors.clone(), ids, script_sender, &mut actor_pipelines, - &mut actor_workers, pageinfo), - DevtoolsControlMsg::FromScript(ScriptToDevtoolsControlMsg::ConsoleAPI( - id, - console_message, - worker_id)) => - handle_console_message(actors.clone(), id, worker_id, console_message, - &actor_pipelines, &actor_workers), - DevtoolsControlMsg::FromScript(ScriptToDevtoolsControlMsg::ReportCSSError( - id, - css_error)) => { - let console_message = ConsoleMessage { - message: css_error.msg, - logLevel: LogLevel::Warn, - filename: css_error.filename, - lineNumber: css_error.line as usize, - columnNumber: css_error.column as usize, - }; - handle_console_message(actors.clone(), id, None, console_message, - &actor_pipelines, &actor_workers) - }, - DevtoolsControlMsg::FromChrome(ChromeToDevtoolsControlMsg::NetworkEvent( - request_id, network_event)) => { - // copy the accepted_connections vector - let mut connections = Vec::::new(); - for stream in &accepted_connections { - connections.push(stream.try_clone().unwrap()); - } - - let pipeline_id = match network_event { - NetworkEvent::HttpResponse(ref response) => response.pipeline_id, - NetworkEvent::HttpRequest(ref request) => request.pipeline_id, - }; - handle_network_event(actors.clone(), connections, &actor_pipelines, &mut actor_requests, - &actor_workers, pipeline_id, request_id, network_event); - }, - DevtoolsControlMsg::FromChrome(ChromeToDevtoolsControlMsg::ServerExitMsg) => break - } - } - for connection in &mut accepted_connections { - let _ = connection.shutdown(Shutdown::Both); - } -} diff --git a/servo/components/devtools/protocol.rs b/servo/components/devtools/protocol.rs deleted file mode 100644 index f0bfce4b3d77..000000000000 --- a/servo/components/devtools/protocol.rs +++ /dev/null @@ -1,89 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -//! Low-level wire protocol implementation. Currently only supports -//! [JSON packets] -//! (https://wiki.mozilla.org/Remote_Debugging_Protocol_Stream_Transport#JSON_Packets). - -use serde::Serialize; -use serde_json::{self, Value}; -use std::error::Error; -use std::io::{Read, Write}; -use std::net::TcpStream; - -#[derive(Serialize)] -pub struct ActorDescription { - pub category: &'static str, - pub typeName: &'static str, - pub methods: Vec, -} - -#[derive(Serialize)] -pub struct Method { - pub name: &'static str, - pub request: Value, - pub response: Value, -} - -pub trait JsonPacketStream { - fn write_json_packet(&mut self, obj: &T); - fn write_merged_json_packet(&mut self, base: &T, extra: &U); - fn read_json_packet(&mut self) -> Result, String>; -} - -impl JsonPacketStream for TcpStream { - fn write_json_packet(&mut self, obj: &T) { - let s = serde_json::to_string(obj).unwrap(); - debug!("<- {}", s); - write!(self, "{}:{}", s.len(), s).unwrap(); - } - - fn write_merged_json_packet(&mut self, base: &T, extra: &U) { - let mut obj = serde_json::to_value(base).unwrap(); - let obj = obj.as_object_mut().unwrap(); - let extra = serde_json::to_value(extra).unwrap(); - let extra = extra.as_object().unwrap(); - - for (key, value) in extra { - obj.insert(key.to_owned(), value.to_owned()); - } - - self.write_json_packet(obj); - } - - fn read_json_packet(&mut self) -> Result, String> { - // https://wiki.mozilla.org/Remote_Debugging_Protocol_Stream_Transport - // In short, each JSON packet is [ascii length]:[JSON data of given length] - let mut buffer = vec!(); - loop { - let mut buf = [0]; - let byte = match self.read(&mut buf) { - Ok(0) => return Ok(None), // EOF - Ok(1) => buf[0], - Ok(_) => unreachable!(), - Err(e) => return Err(e.description().to_owned()), - }; - match byte { - b':' => { - let packet_len_str = match String::from_utf8(buffer) { - Ok(packet_len) => packet_len, - Err(_) => return Err("nonvalid UTF8 in packet length".to_owned()), - }; - let packet_len = match u64::from_str_radix(&packet_len_str, 10) { - Ok(packet_len) => packet_len, - Err(_) => return Err("packet length missing / not parsable".to_owned()), - }; - let mut packet = String::new(); - self.take(packet_len).read_to_string(&mut packet).unwrap(); - debug!("{}", packet); - return match serde_json::from_str(&packet) { - Ok(json) => Ok(Some(json)), - Err(err) => Err(err.description().to_owned()), - }; - }, - c => buffer.push(c), - } - } - } -} diff --git a/servo/components/devtools_traits/Cargo.toml b/servo/components/devtools_traits/Cargo.toml deleted file mode 100644 index 49c7f7ac332a..000000000000 --- a/servo/components/devtools_traits/Cargo.toml +++ /dev/null @@ -1,22 +0,0 @@ -[package] -name = "devtools_traits" -version = "0.0.1" -authors = ["The Servo Project Developers"] -license = "MPL-2.0" -publish = false - -[lib] -name = "devtools_traits" -path = "lib.rs" - -[dependencies] -bitflags = "1.0" -hyper = "0.10" -hyper_serde = "0.8" -ipc-channel = "0.10" -malloc_size_of = { path = "../malloc_size_of" } -malloc_size_of_derive = { path = "../malloc_size_of_derive" } -msg = {path = "../msg"} -serde = "1.0" -servo_url = {path = "../url"} -time = "0.1" diff --git a/servo/components/devtools_traits/lib.rs b/servo/components/devtools_traits/lib.rs deleted file mode 100644 index fe0f91c7e525..000000000000 --- a/servo/components/devtools_traits/lib.rs +++ /dev/null @@ -1,359 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -//! This module contains shared types and messages for use by devtools/script. -//! The traits are here instead of in script so that the devtools crate can be -//! modified independently of the rest of Servo. - -#![crate_name = "devtools_traits"] -#![crate_type = "rlib"] - -#![allow(non_snake_case)] -#![deny(unsafe_code)] - -#[macro_use] -extern crate bitflags; -extern crate hyper; -extern crate ipc_channel; -extern crate malloc_size_of; -#[macro_use] extern crate malloc_size_of_derive; -extern crate msg; -#[macro_use] extern crate serde; -extern crate servo_url; -extern crate time; - -use hyper::header::Headers; -use hyper::method::Method; -use ipc_channel::ipc::IpcSender; -use msg::constellation_msg::PipelineId; -use servo_url::ServoUrl; -use std::net::TcpStream; -use time::Duration; -use time::Tm; - -// Information would be attached to NewGlobal to be received and show in devtools. -// Extend these fields if we need more information. -#[derive(Debug, Deserialize, Serialize)] -pub struct DevtoolsPageInfo { - pub title: String, - pub url: ServoUrl, -} - -#[derive(Clone, Debug, Deserialize, MallocSizeOf, Serialize)] -pub struct CSSError { - pub filename: String, - pub line: u32, - pub column: u32, - pub msg: String -} - -/// Messages to instruct the devtools server to update its known actors/state -/// according to changes in the browser. -#[derive(Debug)] -pub enum DevtoolsControlMsg { - /// Messages from threads in the chrome process (resource/constellation/devtools) - FromChrome(ChromeToDevtoolsControlMsg), - /// Messages from script threads - FromScript(ScriptToDevtoolsControlMsg), -} - -/// Events that the devtools server must act upon. -#[derive(Debug)] -pub enum ChromeToDevtoolsControlMsg { - /// A new client has connected to the server. - AddClient(TcpStream), - /// The browser is shutting down. - ServerExitMsg, - /// A network event occurred (request, reply, etc.). The actor with the - /// provided name should be notified. - NetworkEvent(String, NetworkEvent), -} - -#[derive(Debug, Deserialize, Serialize)] -/// Events that the devtools server must act upon. -pub enum ScriptToDevtoolsControlMsg { - /// A new global object was created, associated with a particular pipeline. - /// The means of communicating directly with it are provided. - NewGlobal((PipelineId, Option), - IpcSender, - DevtoolsPageInfo), - /// A particular page has invoked the console API. - ConsoleAPI(PipelineId, ConsoleMessage, Option), - /// An animation frame with the given timestamp was processed in a script thread. - /// The actor with the provided name should be notified. - FramerateTick(String, f64), - - /// Report a CSS parse error for the given pipeline - ReportCSSError(PipelineId, CSSError), -} - -/// Serialized JS return values -/// TODO: generalize this beyond the EvaluateJS message? -#[derive(Debug, Deserialize, Serialize)] -pub enum EvaluateJSReply { - VoidValue, - NullValue, - BooleanValue(bool), - NumberValue(f64), - StringValue(String), - ActorValue { class: String, uuid: String }, -} - -#[derive(Debug, Deserialize, Serialize)] -pub struct AttrInfo { - pub namespace: String, - pub name: String, - pub value: String, -} - -#[derive(Debug, Deserialize, Serialize)] -pub struct NodeInfo { - pub uniqueId: String, - pub baseURI: String, - pub parent: String, - pub nodeType: u16, - pub namespaceURI: String, - pub nodeName: String, - pub numChildren: usize, - - pub name: String, - pub publicId: String, - pub systemId: String, - - pub attrs: Vec, - - pub isDocumentElement: bool, - - pub shortValue: String, - pub incompleteValue: bool, -} - -pub struct StartedTimelineMarker { - name: String, - start_time: PreciseTime, - start_stack: Option>, -} - -#[derive(Debug, Deserialize, Serialize)] -pub struct TimelineMarker { - pub name: String, - pub start_time: PreciseTime, - pub start_stack: Option>, - pub end_time: PreciseTime, - pub end_stack: Option>, -} - -#[derive(Clone, Debug, Deserialize, Eq, Hash, MallocSizeOf, PartialEq, Serialize)] -pub enum TimelineMarkerType { - Reflow, - DOMEvent, -} - -/// The properties of a DOM node as computed by layout. -#[derive(Debug, Deserialize, Serialize)] -pub struct ComputedNodeLayout { - pub display: String, - pub position: String, - pub zIndex: String, - pub boxSizing: String, - - pub autoMargins: AutoMargins, - pub marginTop: String, - pub marginRight: String, - pub marginBottom: String, - pub marginLeft: String, - - pub borderTopWidth: String, - pub borderRightWidth: String, - pub borderBottomWidth: String, - pub borderLeftWidth: String, - - pub paddingTop: String, - pub paddingRight: String, - pub paddingBottom: String, - pub paddingLeft: String, - - pub width: f32, - pub height: f32, -} - -#[derive(Debug, Deserialize, Serialize)] -pub struct AutoMargins { - pub top: bool, - pub right: bool, - pub bottom: bool, - pub left: bool, -} - -/// Messages to process in a particular script thread, as instructed by a devtools client. -/// TODO: better error handling, e.g. if pipeline id lookup fails? -#[derive(Debug, Deserialize, Serialize)] -pub enum DevtoolScriptControlMsg { - /// Evaluate a JS snippet in the context of the global for the given pipeline. - EvaluateJS(PipelineId, String, IpcSender), - /// Retrieve the details of the root node (ie. the document) for the given pipeline. - GetRootNode(PipelineId, IpcSender>), - /// Retrieve the details of the document element for the given pipeline. - GetDocumentElement(PipelineId, IpcSender>), - /// Retrieve the details of the child nodes of the given node in the given pipeline. - GetChildren(PipelineId, String, IpcSender>>), - /// Retrieve the computed layout properties of the given node in the given pipeline. - GetLayout(PipelineId, String, IpcSender>), - /// Retrieve all stored console messages for the given pipeline. - GetCachedMessages(PipelineId, CachedConsoleMessageTypes, IpcSender>), - /// Update a given node's attributes with a list of modifications. - ModifyAttribute(PipelineId, String, Vec), - /// Request live console messages for a given pipeline (true if desired, false otherwise). - WantsLiveNotifications(PipelineId, bool), - /// Request live notifications for a given set of timeline events for a given pipeline. - SetTimelineMarkers(PipelineId, Vec, IpcSender>), - /// Withdraw request for live timeline notifications for a given pipeline. - DropTimelineMarkers(PipelineId, Vec), - /// Request a callback directed at the given actor name from the next animation frame - /// executed in the given pipeline. - RequestAnimationFrame(PipelineId, String), - /// Direct the given pipeline to reload the current page. - Reload(PipelineId), -} - -#[derive(Debug, Deserialize, Serialize)] -pub struct Modification { - pub attributeName: String, - pub newValue: Option, -} - -#[derive(Clone, Debug, Deserialize, Serialize)] -pub enum LogLevel { - Log, - Debug, - Info, - Warn, - Error, -} - -#[derive(Clone, Debug, Deserialize, Serialize)] -pub struct ConsoleMessage { - pub message: String, - pub logLevel: LogLevel, - pub filename: String, - pub lineNumber: usize, - pub columnNumber: usize, -} - -bitflags! { - #[derive(Deserialize, Serialize)] - pub struct CachedConsoleMessageTypes: u8 { - const PAGE_ERROR = 1 << 0; - const CONSOLE_API = 1 << 1; - } -} - -#[derive(Debug, Deserialize, Serialize)] -pub struct PageError { - #[serde(rename = "_type")] - pub type_: String, - pub errorMessage: String, - pub sourceName: String, - pub lineText: String, - pub lineNumber: u32, - pub columnNumber: u32, - pub category: String, - pub timeStamp: u64, - pub error: bool, - pub warning: bool, - pub exception: bool, - pub strict: bool, - pub private: bool, -} - -#[derive(Debug, Deserialize, Serialize)] -pub struct ConsoleAPI { - #[serde(rename = "_type")] - pub type_: String, - pub level: String, - pub filename: String, - pub lineNumber: u32, - pub functionName: String, - pub timeStamp: u64, - pub private: bool, - pub arguments: Vec, -} - -#[derive(Debug, Deserialize, Serialize)] -pub enum CachedConsoleMessage { - PageError(PageError), - ConsoleAPI(ConsoleAPI), -} - -#[derive(Debug, PartialEq)] -pub struct HttpRequest { - pub url: ServoUrl, - pub method: Method, - pub headers: Headers, - pub body: Option>, - pub pipeline_id: PipelineId, - pub startedDateTime: Tm, - pub timeStamp: i64, - pub connect_time: u64, - pub send_time: u64, - pub is_xhr: bool, -} - -#[derive(Debug, PartialEq)] -pub struct HttpResponse { - pub headers: Option, - pub status: Option<(u16, Vec)>, - pub body: Option>, - pub pipeline_id: PipelineId, -} - -#[derive(Debug)] -pub enum NetworkEvent { - HttpRequest(HttpRequest), - HttpResponse(HttpResponse), -} - -impl TimelineMarker { - pub fn start(name: String) -> StartedTimelineMarker { - StartedTimelineMarker { - name: name, - start_time: PreciseTime::now(), - start_stack: None, - } - } -} - -impl StartedTimelineMarker { - pub fn end(self) -> TimelineMarker { - TimelineMarker { - name: self.name, - start_time: self.start_time, - start_stack: self.start_stack, - end_time: PreciseTime::now(), - end_stack: None, - } - } -} - -/// A replacement for `time::PreciseTime` that isn't opaque, so we can serialize it. -/// -/// The reason why this doesn't go upstream is that `time` is slated to be part of Rust's standard -/// library, which definitely can't have any dependencies on `serde`. But `serde` can't implement -/// `Deserialize` and `Serialize` itself, because `time::PreciseTime` is opaque! A Catch-22. So I'm -/// duplicating the definition here. -#[derive(Clone, Copy, Debug, Deserialize, Serialize)] -pub struct PreciseTime(u64); - -impl PreciseTime { - pub fn now() -> PreciseTime { - PreciseTime(time::precise_time_ns()) - } - - pub fn to(&self, later: PreciseTime) -> Duration { - Duration::nanoseconds((later.0 - self.0) as i64) - } -} - -#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, MallocSizeOf, PartialEq, Serialize)] -pub struct WorkerId(pub u32); diff --git a/servo/components/dom_struct/Cargo.toml b/servo/components/dom_struct/Cargo.toml deleted file mode 100644 index 7a76375ac06e..000000000000 --- a/servo/components/dom_struct/Cargo.toml +++ /dev/null @@ -1,10 +0,0 @@ -[package] -name = "dom_struct" -version = "0.0.1" -authors = ["The Servo Project Developers"] -license = "MPL-2.0" -publish = false - -[lib] -path = "lib.rs" -proc-macro = true diff --git a/servo/components/dom_struct/lib.rs b/servo/components/dom_struct/lib.rs deleted file mode 100644 index 86c7134a78fe..000000000000 --- a/servo/components/dom_struct/lib.rs +++ /dev/null @@ -1,26 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -#![feature(proc_macro)] - -extern crate proc_macro; - -use proc_macro::{TokenStream, quote}; - -#[proc_macro_attribute] -pub fn dom_struct(args: TokenStream, input: TokenStream) -> TokenStream { - if !args.is_empty() { - panic!("#[dom_struct] takes no arguments"); - } - let attributes = quote! { - #[derive(DenyPublicFields, DomObject, JSTraceable, MallocSizeOf)] - #[must_root] - #[repr(C)] - }; - - // Work around https://github.com/rust-lang/rust/issues/46489 - let attributes: TokenStream = attributes.to_string().parse().unwrap(); - - attributes.into_iter().chain(input.into_iter()).collect() -} diff --git a/servo/components/domobject_derive/Cargo.toml b/servo/components/domobject_derive/Cargo.toml deleted file mode 100644 index ca05937294e8..000000000000 --- a/servo/components/domobject_derive/Cargo.toml +++ /dev/null @@ -1,14 +0,0 @@ -[package] -name = "domobject_derive" -version = "0.0.1" -authors = ["The Servo Project Developers"] -license = "MPL-2.0" -publish = false - -[lib] -path = "lib.rs" -proc-macro = true - -[dependencies] -syn = "0.12.12" -quote = "0.4.2" diff --git a/servo/components/domobject_derive/lib.rs b/servo/components/domobject_derive/lib.rs deleted file mode 100644 index 1db1af05d703..000000000000 --- a/servo/components/domobject_derive/lib.rs +++ /dev/null @@ -1,93 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -#![recursion_limit = "128"] - -extern crate proc_macro; -#[macro_use] extern crate quote; -#[macro_use] extern crate syn; - -#[proc_macro_derive(DomObject)] -pub fn expand_token_stream(input: proc_macro::TokenStream) -> proc_macro::TokenStream { - let input = syn::parse(input).unwrap(); - expand_dom_object(input).into() -} - -fn expand_dom_object(input: syn::DeriveInput) -> quote::Tokens { - let fields = if let syn::Data::Struct(syn::DataStruct { ref fields, .. }) = input.data { - fields.iter().collect::>() - } else { - panic!("#[derive(DomObject)] should only be applied on proper structs") - }; - - let (first_field, fields) = fields - .split_first() - .expect("#[derive(DomObject)] should not be applied on empty structs"); - - let first_field_name = first_field.ident.as_ref().unwrap(); - let mut field_types = vec![]; - for field in fields { - if !field_types.contains(&&field.ty) { - field_types.push(&field.ty); - } - } - - let name = &input.ident; - let (impl_generics, ty_generics, where_clause) = input.generics.split_for_impl(); - let mut items = quote! { - impl #impl_generics ::js::conversions::ToJSValConvertible for #name #ty_generics #where_clause { - #[allow(unsafe_code)] - unsafe fn to_jsval(&self, - cx: *mut ::js::jsapi::JSContext, - rval: ::js::rust::MutableHandleValue) { - let object = ::dom::bindings::reflector::DomObject::reflector(self).get_jsobject(); - object.to_jsval(cx, rval) - } - } - - impl #impl_generics ::dom::bindings::reflector::DomObject for #name #ty_generics #where_clause { - #[inline] - fn reflector(&self) -> &::dom::bindings::reflector::Reflector { - self.#first_field_name.reflector() - } - } - - impl #impl_generics ::dom::bindings::reflector::MutDomObject for #name #ty_generics #where_clause { - fn init_reflector(&mut self, obj: *mut ::js::jsapi::JSObject) { - self.#first_field_name.init_reflector(obj); - } - } - }; - - let mut params = quote::Tokens::new(); - params.append_separated(input.generics.type_params().map(|param| param.ident), ", "); - - // For each field in the struct, we implement ShouldNotImplDomObject for a - // pair of all the type parameters of the DomObject and and the field type. - // This allows us to support parameterized DOM objects - // such as IteratorIterable. - items.append_all(field_types.iter().map(|ty| { - quote! { - impl #impl_generics ShouldNotImplDomObject for ((#params), #ty) #where_clause {} - } - })); - - let mut generics = input.generics.clone(); - generics.params.push(parse_quote!(__T: ::dom::bindings::reflector::DomObject)); - - let (impl_generics, _, where_clause) = generics.split_for_impl(); - - items.append_all(quote! { - trait ShouldNotImplDomObject {} - impl #impl_generics ShouldNotImplDomObject for ((#params), __T) #where_clause {} - }); - - let dummy_const = syn::Ident::from(format!("_IMPL_DOMOBJECT_FOR_{}", name)); - let tokens = quote! { - #[allow(non_upper_case_globals)] - const #dummy_const: () = { #items }; - }; - - tokens -} diff --git a/servo/components/geometry/Cargo.toml b/servo/components/geometry/Cargo.toml deleted file mode 100644 index d37b8b9e64d4..000000000000 --- a/servo/components/geometry/Cargo.toml +++ /dev/null @@ -1,18 +0,0 @@ -[package] -name = "servo_geometry" -version = "0.0.1" -authors = ["The Servo Project Developers"] -license = "MPL-2.0" -publish = false - -[lib] -name = "servo_geometry" -path = "lib.rs" - -[dependencies] -app_units = "0.6" -euclid = "0.17" -malloc_size_of = { path = "../malloc_size_of" } -malloc_size_of_derive = { path = "../malloc_size_of_derive" } -style_traits = { path = "../style_traits" } -webrender_api = { git = "https://github.com/servo/webrender" } diff --git a/servo/components/geometry/lib.rs b/servo/components/geometry/lib.rs deleted file mode 100644 index c4bb9721bf65..000000000000 --- a/servo/components/geometry/lib.rs +++ /dev/null @@ -1,75 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -extern crate app_units; -extern crate euclid; -extern crate malloc_size_of; -extern crate style_traits; -#[macro_use] extern crate malloc_size_of_derive; -extern crate webrender_api; - -use app_units::{Au, MAX_AU, MIN_AU}; -use euclid::{Length, Point2D, Rect, Size2D}; -use std::f32; -use style_traits::DevicePixel; -use webrender_api::{LayoutPoint, LayoutRect, LayoutSize}; - -// Units for use with euclid::length and euclid::scale_factor. - -pub type DeviceUintLength = Length; - -/// A normalized "pixel" at the default resolution for the display. -/// -/// Like the CSS "px" unit, the exact physical size of this unit may vary between devices, but it -/// should approximate a device-independent reference length. This unit corresponds to Android's -/// "density-independent pixel" (dip), Mac OS X's "point", and Windows "device-independent pixel." -/// -/// The relationship between DevicePixel and DeviceIndependentPixel is defined by the OS. On most low-dpi -/// screens, one DeviceIndependentPixel is equal to one DevicePixel. But on high-density screens it can be -/// some larger number. For example, by default on Apple "retina" displays, one DeviceIndependentPixel equals -/// two DevicePixels. On Android "MDPI" displays, one DeviceIndependentPixel equals 1.5 device pixels. -/// -/// The ratio between DeviceIndependentPixel and DevicePixel for a given display be found by calling -/// `servo::windowing::WindowMethods::hidpi_factor`. -#[derive(Clone, Copy, Debug, MallocSizeOf)] -pub enum DeviceIndependentPixel {} - -// An Au is an "App Unit" and represents 1/60th of a CSS pixel. It was -// originally proposed in 2002 as a standard unit of measure in Gecko. -// See https://bugzilla.mozilla.org/show_bug.cgi?id=177805 for more info. - -pub trait MaxRect { - #[inline(always)] - fn max_rect() -> Self; -} - -impl MaxRect for Rect { - fn max_rect() -> Rect { - Rect::new( - Point2D::new(MIN_AU / 2, MIN_AU / 2), - Size2D::new(MAX_AU, MAX_AU) - ) - } -} - -impl MaxRect for LayoutRect { - fn max_rect() -> LayoutRect { - LayoutRect::new( - LayoutPoint::new(f32::MIN / 2.0, f32::MIN / 2.0), - LayoutSize::new(f32::MAX, f32::MAX), - ) - } -} - -/// A helper function to convert a rect of `f32` pixels to a rect of app units. -pub fn f32_rect_to_au_rect(rect: Rect) -> Rect { - Rect::new(Point2D::new(Au::from_f32_px(rect.origin.x), Au::from_f32_px(rect.origin.y)), - Size2D::new(Au::from_f32_px(rect.size.width), Au::from_f32_px(rect.size.height))) -} - -/// A helper function to convert a rect of `Au` pixels to a rect of f32 units. -pub fn au_rect_to_f32_rect(rect: Rect) -> Rect { - Rect::new(Point2D::new(rect.origin.x.to_f32_px(), rect.origin.y.to_f32_px()), - Size2D::new(rect.size.width.to_f32_px(), rect.size.height.to_f32_px())) -} diff --git a/servo/components/gfx/Cargo.toml b/servo/components/gfx/Cargo.toml deleted file mode 100644 index c231b6fe4eae..000000000000 --- a/servo/components/gfx/Cargo.toml +++ /dev/null @@ -1,70 +0,0 @@ -[package] - -name = "gfx" -version = "0.0.1" -authors = ["The Servo Project Developers"] -license = "MPL-2.0" -publish = false - -[lib] -name = "gfx" -path = "lib.rs" -test = false -doctest = false - -[features] -unstable = ["simd"] - -[dependencies] -app_units = "0.6" -bitflags = "1.0" -euclid = "0.17" -fnv = "1.0" -fontsan = {git = "https://github.com/servo/fontsan"} -gfx_traits = {path = "../gfx_traits"} -harfbuzz-sys = "0.1" -ipc-channel = "0.10" -lazy_static = "1" -libc = "0.2" -log = "0.4" -malloc_size_of = { path = "../malloc_size_of" } -malloc_size_of_derive = { path = "../malloc_size_of_derive" } -msg = {path = "../msg"} -net_traits = {path = "../net_traits"} -ordered-float = "0.4" -range = {path = "../range"} -serde = "1.0" -servo_arc = {path = "../servo_arc"} -servo_atoms = {path = "../atoms"} -servo_geometry = {path = "../geometry"} -servo_url = {path = "../url"} -smallvec = "0.6" -style = {path = "../style"} -time = "0.1.12" -unicode-bidi = {version = "0.3", features = ["with_serde"]} -unicode-script = {version = "0.1", features = ["harfbuzz"]} -webrender_api = {git = "https://github.com/servo/webrender", features = ["ipc"]} -xi-unicode = "0.1.0" - -[target.'cfg(target_os = "macos")'.dependencies] -byteorder = "1.0" -core-foundation = "0.5" -core-graphics = "0.13" -core-text = "9.0" - -[target.'cfg(any(target_os = "linux", target_os = "android"))'.dependencies] -freetype = "0.3" -servo_allocator = {path = "../allocator"} - -[target.'cfg(target_os = "linux")'.dependencies] -servo-fontconfig = "0.2.1" - -[target.'cfg(target_os = "android")'.dependencies] -xml5ever = {version = "0.12"} - -[target.'cfg(any(target_feature = "sse2", target_feature = "neon"))'.dependencies] -simd = {version = "0.2.0", optional = true} - -[target.'cfg(target_os = "windows")'.dependencies] -dwrote = "0.4" -truetype = "0.26" diff --git a/servo/components/gfx/display_list/mod.rs b/servo/components/gfx/display_list/mod.rs deleted file mode 100644 index aa081c1e2804..000000000000 --- a/servo/components/gfx/display_list/mod.rs +++ /dev/null @@ -1,1004 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -//! Servo heavily uses display lists, which are retained-mode lists of painting commands to -//! perform. Using a list instead of painting elements in immediate mode allows transforms, hit -//! testing, and invalidation to be performed using the same primitives as painting. It also allows -//! Servo to aggressively cull invisible and out-of-bounds painting elements, to reduce overdraw. -//! Finally, display lists allow tiles to be farmed out onto multiple CPUs and painted in parallel -//! (although this benefit does not apply to GPU-based painting). -//! -//! Display items describe relatively high-level drawing operations (for example, entire borders -//! and shadows instead of lines and blur operations), to reduce the amount of allocation required. -//! They are therefore not exactly analogous to constructs like Skia pictures, which consist of -//! low-level drawing primitives. - -use euclid::{Vector2D, TypedRect, SideOffsets2D}; -use euclid::num::{One, Zero}; -use gfx_traits::{self, StackingContextId}; -use gfx_traits::print_tree::PrintTree; -use msg::constellation_msg::PipelineId; -use net_traits::image::base::{Image, PixelFormat}; -use servo_geometry::MaxRect; -use std::cmp::Ordering; -use std::collections::HashMap; -use std::f32; -use std::fmt; -use webrender_api::{BorderRadius, BorderWidths, BoxShadowClipMode, ClipMode, ColorF}; -use webrender_api::{ComplexClipRegion, ExtendMode, ExternalScrollId, FilterOp, FontInstanceKey}; -use webrender_api::{GlyphInstance, GradientStop, ImageBorder, ImageKey, ImageRendering}; -use webrender_api::{LayoutPoint, LayoutRect, LayoutSize, LayoutTransform, LayoutVector2D}; -use webrender_api::{LineStyle, MixBlendMode, NormalBorder, ScrollPolicy, ScrollSensitivity}; -use webrender_api::{StickyOffsetBounds, TransformStyle}; - -pub use style::dom::OpaqueNode; - -/// The factor that we multiply the blur radius by in order to inflate the boundaries of display -/// items that involve a blur. This ensures that the display item boundaries include all the ink. -pub static BLUR_INFLATION_FACTOR: i32 = 3; - -/// An index into the vector of ClipScrollNodes. During WebRender conversion these nodes -/// are given ClipIds. -#[derive(Clone, Copy, Debug, Deserialize, MallocSizeOf, PartialEq, Serialize)] -pub struct ClipScrollNodeIndex(pub usize); - -impl ClipScrollNodeIndex { - pub fn is_root_scroll_node(&self) -> bool { - match *self { - ClipScrollNodeIndex(0) => true, - _ => false, - } - } - - pub fn to_define_item(&self) -> DisplayItem { - DisplayItem::DefineClipScrollNode(Box::new(DefineClipScrollNodeItem { - base: BaseDisplayItem::empty(), - node_index: *self, - })) - } -} - -/// A set of indices into the clip scroll node vector for a given item. -#[derive(Clone, Copy, Debug, Deserialize, MallocSizeOf, PartialEq, Serialize)] -pub struct ClippingAndScrolling { - pub scrolling: ClipScrollNodeIndex, - pub clipping: Option, -} - -impl ClippingAndScrolling { - pub fn simple(scrolling: ClipScrollNodeIndex) -> ClippingAndScrolling { - ClippingAndScrolling { - scrolling, - clipping: None, - } - } - - pub fn new(scrolling: ClipScrollNodeIndex, clipping: ClipScrollNodeIndex) -> ClippingAndScrolling { - ClippingAndScrolling { - scrolling, - clipping: Some(clipping), - } - } -} - -#[derive(Deserialize, MallocSizeOf, Serialize)] -pub struct DisplayList { - pub list: Vec, - pub clip_scroll_nodes: Vec, -} - -impl DisplayList { - /// Return the bounds of this display list based on the dimensions of the root - /// stacking context. - pub fn bounds(&self) -> LayoutRect { - match self.list.get(0) { - Some(&DisplayItem::PushStackingContext(ref item)) => item.stacking_context.bounds, - Some(_) => unreachable!("Root element of display list not stacking context."), - None => LayoutRect::zero(), - } - } - - pub fn print(&self) { - let mut print_tree = PrintTree::new("Display List".to_owned()); - self.print_with_tree(&mut print_tree); - } - - pub fn print_with_tree(&self, print_tree: &mut PrintTree) { - print_tree.new_level("ClipScrollNodes".to_owned()); - for node in &self.clip_scroll_nodes { - print_tree.add_item(format!("{:?}", node)); - } - print_tree.end_level(); - - print_tree.new_level("Items".to_owned()); - for item in &self.list { - print_tree.add_item(format!("{:?} StackingContext: {:?} {:?}", - item, - item.base().stacking_context_id, - item.clipping_and_scrolling()) - ); - } - print_tree.end_level(); - } -} - -impl gfx_traits::DisplayList for DisplayList { - /// Analyze the display list to figure out if this may be the first - /// contentful paint (i.e. the display list contains items of type text, - /// image, non-white canvas or SVG). Used by metrics. - fn is_contentful(&self) -> bool { - for item in &self.list { - match item { - &DisplayItem::Text(_) | - &DisplayItem::Image(_) => { - return true - } - _ => (), - } - } - - false - } -} - -/// Display list sections that make up a stacking context. Each section here refers -/// to the steps in CSS 2.1 Appendix E. -/// -#[derive(Clone, Copy, Debug, Deserialize, Eq, MallocSizeOf, Ord, PartialEq, PartialOrd, Serialize)] -pub enum DisplayListSection { - BackgroundAndBorders, - BlockBackgroundsAndBorders, - Content, - Outlines, -} - -#[derive(Clone, Copy, Debug, Deserialize, Eq, MallocSizeOf, Ord, PartialEq, PartialOrd, Serialize)] -pub enum StackingContextType { - Real, - PseudoPositioned, - PseudoFloat, -} - -#[derive(Clone, Deserialize, MallocSizeOf, Serialize)] -/// Represents one CSS stacking context, which may or may not have a hardware layer. -pub struct StackingContext { - /// The ID of this StackingContext for uniquely identifying it. - pub id: StackingContextId, - - /// The type of this StackingContext. Used for collecting and sorting. - pub context_type: StackingContextType, - - /// The position and size of this stacking context. - pub bounds: LayoutRect, - - /// The overflow rect for this stacking context in its coordinate system. - pub overflow: LayoutRect, - - /// The `z-index` for this stacking context. - pub z_index: i32, - - /// CSS filters to be applied to this stacking context (including opacity). - pub filters: Vec, - - /// The blend mode with which this stacking context blends with its backdrop. - pub mix_blend_mode: MixBlendMode, - - /// A transform to be applied to this stacking context. - pub transform: Option, - - /// The transform style of this stacking context. - pub transform_style: TransformStyle, - - /// The perspective matrix to be applied to children. - pub perspective: Option, - - /// The scroll policy of this layer. - pub scroll_policy: ScrollPolicy, - - /// The clip and scroll info for this StackingContext. - pub parent_clipping_and_scrolling: ClippingAndScrolling, -} - -impl StackingContext { - /// Creates a new stacking context. - #[inline] - pub fn new(id: StackingContextId, - context_type: StackingContextType, - bounds: LayoutRect, - overflow: LayoutRect, - z_index: i32, - filters: Vec, - mix_blend_mode: MixBlendMode, - transform: Option, - transform_style: TransformStyle, - perspective: Option, - scroll_policy: ScrollPolicy, - parent_clipping_and_scrolling: ClippingAndScrolling) - -> StackingContext { - StackingContext { - id, - context_type, - bounds, - overflow, - z_index, - filters, - mix_blend_mode, - transform, - transform_style, - perspective, - scroll_policy, - parent_clipping_and_scrolling, - } - } - - #[inline] - pub fn root() -> StackingContext { - StackingContext::new( - StackingContextId::root(), - StackingContextType::Real, - LayoutRect::zero(), - LayoutRect::zero(), - 0, - vec![], - MixBlendMode::Normal, - None, - TransformStyle::Flat, - None, - ScrollPolicy::Scrollable, - ClippingAndScrolling::simple(ClipScrollNodeIndex(0)) - ) - } - - pub fn to_display_list_items(self) -> (DisplayItem, DisplayItem) { - let mut base_item = BaseDisplayItem::empty(); - base_item.stacking_context_id = self.id; - base_item.clipping_and_scrolling = self.parent_clipping_and_scrolling; - - let pop_item = DisplayItem::PopStackingContext(Box::new( - PopStackingContextItem { - base: base_item.clone(), - stacking_context_id: self.id, - } - )); - - let push_item = DisplayItem::PushStackingContext(Box::new( - PushStackingContextItem { - base: base_item, - stacking_context: self, - } - )); - - (push_item, pop_item) - } -} - -impl Ord for StackingContext { - fn cmp(&self, other: &Self) -> Ordering { - if self.z_index != 0 || other.z_index != 0 { - return self.z_index.cmp(&other.z_index); - } - - match (self.context_type, other.context_type) { - (StackingContextType::PseudoFloat, StackingContextType::PseudoFloat) => Ordering::Equal, - (StackingContextType::PseudoFloat, _) => Ordering::Less, - (_, StackingContextType::PseudoFloat) => Ordering::Greater, - (_, _) => Ordering::Equal, - } - } -} - -impl PartialOrd for StackingContext { - fn partial_cmp(&self, other: &Self) -> Option { - Some(self.cmp(other)) - } -} - -impl Eq for StackingContext {} -impl PartialEq for StackingContext { - fn eq(&self, other: &Self) -> bool { - self.id == other.id - } -} - -impl fmt::Debug for StackingContext { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - let type_string = if self.context_type == StackingContextType::Real { - "StackingContext" - } else { - "Pseudo-StackingContext" - }; - - write!(f, "{} at {:?} with overflow {:?}: {:?}", - type_string, - self.bounds, - self.overflow, - self.id) - } -} - -#[derive(Clone, Debug, Deserialize, MallocSizeOf, Serialize)] -pub struct StickyFrameData { - pub margins: SideOffsets2D>, - pub vertical_offset_bounds: StickyOffsetBounds, - pub horizontal_offset_bounds: StickyOffsetBounds, -} - -#[derive(Clone, Debug, Deserialize, MallocSizeOf, Serialize)] -pub enum ClipScrollNodeType { - ScrollFrame(ScrollSensitivity, ExternalScrollId), - StickyFrame(StickyFrameData), - Clip, -} - -/// Defines a clip scroll node. -#[derive(Clone, Debug, Deserialize, MallocSizeOf, Serialize)] -pub struct ClipScrollNode { - /// The index of the parent of this ClipScrollNode. - pub parent_index: ClipScrollNodeIndex, - - /// The position of this scroll root's frame in the parent stacking context. - pub clip: ClippingRegion, - - /// The rect of the contents that can be scrolled inside of the scroll root. - pub content_rect: LayoutRect, - - /// The type of this ClipScrollNode. - pub node_type: ClipScrollNodeType, -} - -/// One drawing command in the list. -#[derive(Clone, Deserialize, MallocSizeOf, Serialize)] -pub enum DisplayItem { - SolidColor(Box), - Text(Box), - Image(Box), - Border(Box), - Gradient(Box), - RadialGradient(Box), - Line(Box), - BoxShadow(Box), - PushTextShadow(Box), - PopAllTextShadows(Box), - Iframe(Box), - PushStackingContext(Box), - PopStackingContext(Box), - DefineClipScrollNode(Box), -} - -/// Information common to all display items. -#[derive(Clone, Deserialize, MallocSizeOf, Serialize)] -pub struct BaseDisplayItem { - /// The boundaries of the display item, in layer coordinates. - pub bounds: LayoutRect, - - /// Metadata attached to this display item. - pub metadata: DisplayItemMetadata, - - /// The clip rectangle to use for this item. - pub clip_rect: LayoutRect, - - /// The section of the display list that this item belongs to. - pub section: DisplayListSection, - - /// The id of the stacking context this item belongs to. - pub stacking_context_id: StackingContextId, - - /// The clip and scroll info for this item. - pub clipping_and_scrolling: ClippingAndScrolling, -} - -impl BaseDisplayItem { - #[inline(always)] - pub fn new(bounds: LayoutRect, - metadata: DisplayItemMetadata, - clip_rect: LayoutRect, - section: DisplayListSection, - stacking_context_id: StackingContextId, - clipping_and_scrolling: ClippingAndScrolling) - -> BaseDisplayItem { - BaseDisplayItem { - bounds, - metadata, - clip_rect, - section, - stacking_context_id, - clipping_and_scrolling, - } - } - - #[inline(always)] - pub fn empty() -> BaseDisplayItem { - BaseDisplayItem { - bounds: TypedRect::zero(), - metadata: DisplayItemMetadata { - node: OpaqueNode(0), - pointing: None, - }, - // Create a rectangle of maximal size. - clip_rect: LayoutRect::max_rect(), - section: DisplayListSection::Content, - stacking_context_id: StackingContextId::root(), - clipping_and_scrolling: ClippingAndScrolling::simple(ClipScrollNodeIndex(0)), - } - } -} - -/// A clipping region for a display item. Currently, this can describe rectangles, rounded -/// rectangles (for `border-radius`), or arbitrary intersections of the two. Arbitrary transforms -/// are not supported because those are handled by the higher-level `StackingContext` abstraction. -#[derive(Clone, Deserialize, MallocSizeOf, PartialEq, Serialize)] -pub struct ClippingRegion { - /// The main rectangular region. This does not include any corners. - pub main: LayoutRect, - /// Any complex regions. - /// - /// TODO(pcwalton): Atomically reference count these? Not sure if it's worth the trouble. - /// Measure and follow up. - pub complex: Vec, -} - -impl ClippingRegion { - /// Returns an empty clipping region that, if set, will result in no pixels being visible. - #[inline] - pub fn empty() -> ClippingRegion { - ClippingRegion { - main: LayoutRect::zero(), - complex: Vec::new(), - } - } - - /// Returns an all-encompassing clipping region that clips no pixels out. - #[inline] - pub fn max() -> ClippingRegion { - ClippingRegion { - main: LayoutRect::max_rect(), - complex: Vec::new(), - } - } - - /// Returns a clipping region that represents the given rectangle. - #[inline] - pub fn from_rect(rect: LayoutRect) -> ClippingRegion { - ClippingRegion { - main: rect, - complex: Vec::new(), - } - } - - /// Mutates this clipping region to intersect with the given rectangle. - /// - /// TODO(pcwalton): This could more eagerly eliminate complex clipping regions, at the cost of - /// complexity. - #[inline] - pub fn intersect_rect(&mut self, rect: &LayoutRect) { - self.main = self.main.intersection(rect).unwrap_or(LayoutRect::zero()) - } - - /// Returns true if this clipping region might be nonempty. This can return false positives, - /// but never false negatives. - #[inline] - pub fn might_be_nonempty(&self) -> bool { - !self.main.is_empty() - } - - /// Returns true if this clipping region might contain the given point and false otherwise. - /// This is a quick, not a precise, test; it can yield false positives. - #[inline] - pub fn might_intersect_point(&self, point: &LayoutPoint) -> bool { - self.main.contains(point) && - self.complex.iter().all(|complex| complex.rect.contains(point)) - } - - /// Returns true if this clipping region might intersect the given rectangle and false - /// otherwise. This is a quick, not a precise, test; it can yield false positives. - #[inline] - pub fn might_intersect_rect(&self, rect: &LayoutRect) -> bool { - self.main.intersects(rect) && - self.complex.iter().all(|complex| complex.rect.intersects(rect)) - } - - /// Returns true if this clipping region completely surrounds the given rect. - #[inline] - pub fn does_not_clip_rect(&self, rect: &LayoutRect) -> bool { - self.main.contains(&rect.origin) && self.main.contains(&rect.bottom_right()) && - self.complex.iter().all(|complex| { - complex.rect.contains(&rect.origin) && complex.rect.contains(&rect.bottom_right()) - }) - } - - /// Returns a bounding rect that surrounds this entire clipping region. - #[inline] - pub fn bounding_rect(&self) -> LayoutRect { - let mut rect = self.main; - for complex in &*self.complex { - rect = rect.union(&complex.rect) - } - rect - } - - /// Intersects this clipping region with the given rounded rectangle. - #[inline] - pub fn intersect_with_rounded_rect(&mut self, rect: LayoutRect, radii: BorderRadius) { - let new_complex_region = ComplexClipRegion { - rect, - radii, - mode: ClipMode::Clip, - }; - - // FIXME(pcwalton): This is O(n²) worst case for disjoint clipping regions. Is that OK? - // They're slow anyway… - // - // Possibly relevant if we want to do better: - // - // http://www.inrg.csie.ntu.edu.tw/algorithm2014/presentation/D&C%20Lee-84.pdf - for existing_complex_region in &mut self.complex { - if existing_complex_region.completely_encloses(&new_complex_region) { - *existing_complex_region = new_complex_region; - return - } - if new_complex_region.completely_encloses(existing_complex_region) { - return - } - } - - self.complex.push(new_complex_region); - } - - /// Translates this clipping region by the given vector. - #[inline] - pub fn translate(&self, delta: &LayoutVector2D) -> ClippingRegion { - ClippingRegion { - main: self.main.translate(delta), - complex: self.complex.iter().map(|complex| { - ComplexClipRegion { - rect: complex.rect.translate(delta), - radii: complex.radii, - mode: complex.mode, - } - }).collect(), - } - } - - #[inline] - pub fn is_max(&self) -> bool { - self.main == LayoutRect::max_rect() && self.complex.is_empty() - } -} - -impl fmt::Debug for ClippingRegion { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - if *self == ClippingRegion::max() { - write!(f, "ClippingRegion::Max") - } else if *self == ClippingRegion::empty() { - write!(f, "ClippingRegion::Empty") - } else if self.main == LayoutRect::max_rect() { - write!(f, "ClippingRegion(Complex={:?})", self.complex) - } else { - write!(f, "ClippingRegion(Rect={:?}, Complex={:?})", self.main, self.complex) - } - } -} - -pub trait CompletelyEncloses { - fn completely_encloses(&self, other: &Self) -> bool; -} - -impl CompletelyEncloses for ComplexClipRegion { - // TODO(pcwalton): This could be more aggressive by considering points that touch the inside of - // the border radius ellipse. - fn completely_encloses(&self, other: &Self) -> bool { - let left = self.radii.top_left.width.max(self.radii.bottom_left.width); - let top = self.radii.top_left.height.max(self.radii.top_right.height); - let right = self.radii.top_right.width.max(self.radii.bottom_right.width); - let bottom = self.radii.bottom_left.height.max(self.radii.bottom_right.height); - let interior = LayoutRect::new(LayoutPoint::new(self.rect.origin.x + left, self.rect.origin.y + top), - LayoutSize::new(self.rect.size.width - left - right, - self.rect.size.height - top - bottom)); - interior.origin.x <= other.rect.origin.x && interior.origin.y <= other.rect.origin.y && - interior.max_x() >= other.rect.max_x() && interior.max_y() >= other.rect.max_y() - } -} - -/// Metadata attached to each display item. This is useful for performing auxiliary threads with -/// the display list involving hit testing: finding the originating DOM node and determining the -/// cursor to use when the element is hovered over. -#[derive(Clone, Copy, Deserialize, MallocSizeOf, Serialize)] -pub struct DisplayItemMetadata { - /// The DOM node from which this display item originated. - pub node: OpaqueNode, - /// The value of the `cursor` property when the mouse hovers over this display item. If `None`, - /// this display item is ineligible for pointer events (`pointer-events: none`). - pub pointing: Option, -} - -/// Paints a solid color. -#[derive(Clone, Deserialize, MallocSizeOf, Serialize)] -pub struct SolidColorDisplayItem { - /// Fields common to all display items. - pub base: BaseDisplayItem, - - /// The color. - pub color: ColorF, -} - -/// Paints text. -#[derive(Clone, Deserialize, MallocSizeOf, Serialize)] -pub struct TextDisplayItem { - /// Fields common to all display items. - pub base: BaseDisplayItem, - /// A collection of (non-whitespace) glyphs to be displayed. - pub glyphs: Vec, - /// Reference to the font to be used. - pub font_key: FontInstanceKey, - /// The color of the text. - pub text_color: ColorF, -} - -#[derive(Clone, Deserialize, Eq, MallocSizeOf, PartialEq, Serialize)] -pub enum TextOrientation { - Upright, - SidewaysLeft, - SidewaysRight, -} - -/// Paints an image. -#[derive(Clone, Deserialize, MallocSizeOf, Serialize)] -pub struct ImageDisplayItem { - pub base: BaseDisplayItem, - - pub webrender_image: WebRenderImageInfo, - - /// The dimensions to which the image display item should be stretched. If this is smaller than - /// the bounds of this display item, then the image will be repeated in the appropriate - /// direction to tile the entire bounds. - pub stretch_size: LayoutSize, - - /// The amount of space to add to the right and bottom part of each tile, when the image - /// is tiled. - pub tile_spacing: LayoutSize, - - /// The algorithm we should use to stretch the image. See `image_rendering` in CSS-IMAGES-3 § - /// 5.3. - pub image_rendering: ImageRendering, -} -/// Paints an iframe. -#[derive(Clone, Deserialize, MallocSizeOf, Serialize)] -pub struct IframeDisplayItem { - pub base: BaseDisplayItem, - pub iframe: PipelineId, -} - -/// Paints a gradient. -#[derive(Clone, Deserialize, MallocSizeOf, Serialize)] -pub struct Gradient { - /// The start point of the gradient (computed during display list construction). - pub start_point: LayoutPoint, - - /// The end point of the gradient (computed during display list construction). - pub end_point: LayoutPoint, - - /// A list of color stops. - pub stops: Vec, - - /// Whether the gradient is repeated or clamped. - pub extend_mode: ExtendMode, -} - -#[derive(Clone, Deserialize, MallocSizeOf, Serialize)] -pub struct GradientDisplayItem { - /// Fields common to all display item. - pub base: BaseDisplayItem, - - /// Contains all gradient data. Included start, end point and color stops. - pub gradient: Gradient, - - /// The size of a single gradient tile. - /// - /// The gradient may fill an entire element background - /// but it can be composed from many smaller copys of - /// the same gradient. - /// - /// Without tiles, the tile will be the same size as the background. - pub tile: LayoutSize, - pub tile_spacing: LayoutSize, -} - -/// Paints a radial gradient. -#[derive(Clone, Deserialize, MallocSizeOf, Serialize)] -pub struct RadialGradient { - /// The center point of the gradient. - pub center: LayoutPoint, - - /// The radius of the gradient with an x and an y component. - pub radius: LayoutSize, - - /// A list of color stops. - pub stops: Vec, - - /// Whether the gradient is repeated or clamped. - pub extend_mode: ExtendMode, -} - -#[derive(Clone, Deserialize, MallocSizeOf, Serialize)] -pub struct RadialGradientDisplayItem { - /// Fields common to all display item. - pub base: BaseDisplayItem, - - /// Contains all gradient data. - pub gradient: RadialGradient, - - /// The size of a single gradient tile. - /// - /// The gradient may fill an entire element background - /// but it can be composed from many smaller copys of - /// the same gradient. - /// - /// Without tiles, the tile will be the same size as the background. - pub tile: LayoutSize, - pub tile_spacing: LayoutSize, -} - -/// A border that is made of linear gradient -#[derive(Clone, Deserialize, MallocSizeOf, Serialize)] -pub struct GradientBorder { - /// The gradient info that this border uses, border-image-source. - pub gradient: Gradient, - - /// Outsets for the border, as per border-image-outset. - pub outset: SideOffsets2D, -} - -/// A border that is made of radial gradient -#[derive(Clone, Deserialize, MallocSizeOf, Serialize)] -pub struct RadialGradientBorder { - /// The gradient info that this border uses, border-image-source. - pub gradient: RadialGradient, - - /// Outsets for the border, as per border-image-outset. - pub outset: SideOffsets2D, -} - -/// Specifies the type of border -#[derive(Clone, Deserialize, MallocSizeOf, Serialize)] -pub enum BorderDetails { - Normal(NormalBorder), - Image(ImageBorder), - Gradient(GradientBorder), - RadialGradient(RadialGradientBorder), -} - -/// Paints a border. -#[derive(Clone, Deserialize, MallocSizeOf, Serialize)] -pub struct BorderDisplayItem { - /// Fields common to all display items. - pub base: BaseDisplayItem, - - /// Border widths. - pub border_widths: BorderWidths, - - /// Details for specific border type - pub details: BorderDetails, -} - -/// Paints a line segment. -#[derive(Clone, Deserialize, MallocSizeOf, Serialize)] -pub struct LineDisplayItem { - pub base: BaseDisplayItem, - - /// The line segment color. - pub color: ColorF, - - /// The line segment style. - pub style: LineStyle, -} - -/// Paints a box shadow per CSS-BACKGROUNDS. -#[derive(Clone, Deserialize, MallocSizeOf, Serialize)] -pub struct BoxShadowDisplayItem { - /// Fields common to all display items. - pub base: BaseDisplayItem, - - /// The dimensions of the box that we're placing a shadow around. - pub box_bounds: LayoutRect, - - /// The offset of this shadow from the box. - pub offset: LayoutVector2D, - - /// The color of this shadow. - pub color: ColorF, - - /// The blur radius for this shadow. - pub blur_radius: f32, - - /// The spread radius of this shadow. - pub spread_radius: f32, - - /// The border radius of this shadow. - pub border_radius: BorderRadius, - - /// How we should clip the result. - pub clip_mode: BoxShadowClipMode, -} - -/// Defines a text shadow that affects all items until the paired PopTextShadow. -#[derive(Clone, Deserialize, MallocSizeOf, Serialize)] -pub struct PushTextShadowDisplayItem { - /// Fields common to all display items. - pub base: BaseDisplayItem, - - /// The offset of this shadow from the text. - pub offset: LayoutVector2D, - - /// The color of this shadow. - pub color: ColorF, - - /// The blur radius for this shadow. - pub blur_radius: f32, -} - -/// Defines a text shadow that affects all items until the next PopTextShadow. -#[derive(Clone, Deserialize, MallocSizeOf, Serialize)] -pub struct PopAllTextShadowsDisplayItem { - /// Fields common to all display items. - pub base: BaseDisplayItem, -} - -/// Defines a stacking context. -#[derive(Clone, Deserialize, MallocSizeOf, Serialize)] -pub struct PushStackingContextItem { - /// Fields common to all display items. - pub base: BaseDisplayItem, - - pub stacking_context: StackingContext, -} - -/// Defines a stacking context. -#[derive(Clone, Deserialize, MallocSizeOf, Serialize)] -pub struct PopStackingContextItem { - /// Fields common to all display items. - pub base: BaseDisplayItem, - - pub stacking_context_id: StackingContextId, -} - -/// Starts a group of items inside a particular scroll root. -#[derive(Clone, Deserialize, MallocSizeOf, Serialize)] -pub struct DefineClipScrollNodeItem { - /// Fields common to all display items. - pub base: BaseDisplayItem, - - /// The scroll root that this item starts. - pub node_index: ClipScrollNodeIndex, -} - -impl DisplayItem { - pub fn base(&self) -> &BaseDisplayItem { - match *self { - DisplayItem::SolidColor(ref solid_color) => &solid_color.base, - DisplayItem::Text(ref text) => &text.base, - DisplayItem::Image(ref image_item) => &image_item.base, - DisplayItem::Border(ref border) => &border.base, - DisplayItem::Gradient(ref gradient) => &gradient.base, - DisplayItem::RadialGradient(ref gradient) => &gradient.base, - DisplayItem::Line(ref line) => &line.base, - DisplayItem::BoxShadow(ref box_shadow) => &box_shadow.base, - DisplayItem::PushTextShadow(ref push_text_shadow) => &push_text_shadow.base, - DisplayItem::PopAllTextShadows(ref pop_text_shadow) => &pop_text_shadow.base, - DisplayItem::Iframe(ref iframe) => &iframe.base, - DisplayItem::PushStackingContext(ref stacking_context) => &stacking_context.base, - DisplayItem::PopStackingContext(ref item) => &item.base, - DisplayItem::DefineClipScrollNode(ref item) => &item.base, - } - } - - pub fn scroll_node_index(&self) -> ClipScrollNodeIndex { - self.base().clipping_and_scrolling.scrolling - } - - pub fn clipping_and_scrolling(&self) -> ClippingAndScrolling { - self.base().clipping_and_scrolling - } - - pub fn stacking_context_id(&self) -> StackingContextId { - self.base().stacking_context_id - } - - pub fn section(&self) -> DisplayListSection { - self.base().section - } - - pub fn bounds(&self) -> LayoutRect { - self.base().bounds - } - - pub fn debug_with_level(&self, level: u32) { - let mut indent = String::new(); - for _ in 0..level { - indent.push_str("| ") - } - println!("{}+ {:?}", indent, self); - } -} - -impl fmt::Debug for DisplayItem { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - if let DisplayItem::PushStackingContext(ref item) = *self { - return write!(f, "PushStackingContext({:?})", item.stacking_context); - } - - if let DisplayItem::PopStackingContext(ref item) = *self { - return write!(f, "PopStackingContext({:?}", item.stacking_context_id); - } - - if let DisplayItem::DefineClipScrollNode(ref item) = *self { - return write!(f, "DefineClipScrollNode({:?}", item.node_index); - } - - write!(f, "{} @ {:?} {:?}", - match *self { - DisplayItem::SolidColor(ref solid_color) => - format!("SolidColor rgba({}, {}, {}, {})", - solid_color.color.r, - solid_color.color.g, - solid_color.color.b, - solid_color.color.a), - DisplayItem::Text(_) => "Text".to_owned(), - DisplayItem::Image(_) => "Image".to_owned(), - DisplayItem::Border(_) => "Border".to_owned(), - DisplayItem::Gradient(_) => "Gradient".to_owned(), - DisplayItem::RadialGradient(_) => "RadialGradient".to_owned(), - DisplayItem::Line(_) => "Line".to_owned(), - DisplayItem::BoxShadow(_) => "BoxShadow".to_owned(), - DisplayItem::PushTextShadow(_) => "PushTextShadow".to_owned(), - DisplayItem::PopAllTextShadows(_) => "PopTextShadow".to_owned(), - DisplayItem::Iframe(_) => "Iframe".to_owned(), - DisplayItem::PushStackingContext(_) | - DisplayItem::PopStackingContext(_) | - DisplayItem::DefineClipScrollNode(_) => "".to_owned(), - }, - self.bounds(), - self.base().clip_rect - ) - } -} - -#[derive(Clone, Copy, Deserialize, MallocSizeOf, Serialize)] -pub struct WebRenderImageInfo { - pub width: u32, - pub height: u32, - pub format: PixelFormat, - pub key: Option, -} - -impl WebRenderImageInfo { - #[inline] - pub fn from_image(image: &Image) -> WebRenderImageInfo { - WebRenderImageInfo { - width: image.width, - height: image.height, - format: image.format, - key: image.id, - } - } -} - -/// The type of the scroll offset list. This is only populated if WebRender is in use. -pub type ScrollOffsetMap = HashMap>; - - -pub trait SimpleMatrixDetection { - fn is_identity_or_simple_translation(&self) -> bool; -} - -impl SimpleMatrixDetection for LayoutTransform { - #[inline] - fn is_identity_or_simple_translation(&self) -> bool { - let (_0, _1) = (Zero::zero(), One::one()); - self.m11 == _1 && self.m12 == _0 && self.m13 == _0 && self.m14 == _0 && - self.m21 == _0 && self.m22 == _1 && self.m23 == _0 && self.m24 == _0 && - self.m31 == _0 && self.m32 == _0 && self.m33 == _1 && self.m34 == _0 && - self.m44 == _1 - } -} - diff --git a/servo/components/gfx/font.rs b/servo/components/gfx/font.rs deleted file mode 100644 index 09578168ea7d..000000000000 --- a/servo/components/gfx/font.rs +++ /dev/null @@ -1,447 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -use app_units::Au; -use euclid::{Point2D, Rect, Size2D}; -use font_context::{FontContext, FontSource}; -use font_template::FontTemplateDescriptor; -use ordered_float::NotNaN; -use platform::font::{FontHandle, FontTable}; -use platform::font_context::FontContextHandle; -use platform::font_template::FontTemplateData; -use servo_atoms::Atom; -use smallvec::SmallVec; -use std::borrow::ToOwned; -use std::cell::RefCell; -use std::collections::HashMap; -use std::rc::Rc; -use std::str; -use std::sync::Arc; -use std::sync::atomic::{ATOMIC_USIZE_INIT, AtomicUsize, Ordering}; -use style::computed_values::{font_stretch, font_variant_caps, font_weight}; -use style::properties::style_structs::Font as FontStyleStruct; -use style::values::computed::font::SingleFontFamily; -use text::Shaper; -use text::glyph::{ByteIndex, GlyphData, GlyphId, GlyphStore}; -use text::shaping::ShaperMethods; -use time; -use unicode_script::Script; -use webrender_api; - -macro_rules! ot_tag { - ($t1:expr, $t2:expr, $t3:expr, $t4:expr) => ( - (($t1 as u32) << 24) | (($t2 as u32) << 16) | (($t3 as u32) << 8) | ($t4 as u32) - ); -} - -pub const GPOS: u32 = ot_tag!('G', 'P', 'O', 'S'); -pub const GSUB: u32 = ot_tag!('G', 'S', 'U', 'B'); -pub const KERN: u32 = ot_tag!('k', 'e', 'r', 'n'); - -static TEXT_SHAPING_PERFORMANCE_COUNTER: AtomicUsize = ATOMIC_USIZE_INIT; - -// FontHandle encapsulates access to the platform's font API, -// e.g. quartz, FreeType. It provides access to metrics and tables -// needed by the text shaper as well as access to the underlying font -// resources needed by the graphics layer to draw glyphs. - -pub trait FontHandleMethods: Sized { - fn new_from_template(fctx: &FontContextHandle, template: Arc, pt_size: Option) - -> Result; - fn template(&self) -> Arc; - fn family_name(&self) -> String; - fn face_name(&self) -> Option; - fn is_italic(&self) -> bool; - fn boldness(&self) -> font_weight::T; - fn stretchiness(&self) -> font_stretch::T; - - fn glyph_index(&self, codepoint: char) -> Option; - fn glyph_h_advance(&self, GlyphId) -> Option; - fn glyph_h_kerning(&self, glyph0: GlyphId, glyph1: GlyphId) -> FractionalPixel; - /// Can this font do basic horizontal LTR shaping without Harfbuzz? - fn can_do_fast_shaping(&self) -> bool; - fn metrics(&self) -> FontMetrics; - fn table_for_tag(&self, FontTableTag) -> Option; - - /// A unique identifier for the font, allowing comparison. - fn identifier(&self) -> Atom; -} - -// Used to abstract over the shaper's choice of fixed int representation. -pub type FractionalPixel = f64; - -pub type FontTableTag = u32; - -trait FontTableTagConversions { - fn tag_to_str(&self) -> String; -} - -impl FontTableTagConversions for FontTableTag { - fn tag_to_str(&self) -> String { - let bytes = [(self >> 24) as u8, - (self >> 16) as u8, - (self >> 8) as u8, - (self >> 0) as u8]; - str::from_utf8(&bytes).unwrap().to_owned() - } -} - -pub trait FontTableMethods { - fn buffer(&self) -> &[u8]; -} - -#[derive(Clone, Debug, Deserialize, Serialize)] -pub struct FontMetrics { - pub underline_size: Au, - pub underline_offset: Au, - pub strikeout_size: Au, - pub strikeout_offset: Au, - pub leading: Au, - pub x_height: Au, - pub em_size: Au, - pub ascent: Au, - pub descent: Au, - pub max_advance: Au, - pub average_advance: Au, - pub line_gap: Au, -} - -/// `FontDescriptor` describes the parameters of a `Font`. It represents rendering a given font -/// template at a particular size, with a particular font-variant-caps applied, etc. This contrasts -/// with `FontTemplateDescriptor` in that the latter represents only the parameters inherent in the -/// font data (weight, stretch, etc.). -#[derive(Clone, Debug, PartialEq)] -pub struct FontDescriptor { - pub template_descriptor: FontTemplateDescriptor, - pub variant: font_variant_caps::T, - pub pt_size: Au, -} - -impl<'a> From<&'a FontStyleStruct> for FontDescriptor { - fn from(style: &'a FontStyleStruct) -> Self { - FontDescriptor { - template_descriptor: FontTemplateDescriptor::from(style), - variant: style.font_variant_caps, - pt_size: style.font_size.size(), - } - } -} - -#[derive(Debug)] -pub struct Font { - pub handle: FontHandle, - pub metrics: FontMetrics, - pub descriptor: FontDescriptor, - pub actual_pt_size: Au, - shaper: Option, - shape_cache: RefCell>>, - glyph_advance_cache: RefCell>, - pub font_key: webrender_api::FontInstanceKey, -} - -impl Font { - pub fn new(handle: FontHandle, - descriptor: FontDescriptor, - actual_pt_size: Au, - font_key: webrender_api::FontInstanceKey) -> Font { - let metrics = handle.metrics(); - - Font { - handle: handle, - shaper: None, - descriptor, - actual_pt_size, - metrics, - shape_cache: RefCell::new(HashMap::new()), - glyph_advance_cache: RefCell::new(HashMap::new()), - font_key, - } - } - - /// A unique identifier for the font, allowing comparison. - pub fn identifier(&self) -> Atom { - self.handle.identifier() - } -} - -bitflags! { - pub struct ShapingFlags: u8 { - #[doc = "Set if the text is entirely whitespace."] - const IS_WHITESPACE_SHAPING_FLAG = 0x01; - #[doc = "Set if we are to ignore ligatures."] - const IGNORE_LIGATURES_SHAPING_FLAG = 0x02; - #[doc = "Set if we are to disable kerning."] - const DISABLE_KERNING_SHAPING_FLAG = 0x04; - #[doc = "Text direction is right-to-left."] - const RTL_FLAG = 0x08; - #[doc = "Set if word-break is set to keep-all."] - const KEEP_ALL_FLAG = 0x10; - } -} - -/// Various options that control text shaping. -#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)] -pub struct ShapingOptions { - /// Spacing to add between each letter. Corresponds to the CSS 2.1 `letter-spacing` property. - /// NB: You will probably want to set the `IGNORE_LIGATURES_SHAPING_FLAG` if this is non-null. - pub letter_spacing: Option, - /// Spacing to add between each word. Corresponds to the CSS 2.1 `word-spacing` property. - pub word_spacing: (Au, NotNaN), - /// The Unicode script property of the characters in this run. - pub script: Script, - /// Various flags. - pub flags: ShapingFlags, -} - -/// An entry in the shape cache. -#[derive(Clone, Debug, Eq, Hash, PartialEq)] -struct ShapeCacheEntry { - text: String, - options: ShapingOptions, -} - -impl Font { - pub fn shape_text(&mut self, text: &str, options: &ShapingOptions) -> Arc { - let this = self as *const Font; - let mut shaper = self.shaper.take(); - - let lookup_key = ShapeCacheEntry { - text: text.to_owned(), - options: *options, - }; - let result = self.shape_cache.borrow_mut().entry(lookup_key).or_insert_with(|| { - let start_time = time::precise_time_ns(); - let mut glyphs = GlyphStore::new(text.len(), - options.flags.contains(ShapingFlags::IS_WHITESPACE_SHAPING_FLAG), - options.flags.contains(ShapingFlags::RTL_FLAG)); - - if self.can_do_fast_shaping(text, options) { - debug!("shape_text: Using ASCII fast path."); - self.shape_text_fast(text, options, &mut glyphs); - } else { - debug!("shape_text: Using Harfbuzz."); - if shaper.is_none() { - shaper = Some(Shaper::new(this)); - } - shaper.as_ref().unwrap().shape_text(text, options, &mut glyphs); - } - - let end_time = time::precise_time_ns(); - TEXT_SHAPING_PERFORMANCE_COUNTER.fetch_add((end_time - start_time) as usize, - Ordering::Relaxed); - Arc::new(glyphs) - }).clone(); - self.shaper = shaper; - result - } - - fn can_do_fast_shaping(&self, text: &str, options: &ShapingOptions) -> bool { - options.script == Script::Latin && - !options.flags.contains(ShapingFlags::RTL_FLAG) && - self.handle.can_do_fast_shaping() && - text.is_ascii() - } - - /// Fast path for ASCII text that only needs simple horizontal LTR kerning. - fn shape_text_fast(&self, text: &str, options: &ShapingOptions, glyphs: &mut GlyphStore) { - let mut prev_glyph_id = None; - for (i, byte) in text.bytes().enumerate() { - let character = byte as char; - let glyph_id = match self.glyph_index(character) { - Some(id) => id, - None => continue, - }; - - let mut advance = Au::from_f64_px(self.glyph_h_advance(glyph_id)); - if character == ' ' { - // https://drafts.csswg.org/css-text-3/#word-spacing-property - let (length, percent) = options.word_spacing; - advance = (advance + length) + Au((advance.0 as f32 * percent.into_inner()) as i32); - } - if let Some(letter_spacing) = options.letter_spacing { - advance += letter_spacing; - } - let offset = prev_glyph_id.map(|prev| { - let h_kerning = Au::from_f64_px(self.glyph_h_kerning(prev, glyph_id)); - advance += h_kerning; - Point2D::new(h_kerning, Au(0)) - }); - - let glyph = GlyphData::new(glyph_id, advance, offset, true, true); - glyphs.add_glyph_for_byte_index(ByteIndex(i as isize), character, &glyph); - prev_glyph_id = Some(glyph_id); - } - glyphs.finalize_changes(); - } - - pub fn table_for_tag(&self, tag: FontTableTag) -> Option { - let result = self.handle.table_for_tag(tag); - let status = if result.is_some() { "Found" } else { "Didn't find" }; - - debug!("{} font table[{}] with family={}, face={}", - status, tag.tag_to_str(), - self.handle.family_name(), self.handle.face_name().unwrap_or("unavailable".to_owned())); - - result - } - - #[inline] - pub fn glyph_index(&self, codepoint: char) -> Option { - let codepoint = match self.descriptor.variant { - font_variant_caps::T::SmallCaps => codepoint.to_uppercase().next().unwrap(), //FIXME: #5938 - font_variant_caps::T::Normal => codepoint, - }; - self.handle.glyph_index(codepoint) - } - - pub fn has_glyph_for(&self, codepoint: char) -> bool { - self.glyph_index(codepoint).is_some() - } - - pub fn glyph_h_kerning(&self, first_glyph: GlyphId, second_glyph: GlyphId) - -> FractionalPixel { - self.handle.glyph_h_kerning(first_glyph, second_glyph) - } - - pub fn glyph_h_advance(&self, glyph: GlyphId) -> FractionalPixel { - *self.glyph_advance_cache.borrow_mut().entry(glyph).or_insert_with(|| { - match self.handle.glyph_h_advance(glyph) { - Some(adv) => adv, - None => 10f64 as FractionalPixel // FIXME: Need fallback strategy - } - }) - } -} - -pub type FontRef = Rc>; - -/// A `FontGroup` is a prioritised list of fonts for a given set of font styles. It is used by -/// `TextRun` to decide which font to render a character with. If none of the fonts listed in the -/// styles are suitable, a fallback font may be used. -#[derive(Debug)] -pub struct FontGroup { - descriptor: FontDescriptor, - families: SmallVec<[FontGroupFamily; 8]>, -} - -impl FontGroup { - pub fn new(style: &FontStyleStruct) -> FontGroup { - let descriptor = FontDescriptor::from(style); - - let families = - style.font_family.0.iter() - .map(|family| FontGroupFamily::new(descriptor.clone(), family.clone())) - .collect(); - - FontGroup { descriptor, families } - } - - /// Finds the first font, or else the first fallback font, which contains a glyph for - /// `codepoint`. If no such font is found, returns the first available font or fallback font - /// (which will cause a "glyph not found" character to be rendered). If no font at all can be - /// found, returns None. - pub fn find_by_codepoint( - &mut self, - mut font_context: &mut FontContext, - codepoint: char - ) -> Option { - self.find(&mut font_context, |font| font.borrow().has_glyph_for(codepoint)) - .or_else(|| self.first(&mut font_context)) - } - - pub fn first( - &mut self, - mut font_context: &mut FontContext - ) -> Option { - self.find(&mut font_context, |_| true) - } - - /// Find a font which returns true for `predicate`. This method mutates because we may need to - /// load new font data in the process of finding a suitable font. - fn find( - &mut self, - mut font_context: &mut FontContext, - mut predicate: P - ) -> Option - where - S: FontSource, - P: FnMut(&FontRef) -> bool - { - self.families.iter_mut() - .filter_map(|family| family.font(&mut font_context)) - .find(|f| predicate(f)) - .or_else(|| { - font_context.fallback_font(&self.descriptor) - .into_iter().find(predicate) - }) - } -} - -/// A `FontGroupFamily` is a single font family in a `FontGroup`. It corresponds to one of the -/// families listed in the `font-family` CSS property. The corresponding font data is lazy-loaded, -/// only if actually needed. -#[derive(Debug)] -struct FontGroupFamily { - descriptor: FontDescriptor, - family: SingleFontFamily, - loaded: bool, - font: Option, -} - -impl FontGroupFamily { - fn new(descriptor: FontDescriptor, family: SingleFontFamily) -> FontGroupFamily { - FontGroupFamily { - descriptor, - family, - loaded: false, - font: None, - } - } - - /// Returns the font within this family which matches the style. We'll fetch the data from the - /// `FontContext` the first time this method is called, and return a cached reference on - /// subsequent calls. - fn font(&mut self, font_context: &mut FontContext) -> Option { - if !self.loaded { - self.font = font_context.font(&self.descriptor, &self.family); - self.loaded = true; - } - - self.font.clone() - } -} - -pub struct RunMetrics { - // may be negative due to negative width (i.e., kerning of '.' in 'P.T.') - pub advance_width: Au, - pub ascent: Au, // nonzero - pub descent: Au, // nonzero - // this bounding box is relative to the left origin baseline. - // so, bounding_box.position.y = -ascent - pub bounding_box: Rect -} - -impl RunMetrics { - pub fn new(advance: Au, ascent: Au, descent: Au) -> RunMetrics { - let bounds = Rect::new(Point2D::new(Au(0), -ascent), - Size2D::new(advance, ascent + descent)); - - // TODO(Issue #125): support loose and tight bounding boxes; using the - // ascent+descent and advance is sometimes too generous and - // looking at actual glyph extents can yield a tighter box. - - RunMetrics { - advance_width: advance, - bounding_box: bounds, - ascent: ascent, - descent: descent, - } - } -} - -pub fn get_and_reset_text_shaping_performance_counter() -> usize { - let value = TEXT_SHAPING_PERFORMANCE_COUNTER.load(Ordering::SeqCst); - TEXT_SHAPING_PERFORMANCE_COUNTER.store(0, Ordering::SeqCst); - value -} diff --git a/servo/components/gfx/font_cache_thread.rs b/servo/components/gfx/font_cache_thread.rs deleted file mode 100644 index fdb48e519fe5..000000000000 --- a/servo/components/gfx/font_cache_thread.rs +++ /dev/null @@ -1,556 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -use app_units::Au; -use font_context::FontSource; -use font_template::{FontTemplate, FontTemplateDescriptor}; -use fontsan; -use ipc_channel::ipc::{self, IpcReceiver, IpcSender}; -use net_traits::{CoreResourceThread, FetchResponseMsg, fetch_async}; -use net_traits::request::{Destination, RequestInit}; -use platform::font_context::FontContextHandle; -use platform::font_list::SANS_SERIF_FONT_FAMILY; -use platform::font_list::for_each_available_family; -use platform::font_list::for_each_variation; -use platform::font_list::last_resort_font_families; -use platform::font_list::system_default_family; -use platform::font_template::FontTemplateData; -use servo_atoms::Atom; -use servo_url::ServoUrl; -use std::borrow::ToOwned; -use std::collections::HashMap; -use std::fmt; -use std::mem; -use std::ops::Deref; -use std::sync::{Arc, Mutex}; -use std::thread; -use std::u32; -use style::font_face::{EffectiveSources, Source}; -use style::values::computed::font::{SingleFontFamily, FamilyName}; -use webrender_api; - -/// A list of font templates that make up a given font family. -pub struct FontTemplates { - templates: Vec, -} - -#[derive(Debug, Deserialize, Serialize)] -pub struct FontTemplateInfo { - pub font_template: Arc, - pub font_key: webrender_api::FontKey, -} - -impl FontTemplates { - pub fn new() -> FontTemplates { - FontTemplates { - templates: vec!(), - } - } - - /// Find a font in this family that matches a given descriptor. - pub fn find_font_for_style(&mut self, desc: &FontTemplateDescriptor, fctx: &FontContextHandle) - -> Option> { - // TODO(Issue #189): optimize lookup for - // regular/bold/italic/bolditalic with fixed offsets and a - // static decision table for fallback between these values. - for template in &mut self.templates { - let maybe_template = template.data_for_descriptor(fctx, desc); - if maybe_template.is_some() { - return maybe_template; - } - } - - // We didn't find an exact match. Do more expensive fuzzy matching. - // TODO(#190): Do a better job. - let (mut best_template_data, mut best_distance) = (None, u32::MAX); - for template in &mut self.templates { - if let Some((template_data, distance)) = - template.data_for_approximate_descriptor(fctx, desc) { - if distance < best_distance { - best_template_data = Some(template_data); - best_distance = distance - } - } - } - if best_template_data.is_some() { - return best_template_data - } - - // If a request is made for a font family that exists, - // pick the first valid font in the family if we failed - // to find an exact match for the descriptor. - for template in &mut self.templates { - let maybe_template = template.get(); - if maybe_template.is_some() { - return maybe_template; - } - } - - None - } - - pub fn add_template(&mut self, identifier: Atom, maybe_data: Option>) { - for template in &self.templates { - if *template.identifier() == identifier { - return; - } - } - - if let Ok(template) = FontTemplate::new(identifier, maybe_data) { - self.templates.push(template); - } - } -} - -/// Commands that the FontContext sends to the font cache thread. -#[derive(Debug, Deserialize, Serialize)] -pub enum Command { - GetFontTemplate(SingleFontFamily, FontTemplateDescriptor, IpcSender), - GetLastResortFontTemplate(FontTemplateDescriptor, IpcSender), - GetFontInstance(webrender_api::FontKey, Au, IpcSender), - AddWebFont(LowercaseString, EffectiveSources, IpcSender<()>), - AddDownloadedWebFont(LowercaseString, ServoUrl, Vec, IpcSender<()>), - Exit(IpcSender<()>), - Ping, -} - -/// Reply messages sent from the font cache thread to the FontContext caller. -#[derive(Debug, Deserialize, Serialize)] -pub enum Reply { - GetFontTemplateReply(Option), -} - -/// The font cache thread itself. It maintains a list of reference counted -/// font templates that are currently in use. -struct FontCache { - port: IpcReceiver, - channel_to_self: IpcSender, - generic_fonts: HashMap, - local_families: HashMap, - web_families: HashMap, - font_context: FontContextHandle, - core_resource_thread: CoreResourceThread, - webrender_api: webrender_api::RenderApi, - webrender_fonts: HashMap, - font_instances: HashMap<(webrender_api::FontKey, Au), webrender_api::FontInstanceKey>, -} - -fn populate_generic_fonts() -> HashMap { - let mut generic_fonts = HashMap::with_capacity(5); - - append_map(&mut generic_fonts, SingleFontFamily::Generic(atom!("serif")), "Times New Roman"); - append_map(&mut generic_fonts, SingleFontFamily::Generic(atom!("sans-serif")), SANS_SERIF_FONT_FAMILY); - append_map(&mut generic_fonts, SingleFontFamily::Generic(atom!("cursive")), "Apple Chancery"); - append_map(&mut generic_fonts, SingleFontFamily::Generic(atom!("fantasy")), "Papyrus"); - append_map(&mut generic_fonts, SingleFontFamily::Generic(atom!("monospace")), "Menlo"); - - fn append_map(generic_fonts: &mut HashMap, - font_family: SingleFontFamily, - mapped_name: &str) { - let family_name = { - let opt_system_default = system_default_family(font_family.name()); - match opt_system_default { - Some(system_default) => LowercaseString::new(&system_default), - None => LowercaseString::new(mapped_name) - } - }; - - generic_fonts.insert(font_family, family_name); - } - - - generic_fonts -} - -impl FontCache { - fn run(&mut self) { - loop { - let msg = self.port.recv().unwrap(); - - match msg { - Command::GetFontTemplate(family, descriptor, result) => { - let maybe_font_template = self.find_font_template(&family, &descriptor); - let _ = result.send(Reply::GetFontTemplateReply(maybe_font_template)); - } - Command::GetLastResortFontTemplate(descriptor, result) => { - let font_template = self.last_resort_font_template(&descriptor); - let _ = result.send(Reply::GetFontTemplateReply(Some(font_template))); - } - Command::GetFontInstance(font_key, size, result) => { - let webrender_api = &self.webrender_api; - - let instance_key = *self.font_instances - .entry((font_key, size)) - .or_insert_with(|| { - let key = webrender_api.generate_font_instance_key(); - let mut updates = webrender_api::ResourceUpdates::new(); - updates.add_font_instance(key, - font_key, - size, - None, - None, - Vec::new()); - webrender_api.update_resources(updates); - key - }); - - let _ = result.send(instance_key); - } - Command::AddWebFont(family_name, sources, result) => { - self.handle_add_web_font(family_name, sources, result); - } - Command::AddDownloadedWebFont(family_name, url, bytes, result) => { - let templates = &mut self.web_families.get_mut(&family_name).unwrap(); - templates.add_template(Atom::from(url.to_string()), Some(bytes)); - drop(result.send(())); - } - Command::Ping => (), - Command::Exit(result) => { - let _ = result.send(()); - break; - } - } - } - } - - fn handle_add_web_font(&mut self, - family_name: LowercaseString, - mut sources: EffectiveSources, - sender: IpcSender<()>) { - let src = if let Some(src) = sources.next() { - src - } else { - sender.send(()).unwrap(); - return; - }; - - if !self.web_families.contains_key(&family_name) { - let templates = FontTemplates::new(); - self.web_families.insert(family_name.clone(), templates); - } - - match src { - Source::Url(url_source) => { - // https://drafts.csswg.org/css-fonts/#font-fetching-requirements - let url = match url_source.url.url() { - Some(url) => url.clone(), - None => return, - }; - - let request = RequestInit { - url: url.clone(), - destination: Destination::Font, - // TODO: Add a proper origin - Can't import GlobalScope from gfx - // We can leave origin to be set by default - .. RequestInit::default() - }; - - let channel_to_self = self.channel_to_self.clone(); - let bytes = Mutex::new(Vec::new()); - let response_valid = Mutex::new(false); - debug!("Loading @font-face {} from {}", family_name, url); - fetch_async(request, &self.core_resource_thread, move |response| { - match response { - FetchResponseMsg::ProcessRequestBody | - FetchResponseMsg::ProcessRequestEOF => (), - FetchResponseMsg::ProcessResponse(meta_result) => { - trace!("@font-face {} metadata ok={:?}", family_name, meta_result.is_ok()); - *response_valid.lock().unwrap() = meta_result.is_ok(); - } - FetchResponseMsg::ProcessResponseChunk(new_bytes) => { - trace!("@font-face {} chunk={:?}", family_name, new_bytes); - if *response_valid.lock().unwrap() { - bytes.lock().unwrap().extend(new_bytes.into_iter()) - } - } - FetchResponseMsg::ProcessResponseEOF(response) => { - trace!("@font-face {} EOF={:?}", family_name, response); - if response.is_err() || !*response_valid.lock().unwrap() { - let msg = Command::AddWebFont(family_name.clone(), sources.clone(), sender.clone()); - channel_to_self.send(msg).unwrap(); - return; - } - let bytes = mem::replace(&mut *bytes.lock().unwrap(), vec![]); - trace!("@font-face {} data={:?}", family_name, bytes); - let bytes = match fontsan::process(&bytes) { - Ok(san) => san, - Err(_) => { - // FIXME(servo/fontsan#1): get an error message - debug!("Sanitiser rejected web font: \ - family={} url={:?}", family_name, url); - let msg = Command::AddWebFont(family_name.clone(), sources.clone(), sender.clone()); - channel_to_self.send(msg).unwrap(); - return; - }, - }; - let command = - Command::AddDownloadedWebFont(family_name.clone(), - url.clone(), - bytes, - sender.clone()); - channel_to_self.send(command).unwrap(); - } - } - }); - } - Source::Local(ref font) => { - let font_face_name = LowercaseString::new(&font.name); - let templates = &mut self.web_families.get_mut(&family_name).unwrap(); - let mut found = false; - for_each_variation(&font_face_name, |path| { - found = true; - templates.add_template(Atom::from(&*path), None); - }); - if found { - sender.send(()).unwrap(); - } else { - let msg = Command::AddWebFont(family_name, sources, sender); - self.channel_to_self.send(msg).unwrap(); - } - } - } - } - - fn refresh_local_families(&mut self) { - self.local_families.clear(); - for_each_available_family(|family_name| { - let family_name = LowercaseString::new(&family_name); - if !self.local_families.contains_key(&family_name) { - let templates = FontTemplates::new(); - self.local_families.insert(family_name, templates); - } - }); - } - - fn transform_family(&self, family: &SingleFontFamily) -> LowercaseString { - match self.generic_fonts.get(family) { - None => LowercaseString::new(family.name()), - Some(mapped_family) => (*mapped_family).clone() - } - } - - fn find_font_in_local_family(&mut self, family_name: &LowercaseString, desc: &FontTemplateDescriptor) - -> Option> { - // TODO(Issue #188): look up localized font family names if canonical name not found - // look up canonical name - if self.local_families.contains_key(family_name) { - debug!("FontList: Found font family with name={}", &**family_name); - let s = self.local_families.get_mut(family_name).unwrap(); - - if s.templates.is_empty() { - for_each_variation(family_name, |path| { - s.add_template(Atom::from(&*path), None); - }); - } - - // TODO(Issue #192: handle generic font families, like 'serif' and 'sans-serif'. - // if such family exists, try to match style to a font - - s.find_font_for_style(desc, &self.font_context) - } else { - debug!("FontList: Couldn't find font family with name={}", &**family_name); - None - } - } - - fn find_font_in_web_family(&mut self, family: &SingleFontFamily, desc: &FontTemplateDescriptor) - -> Option> { - let family_name = LowercaseString::new(family.name()); - - if self.web_families.contains_key(&family_name) { - let templates = self.web_families.get_mut(&family_name).unwrap(); - templates.find_font_for_style(desc, &self.font_context) - } else { - None - } - } - - fn get_font_template_info(&mut self, template: Arc) -> FontTemplateInfo { - let webrender_api = &self.webrender_api; - let webrender_fonts = &mut self.webrender_fonts; - - let font_key = *webrender_fonts.entry(template.identifier.clone()).or_insert_with(|| { - let font_key = webrender_api.generate_font_key(); - let mut updates = webrender_api::ResourceUpdates::new(); - match (template.bytes_if_in_memory(), template.native_font()) { - (Some(bytes), _) => updates.add_raw_font(font_key, bytes, 0), - (None, Some(native_font)) => updates.add_native_font(font_key, native_font), - (None, None) => updates.add_raw_font(font_key, template.bytes().clone(), 0), - } - webrender_api.update_resources(updates); - font_key - }); - - FontTemplateInfo { - font_template: template, - font_key: font_key, - } - } - - fn find_font_template(&mut self, family: &SingleFontFamily, desc: &FontTemplateDescriptor) - -> Option { - let template = self.find_font_in_web_family(family, desc) - .or_else(|| { - let transformed_family = self.transform_family(family); - self.find_font_in_local_family(&transformed_family, desc) - }); - - template.map(|template| { - self.get_font_template_info(template) - }) - } - - fn last_resort_font_template(&mut self, desc: &FontTemplateDescriptor) - -> FontTemplateInfo { - let last_resort = last_resort_font_families(); - - for family in &last_resort { - let family = LowercaseString::new(family); - let maybe_font_in_family = self.find_font_in_local_family(&family, desc); - if let Some(family) = maybe_font_in_family { - return self.get_font_template_info(family) - } - } - - panic!("Unable to find any fonts that match (do you have fallback fonts installed?)"); - } -} - -/// The public interface to the font cache thread, used by per-thread `FontContext` instances (via -/// the `FontSource` trait), and also by layout. -#[derive(Clone, Debug, Deserialize, Serialize)] -pub struct FontCacheThread { - chan: IpcSender, -} - -impl FontCacheThread { - pub fn new(core_resource_thread: CoreResourceThread, - webrender_api: webrender_api::RenderApi) -> FontCacheThread { - let (chan, port) = ipc::channel().unwrap(); - - let channel_to_self = chan.clone(); - thread::Builder::new().name("FontCacheThread".to_owned()).spawn(move || { - // TODO: Allow users to specify these. - let generic_fonts = populate_generic_fonts(); - - let mut cache = FontCache { - port: port, - channel_to_self, - generic_fonts, - local_families: HashMap::new(), - web_families: HashMap::new(), - font_context: FontContextHandle::new(), - core_resource_thread, - webrender_api, - webrender_fonts: HashMap::new(), - font_instances: HashMap::new(), - }; - - cache.refresh_local_families(); - cache.run(); - }).expect("Thread spawning failed"); - - FontCacheThread { - chan: chan, - } - } - - pub fn add_web_font(&self, family: FamilyName, sources: EffectiveSources, sender: IpcSender<()>) { - self.chan.send(Command::AddWebFont(LowercaseString::new(&family.name), sources, sender)).unwrap(); - } - - pub fn exit(&self) { - let (response_chan, response_port) = ipc::channel().unwrap(); - self.chan.send(Command::Exit(response_chan)).expect("Couldn't send FontCacheThread exit message"); - response_port.recv().expect("Couldn't receive FontCacheThread reply"); - } -} - -impl FontSource for FontCacheThread { - fn get_font_instance(&mut self, key: webrender_api::FontKey, size: Au) -> webrender_api::FontInstanceKey { - let (response_chan, response_port) = - ipc::channel().expect("failed to create IPC channel"); - self.chan.send(Command::GetFontInstance(key, size, response_chan)) - .expect("failed to send message to font cache thread"); - - let instance_key = response_port.recv(); - if instance_key.is_err() { - let font_thread_has_closed = self.chan.send(Command::Ping).is_err(); - assert!(font_thread_has_closed, "Failed to receive a response from live font cache"); - panic!("Font cache thread has already exited."); - } - instance_key.unwrap() - } - - fn find_font_template(&mut self, family: SingleFontFamily, desc: FontTemplateDescriptor) - -> Option { - let (response_chan, response_port) = - ipc::channel().expect("failed to create IPC channel"); - self.chan.send(Command::GetFontTemplate(family, desc, response_chan)) - .expect("failed to send message to font cache thread"); - - let reply = response_port.recv(); - - if reply.is_err() { - let font_thread_has_closed = self.chan.send(Command::Ping).is_err(); - assert!(font_thread_has_closed, "Failed to receive a response from live font cache"); - panic!("Font cache thread has already exited."); - } - - match reply.unwrap() { - Reply::GetFontTemplateReply(data) => { - data - } - } - } - - fn last_resort_font_template(&mut self, desc: FontTemplateDescriptor) - -> FontTemplateInfo { - let (response_chan, response_port) = - ipc::channel().expect("failed to create IPC channel"); - self.chan.send(Command::GetLastResortFontTemplate(desc, response_chan)) - .expect("failed to send message to font cache thread"); - - let reply = response_port.recv(); - if reply.is_err() { - let font_thread_has_closed = self.chan.send(Command::Ping).is_err(); - assert!(font_thread_has_closed, "Failed to receive a response from live font cache"); - panic!("Font cache thread has already exited."); - } - - match reply.unwrap() { - Reply::GetFontTemplateReply(data) => { - data.unwrap() - } - } - } -} - -#[derive(Clone, Debug, Deserialize, Eq, Hash, PartialEq, Serialize)] -pub struct LowercaseString { - inner: String, -} - -impl LowercaseString { - pub fn new(s: &str) -> LowercaseString { - LowercaseString { - inner: s.to_lowercase(), - } - } -} - -impl Deref for LowercaseString { - type Target = str; - - #[inline] - fn deref(&self) -> &str { - &*self.inner - } -} - -impl fmt::Display for LowercaseString { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - self.inner.fmt(f) - } -} diff --git a/servo/components/gfx/font_context.rs b/servo/components/gfx/font_context.rs deleted file mode 100644 index a680f59dc44a..000000000000 --- a/servo/components/gfx/font_context.rs +++ /dev/null @@ -1,266 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -use app_units::Au; -use fnv::FnvHasher; -use font::{Font, FontDescriptor, FontGroup, FontHandleMethods, FontRef}; -use font_cache_thread::FontTemplateInfo; -use font_template::FontTemplateDescriptor; -use malloc_size_of::{MallocSizeOf, MallocSizeOfOps}; -use platform::font::FontHandle; -pub use platform::font_context::FontContextHandle; -use servo_arc::Arc; -use servo_atoms::Atom; -use std::cell::RefCell; -use std::collections::HashMap; -use std::default::Default; -use std::hash::{BuildHasherDefault, Hash, Hasher}; -use std::rc::Rc; -use std::sync::atomic::{AtomicUsize, Ordering, ATOMIC_USIZE_INIT}; -use style::computed_values::font_variant_caps::T as FontVariantCaps; -use style::properties::style_structs::Font as FontStyleStruct; -use style::values::computed::font::SingleFontFamily; -use webrender_api; - -static SMALL_CAPS_SCALE_FACTOR: f32 = 0.8; // Matches FireFox (see gfxFont.h) - -#[derive(Debug)] -struct FontCacheEntry { - family: Atom, - font: Option, -} - -impl FontCacheEntry { - fn matches(&self, descriptor: &FontDescriptor, family: &SingleFontFamily) -> bool { - if self.family != *family.atom() { - return false - } - - if let Some(ref font) = self.font { - (*font).borrow().descriptor == *descriptor - } else { - true - } - } -} - -#[derive(Debug)] -struct FallbackFontCacheEntry { - font: FontRef, -} - -impl FallbackFontCacheEntry { - fn matches(&self, descriptor: &FontDescriptor) -> bool { - self.font.borrow().descriptor == *descriptor - } -} - -/// An epoch for the font context cache. The cache is flushed if the current epoch does not match -/// this one. -static FONT_CACHE_EPOCH: AtomicUsize = ATOMIC_USIZE_INIT; - -pub trait FontSource { - fn get_font_instance(&mut self, key: webrender_api::FontKey, size: Au) -> webrender_api::FontInstanceKey; - - fn find_font_template( - &mut self, - family: SingleFontFamily, - desc: FontTemplateDescriptor - ) -> Option; - - fn last_resort_font_template(&mut self, desc: FontTemplateDescriptor) -> FontTemplateInfo; -} - -/// The FontContext represents the per-thread/thread state necessary for -/// working with fonts. It is the public API used by the layout and -/// paint code. It talks directly to the font cache thread where -/// required. -#[derive(Debug)] -pub struct FontContext { - platform_handle: FontContextHandle, - font_source: S, - - // TODO: The font context holds a strong ref to the cached fonts - // so they will never be released. Find out a good time to drop them. - // See bug https://github.com/servo/servo/issues/3300 - // - // GWTODO: Check on real pages if this is faster as Vec() or HashMap(). - font_cache: Vec, - fallback_font_cache: Vec, - - font_group_cache: - HashMap>, BuildHasherDefault>, - - epoch: usize, -} - -impl FontContext { - pub fn new(font_source: S) -> FontContext { - let handle = FontContextHandle::new(); - FontContext { - platform_handle: handle, - font_source, - font_cache: vec!(), - fallback_font_cache: vec!(), - font_group_cache: HashMap::with_hasher(Default::default()), - epoch: 0, - } - } - - /// Create a `Font` for use in layout calculations, from a `FontTemplateInfo` returned by the - /// cache thread (which contains the underlying font data) and a `FontDescriptor` which - /// contains the styling parameters. - fn create_font(&mut self, info: FontTemplateInfo, descriptor: FontDescriptor) -> Result { - // TODO: (Bug #3463): Currently we only support fake small-caps - // painting. We should also support true small-caps (where the - // font supports it) in the future. - let actual_pt_size = match descriptor.variant { - FontVariantCaps::SmallCaps => descriptor.pt_size.scale_by(SMALL_CAPS_SCALE_FACTOR), - FontVariantCaps::Normal => descriptor.pt_size, - }; - - let handle = FontHandle::new_from_template(&self.platform_handle, - info.font_template, - Some(actual_pt_size))?; - - let font_instance_key = self.font_source.get_font_instance(info.font_key, actual_pt_size); - Ok(Font::new(handle, descriptor.to_owned(), actual_pt_size, font_instance_key)) - } - - fn expire_font_caches_if_necessary(&mut self) { - let current_epoch = FONT_CACHE_EPOCH.load(Ordering::SeqCst); - if current_epoch == self.epoch { - return - } - - self.font_cache.clear(); - self.fallback_font_cache.clear(); - self.font_group_cache.clear(); - self.epoch = current_epoch - } - - /// Returns a `FontGroup` representing fonts which can be used for layout, given the `style`. - /// Font groups are cached, so subsequent calls with the same `style` will return a reference - /// to an existing `FontGroup`. - pub fn font_group(&mut self, style: Arc) -> Rc> { - self.expire_font_caches_if_necessary(); - - let cache_key = FontGroupCacheKey { - size: style.font_size.size(), - style, - }; - - if let Some(ref font_group) = self.font_group_cache.get(&cache_key) { - return (*font_group).clone() - } - - let font_group = Rc::new(RefCell::new(FontGroup::new(&cache_key.style))); - self.font_group_cache.insert(cache_key, font_group.clone()); - font_group - } - - /// Returns a reference to an existing font cache entry matching `descriptor` and `family`, if - /// there is one. - fn font_cache_entry(&self, descriptor: &FontDescriptor, family: &SingleFontFamily) -> Option<&FontCacheEntry> { - self.font_cache.iter() - .find(|cache_entry| cache_entry.matches(&descriptor, &family)) - } - - /// Creates a new font cache entry matching `descriptor` and `family`. - fn create_font_cache_entry(&mut self, descriptor: &FontDescriptor, family: &SingleFontFamily) -> FontCacheEntry { - let font = - self.font_source.find_font_template(family.clone(), descriptor.template_descriptor.clone()) - .and_then(|template_info| - self.create_font(template_info, descriptor.to_owned()).ok() - ) - .map(|font| Rc::new(RefCell::new(font))); - - FontCacheEntry { family: family.atom().to_owned(), font } - } - - /// Returns a font from `family` matching the `descriptor`. Fonts are cached, so repeated calls - /// will return a reference to the same underlying `Font`. - pub fn font(&mut self, descriptor: &FontDescriptor, family: &SingleFontFamily) -> Option { - if let Some(entry) = self.font_cache_entry(descriptor, family) { - return entry.font.clone() - } - - let entry = self.create_font_cache_entry(descriptor, family); - let font = entry.font.clone(); - self.font_cache.push(entry); - font - } - - /// Returns a reference to an existing fallback font cache entry matching `descriptor`, if - /// there is one. - fn fallback_font_cache_entry(&self, descriptor: &FontDescriptor) -> Option<&FallbackFontCacheEntry> { - self.fallback_font_cache.iter() - .find(|cache_entry| cache_entry.matches(descriptor)) - } - - /// Creates a new fallback font cache entry matching `descriptor`. - fn create_fallback_font_cache_entry(&mut self, descriptor: &FontDescriptor) -> Option { - let template_info = self.font_source.last_resort_font_template(descriptor.template_descriptor.clone()); - - match self.create_font(template_info, descriptor.to_owned()) { - Ok(font) => - Some(FallbackFontCacheEntry { - font: Rc::new(RefCell::new(font)) - }), - - Err(_) => { - debug!("Failed to create fallback font!"); - None - } - } - } - - /// Returns a fallback font matching the `descriptor`. Fonts are cached, so repeated calls will - /// return a reference to the same underlying `Font`. - pub fn fallback_font(&mut self, descriptor: &FontDescriptor) -> Option { - if let Some(cached_entry) = self.fallback_font_cache_entry(descriptor) { - return Some(cached_entry.font.clone()) - }; - - if let Some(entry) = self.create_fallback_font_cache_entry(descriptor) { - let font = entry.font.clone(); - self.fallback_font_cache.push(entry); - Some(font) - } else { - None - } - } -} - -impl MallocSizeOf for FontContext { - fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize { - // FIXME(njn): Measure other fields eventually. - self.platform_handle.size_of(ops) - } -} - -#[derive(Debug)] -struct FontGroupCacheKey { - style: Arc, - size: Au, -} - -impl PartialEq for FontGroupCacheKey { - fn eq(&self, other: &FontGroupCacheKey) -> bool { - self.style == other.style && self.size == other.size - } -} - -impl Eq for FontGroupCacheKey {} - -impl Hash for FontGroupCacheKey { - fn hash(&self, hasher: &mut H) where H: Hasher { - self.style.hash.hash(hasher) - } -} - -#[inline] -pub fn invalidate_font_caches() { - FONT_CACHE_EPOCH.fetch_add(1, Ordering::SeqCst); -} diff --git a/servo/components/gfx/font_template.rs b/servo/components/gfx/font_template.rs deleted file mode 100644 index 239bfcdd8c92..000000000000 --- a/servo/components/gfx/font_template.rs +++ /dev/null @@ -1,231 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -use font::FontHandleMethods; -use platform::font::FontHandle; -use platform::font_context::FontContextHandle; -use platform::font_template::FontTemplateData; -use servo_atoms::Atom; -use std::fmt::{Debug, Error, Formatter}; -use std::io::Error as IoError; -use std::sync::{Arc, Weak}; -use std::u32; -use style::computed_values::font_stretch::T as FontStretch; -use style::computed_values::font_style::T as FontStyle; -use style::properties::style_structs::Font as FontStyleStruct; -use style::values::computed::font::FontWeight; - -/// Describes how to select a font from a given family. This is very basic at the moment and needs -/// to be expanded or refactored when we support more of the font styling parameters. -/// -/// NB: If you change this, you will need to update `style::properties::compute_font_hash()`. -#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, Serialize)] -pub struct FontTemplateDescriptor { - pub weight: FontWeight, - pub stretch: FontStretch, - pub italic: bool, -} - -impl FontTemplateDescriptor { - #[inline] - pub fn new(weight: FontWeight, stretch: FontStretch, italic: bool) - -> FontTemplateDescriptor { - FontTemplateDescriptor { - weight: weight, - stretch: stretch, - italic: italic, - } - } - - /// Returns a score indicating how far apart visually the two font descriptors are. This is - /// used for fuzzy font selection. - /// - /// The smaller the score, the better the fonts match. 0 indicates an exact match. This must - /// be commutative (distance(A, B) == distance(B, A)). - /// - /// The policy is to care most about differences in italicness, then weight, then stretch - #[inline] - fn distance_from(&self, other: &FontTemplateDescriptor) -> u32 { - let italic_part = if self.italic == other.italic { 0 } else { 1000 }; - // 0 <= weightPart <= 800 - let weight_part = ((self.weight.0 as i16) - (other.weight.0 as i16)).abs() as u32; - // 0 <= stretchPart <= 8 - let stretch_part = (self.stretch_number() - other.stretch_number()).abs() as u32; - italic_part + weight_part + stretch_part - } - - /// Returns a number between 1 and 9 for the stretch property. - /// 1 is ultra_condensed, 5 is normal, and 9 is ultra_expanded - #[inline] - fn stretch_number(&self) -> i32 { - match self.stretch { - FontStretch::UltraCondensed => 1, - FontStretch::ExtraCondensed => 2, - FontStretch::Condensed => 3, - FontStretch::SemiCondensed => 4, - FontStretch::Normal => 5, - FontStretch::SemiExpanded => 6, - FontStretch::Expanded => 7, - FontStretch::ExtraExpanded => 8, - FontStretch::UltraExpanded => 9, - } - } -} - -impl<'a> From<&'a FontStyleStruct> for FontTemplateDescriptor { - fn from(style: &'a FontStyleStruct) -> Self { - FontTemplateDescriptor { - weight: style.font_weight, - stretch: style.font_stretch, - italic: style.font_style == FontStyle::Italic || style.font_style == FontStyle::Oblique, - } - } -} - -impl PartialEq for FontTemplateDescriptor { - fn eq(&self, other: &FontTemplateDescriptor) -> bool { - self.weight == other.weight && self.stretch == other.stretch && self.italic == other.italic - } -} - -/// This describes all the information needed to create -/// font instance handles. It contains a unique -/// FontTemplateData structure that is platform specific. -pub struct FontTemplate { - identifier: Atom, - descriptor: Option, - weak_ref: Option>, - // GWTODO: Add code path to unset the strong_ref for web fonts! - strong_ref: Option>, - is_valid: bool, -} - -impl Debug for FontTemplate { - fn fmt(&self, f: &mut Formatter) -> Result<(), Error> { - self.identifier.fmt(f) - } -} - -/// Holds all of the template information for a font that -/// is common, regardless of the number of instances of -/// this font handle per thread. -impl FontTemplate { - pub fn new(identifier: Atom, maybe_bytes: Option>) -> Result { - let maybe_data = match maybe_bytes { - Some(_) => Some(FontTemplateData::new(identifier.clone(), maybe_bytes)?), - None => None, - }; - - let maybe_strong_ref = match maybe_data { - Some(data) => Some(Arc::new(data)), - None => None, - }; - - let maybe_weak_ref = match maybe_strong_ref { - Some(ref strong_ref) => Some(Arc::downgrade(strong_ref)), - None => None, - }; - - Ok(FontTemplate { - identifier: identifier, - descriptor: None, - weak_ref: maybe_weak_ref, - strong_ref: maybe_strong_ref, - is_valid: true, - }) - } - - pub fn identifier(&self) -> &Atom { - &self.identifier - } - - /// Get the descriptor. Returns `None` when instantiating the data fails. - pub fn descriptor(&mut self, font_context: &FontContextHandle) -> Option { - // The font template data can be unloaded when nothing is referencing - // it (via the Weak reference to the Arc above). However, if we have - // already loaded a font, store the style information about it separately, - // so that we can do font matching against it again in the future - // without having to reload the font (unless it is an actual match). - - self.descriptor.or_else(|| { - if self.instantiate(font_context).is_err() { - return None - }; - - Some(self.descriptor.expect("Instantiation succeeded but no descriptor?")) - }) - } - - /// Get the data for creating a font if it matches a given descriptor. - pub fn data_for_descriptor(&mut self, - fctx: &FontContextHandle, - requested_desc: &FontTemplateDescriptor) - -> Option> { - self.descriptor(&fctx).and_then(|descriptor| { - if *requested_desc == descriptor { - self.data().ok() - } else { - None - } - }) - } - - /// Returns the font data along with the distance between this font's descriptor and the given - /// descriptor, if the font can be loaded. - pub fn data_for_approximate_descriptor(&mut self, - font_context: &FontContextHandle, - requested_descriptor: &FontTemplateDescriptor) - -> Option<(Arc, u32)> { - self.descriptor(&font_context).and_then(|descriptor| { - self.data().ok().map(|data| { - (data, descriptor.distance_from(requested_descriptor)) - }) - }) - } - - fn instantiate(&mut self, font_context: &FontContextHandle) -> Result<(), ()> { - if !self.is_valid { - return Err(()) - } - - let data = self.data().map_err(|_| ())?; - let handle: Result = FontHandleMethods::new_from_template(font_context, - data, - None); - self.is_valid = handle.is_ok(); - let handle = handle?; - self.descriptor = Some(FontTemplateDescriptor::new(handle.boldness(), - handle.stretchiness(), - handle.is_italic())); - Ok(()) - } - - /// Get the data for creating a font. - pub fn get(&mut self) -> Option> { - if self.is_valid { - self.data().ok() - } else { - None - } - } - - /// Get the font template data. If any strong references still - /// exist, it will return a clone, otherwise it will load the - /// font data and store a weak reference to it internally. - pub fn data(&mut self) -> Result, IoError> { - let maybe_data = match self.weak_ref { - Some(ref data) => data.upgrade(), - None => None, - }; - - if let Some(data) = maybe_data { - return Ok(data) - } - - assert!(self.strong_ref.is_none()); - let template_data = Arc::new(FontTemplateData::new(self.identifier.clone(), None)?); - self.weak_ref = Some(Arc::downgrade(&template_data)); - Ok(template_data) - } -} diff --git a/servo/components/gfx/lib.rs b/servo/components/gfx/lib.rs deleted file mode 100644 index 361844bce6b8..000000000000 --- a/servo/components/gfx/lib.rs +++ /dev/null @@ -1,83 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -// For SIMD -#![cfg_attr(feature = "unstable", feature(cfg_target_feature))] - -#![deny(unsafe_code)] - -extern crate app_units; -#[macro_use] -extern crate bitflags; - -// Mac OS-specific library dependencies -#[cfg(target_os = "macos")] extern crate byteorder; -#[cfg(target_os = "macos")] extern crate core_foundation; -#[cfg(target_os = "macos")] extern crate core_graphics; -#[cfg(target_os = "macos")] extern crate core_text; - -// Windows-specific library dependencies -#[cfg(target_os = "windows")] extern crate dwrote; -#[cfg(target_os = "windows")] extern crate truetype; - -extern crate euclid; -extern crate fnv; - -#[cfg(target_os = "linux")] -extern crate fontconfig; -extern crate fontsan; -#[cfg(any(target_os = "linux", target_os = "android"))] extern crate freetype; -#[cfg(any(target_os = "linux", target_os = "android"))] extern crate servo_allocator; -extern crate gfx_traits; - -// Eventually we would like the shaper to be pluggable, as many operating systems have their own -// shapers. For now, however, this is a hard dependency. -extern crate harfbuzz_sys as harfbuzz; - -extern crate ipc_channel; -#[macro_use] -extern crate lazy_static; -extern crate libc; -#[macro_use] -extern crate log; -#[cfg_attr(target_os = "windows", macro_use)] -extern crate malloc_size_of; -#[macro_use] extern crate malloc_size_of_derive; -extern crate msg; -extern crate net_traits; -extern crate ordered_float; -extern crate range; -#[macro_use] extern crate serde; -extern crate servo_arc; -extern crate servo_geometry; -extern crate servo_url; -#[macro_use] extern crate servo_atoms; -#[cfg(feature = "unstable")] -#[cfg(any(target_feature = "sse2", target_feature = "neon"))] -extern crate simd; -extern crate smallvec; -extern crate style; -extern crate time; -extern crate unicode_bidi; -extern crate unicode_script; -extern crate webrender_api; -extern crate xi_unicode; -#[cfg(target_os = "android")] -extern crate xml5ever; - -#[deny(unsafe_code)] -pub mod display_list; - -// Fonts -#[macro_use] pub mod font; -pub mod font_cache_thread; -pub mod font_context; -pub mod font_template; - -// Platform-specific implementations. -#[allow(unsafe_code)] -mod platform; - -// Text -pub mod text; diff --git a/servo/components/gfx/platform/freetype/android/font_list.rs b/servo/components/gfx/platform/freetype/android/font_list.rs deleted file mode 100644 index 6d5a1ea30611..000000000000 --- a/servo/components/gfx/platform/freetype/android/font_list.rs +++ /dev/null @@ -1,481 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -use std::cell::RefCell; -use std::fs::File; -use std::io::{self, Read}; -use std::path::Path; -use xml5ever::Attribute; -use xml5ever::driver::parse_document; -use xml5ever::rcdom::*; -use xml5ever::rcdom::{Node, RcDom}; -use xml5ever::tendril::TendrilSink; - -lazy_static! { - static ref FONT_LIST: FontList = FontList::new(); -} - -// Android doesn't provide an API to query system fonts until Android O: -// https://developer.android.com/reference/android/text/FontConfig.html -// System font configuration files must be parsed until Android O version is set as the minimum target. -// Android uses XML files to handle font mapping configurations. -// On Android API 21+ font mappings are loaded from /etc/fonts.xml. -// Each entry consists of a family with various font names, or a font alias. -// Example: -// -// -// -// Roboto-Thin.ttf -// Roboto-ThinItalic.ttf -// Roboto-Light.ttf -// Roboto-LightItalic.ttf -// Roboto-Regular.ttf -// Roboto-Italic.ttf -// Roboto-Medium.ttf -// Roboto-MediumItalic.ttf -// Roboto-Black.ttf -// Roboto-BlackItalic.ttf -// Roboto-Bold.ttf -// Roboto-BoldItalic.ttf -// // - -// -// -// -// -// -// -// -// -// - -// -// RobotoCondensed-Light.ttf -// RobotoCondensed-LightItalic.ttf -// RobotoCondensed-Regular.ttf -// RobotoCondensed-Italic.ttf -// RobotoCondensed-Bold.ttf -// RobotoCondensed-BoldItalic.ttf -// -// -// -// On Android API 17-20 font mappings are loaded from /system/etc/system_fonts.xml -// Each entry consists of a family with a nameset and a fileset. -// Example: -// -// -// -// sans-serif -// arial -// helvetica -// tahoma -// verdana -// -// -// Roboto-Regular.ttf -// Roboto-Bold.ttf -// Roboto-Italic.ttf -// Roboto-BoldItalic.ttf -// -// // - -// -// -// sans-serif-light -// -// -// Roboto-Light.ttf -// Roboto-LightItalic.ttf -// -// // - -// -// -// sans-serif-thin -// -// -// Roboto-Thin.ttf -// Roboto-ThinItalic.ttf -// -// -// - -struct Font { - filename: String, - weight: Option, -} - -struct FontFamily { - name: String, - fonts: Vec, -} - -struct FontAlias { - from: String, - to: String, - weight: Option -} - -struct FontList { - families: Vec, - aliases: Vec -} - -impl FontList { - fn new() -> FontList { - // Possible paths containing the font mapping xml file. - let paths = [ - "/etc/fonts.xml", - "/system/etc/system_fonts.xml" - ]; - - // Try to load and parse paths until one of them success. - let mut result = None; - paths.iter().all(|path| { - result = Self::from_path(path); - !result.is_some() - }); - - match result { - Some(result) => result, - // If no xml mapping file is found fallback to some default - // fonts expected to be on all Android devices. - None => FontList { - families: Self::fallback_font_families(), - aliases: Vec::new(), - } - } - } - - // Creates a new FontList from a path to the font mapping xml file. - fn from_path(path: &str) -> Option { - let xml = match Self::load_file(path) { - Ok(xml) => xml, - _=> { return None; }, - }; - - let dom: RcDom = parse_document(RcDom::default(), Default::default()) - .one(xml); - let doc = &dom.document; - - // find familyset root node - let children = doc.children.borrow(); - let familyset = children.iter().find(|child| { - match child.data { - NodeData::Element { ref name, .. } => &*name.local == "familyset", - _ => false, - } - }); - - let familyset = match familyset { - Some(node) => node, - _ => { return None; } - }; - - // Parse familyset node - let mut families = Vec::new(); - let mut aliases = Vec::new(); - - for node in familyset.children.borrow().iter() { - match node.data { - NodeData::Element { ref name, ref attrs, .. } => { - if &*name.local == "family" { - Self::parse_family(&node, attrs, &mut families); - } else if &*name.local == "alias" { - // aliases come after the fonts they reference. --> - if !families.is_empty() { - Self::parse_alias(attrs, &mut aliases); - } - } - }, - _=> {} - } - } - - Some(FontList { - families: families, - aliases: aliases - }) - } - - // Fonts expected to exist in Android devices. - // Only used in the unlikely case where no font xml mapping files are found. - fn fallback_font_families() -> Vec { - let alternatives = [ - ("sans-serif", "Roboto-Regular.ttf"), - ("Droid Sans", "DroidSans.ttf"), - ]; - - alternatives.iter().filter(|item| { - Path::new(&Self::font_absolute_path(item.1)).exists() - }).map(|item| { - FontFamily { - name: item.0.into(), - fonts: vec![Font { - filename: item.1.into(), - weight: None, - }] - } - }). collect() - } - - // All Android fonts are located in /system/fonts - fn font_absolute_path(filename: &str) -> String { - format!("/system/fonts/{}", filename) - } - - fn find_family(&self, name: &str) -> Option<&FontFamily>{ - self.families.iter().find(|f| f.name == name) - } - - fn find_alias(&self, name: &str) -> Option<&FontAlias>{ - self.aliases.iter().find(|f| f.from == name) - } - - - fn load_file(path: &str) -> Result { - let mut file = File::open(path)?; - let mut content = String::new(); - file.read_to_string(&mut content)?; - - Ok(content) - } - - // Parse family and font file names - // Example: - // - // Roboto-Thin.ttf - // Roboto-ThinItalic.ttf - // Roboto-Light.ttf - // Roboto-LightItalic.ttf - // Roboto-Regular.ttf - // - fn parse_family(familyset: &Node, attrs: &RefCell>, out:&mut Vec) { - // Fallback to old Android API v17 xml format if required - let using_api_17 = familyset.children.borrow().iter().any(|node| { - match node.data { - NodeData::Element { ref name, .. } => &*name.local == "nameset", - _=> false, - } - }); - if using_api_17 { - Self::parse_family_v17(familyset, out); - return; - } - - // Parse family name - let name = match Self::find_attrib("name", attrs) { - Some(name) => name, - _ => { return; }, - }; - - let mut fonts = Vec::new(); - // Parse font variants - for node in familyset.children.borrow().iter() { - match node.data { - NodeData::Element { ref name, ref attrs, .. } => { - if &*name.local == "font" { - FontList::parse_font(&node, attrs, &mut fonts); - } - }, - _=> {} - } - } - - out.push(FontFamily { - name: name, - fonts: fonts - }); - } - - // Parse family and font file names for Androi API < 21 - // Example: - // - // - // sans-serif - // arial - // helvetica - // tahoma - // verdana - // - // - // Roboto-Regular.ttf - // Roboto-Bold.ttf - // Roboto-Italic.ttf - // Roboto-BoldItalic.ttf - // - // - fn parse_family_v17(familyset: &Node, out:&mut Vec) { - let mut nameset = Vec::new(); - let mut fileset = Vec::new(); - for node in familyset.children.borrow().iter() { - match node.data { - NodeData::Element { ref name, .. } => { - if &*name.local == "nameset" { - Self::collect_contents_with_tag(node, "name", &mut nameset); - } else if &*name.local == "fileset" { - Self::collect_contents_with_tag(node, "file", &mut fileset); - } - }, - _=> {} - } - } - - // Create a families for each variation - for name in nameset { - let fonts: Vec = fileset.iter().map(|f| Font { - filename: f.clone(), - weight: None, - }).collect(); - - if !fonts.is_empty() { - out.push(FontFamily { - name: name, - fonts: fonts - }) - } - } - } - - // Example: - // Roboto-Thin.ttf - fn parse_font(node: &Node, attrs: &RefCell>, out:&mut Vec) { - // Parse font filename - let filename = match Self::text_content(node) { - Some(filename) => filename, - _ => { return; } - }; - - // Parse font weight - let weight = Self::find_attrib("weight", attrs).and_then(|w| w.parse().ok()); - - out.push(Font { - filename: filename, - weight: weight, - }) - } - - // Example: - // - // - // - // - // - // - // - // - fn parse_alias(attrs: &RefCell>, out:&mut Vec) { - // Parse alias name and referenced font - let from = match Self::find_attrib("name", attrs) { - Some(from) => from, - _ => { return; }, - }; - - // Parse referenced font - let to = match Self::find_attrib("to", attrs) { - Some(to) => to, - _ => { return; }, - }; - - // Parse optional weight filter - let weight = Self::find_attrib("weight", attrs).and_then(|w| w.parse().ok()); - - out.push(FontAlias { - from: from, - to: to, - weight: weight, - }) - } - - fn find_attrib(name: &str, attrs: &RefCell>) -> Option { - attrs.borrow().iter().find(|attr| &*attr.name.local == name).map(|s| String::from(&s.value)) - } - - fn text_content(node: &Node) -> Option { - node.children.borrow().get(0).and_then(|child| { - match child.data { - NodeData::Text { ref contents } => { - let mut result = String::new(); - result.push_str(&contents.borrow()); - Some(result) - }, - _ => None - } - }) - } - - fn collect_contents_with_tag(node: &Node, tag: &str, out:&mut Vec) { - for child in node.children.borrow().iter() { - match child.data { - NodeData::Element { ref name, .. } => { - if &*name.local == tag { - if let Some(content) = Self::text_content(child) { - out.push(content); - } - } - }, - _=> {} - } - } - } -} - -// Functions used by FontCacheThread -pub fn for_each_available_family(mut callback: F) where F: FnMut(String) { - for family in &FONT_LIST.families { - callback(family.name.clone()); - } - for alias in &FONT_LIST.aliases { - callback(alias.from.clone()); - } -} - -pub fn for_each_variation(family_name: &str, mut callback: F) - where F: FnMut(String) -{ - println!("Variatioooon {:?}", family_name); - if let Some(family) = FONT_LIST.find_family(family_name) { - for font in &family.fonts { - callback(FontList::font_absolute_path(&font.filename)); - } - return; - } - - if let Some(alias) = FONT_LIST.find_alias(family_name) { - if let Some(family) = FONT_LIST.find_family(&alias.to) { - for font in &family.fonts { - match (alias.weight, font.weight) { - (None, _) => callback(FontList::font_absolute_path(&font.filename)), - (Some(w1), Some(w2)) => { - if w1 == w2 { - callback(FontList::font_absolute_path(&font.filename)) - } - }, - _ => {} - } - } - } - } -} - -pub fn system_default_family(generic_name: &str) -> Option { - if let Some(family) = FONT_LIST.find_family(&generic_name) { - Some(family.name.clone()) - } else if let Some(alias) = FONT_LIST.find_alias(&generic_name) { - Some(alias.from.clone()) - } else { - // First font defined in the fonts.xml is the default on Android. - FONT_LIST.families.get(0).map(|family| family.name.clone()) - } -} - -pub fn last_resort_font_families() -> Vec { - vec!( - "sans-serif".to_owned(), - "Droid Sans".to_owned(), - "serif".to_owned(), - ) -} - -pub static SANS_SERIF_FONT_FAMILY: &'static str = "sans-serif"; diff --git a/servo/components/gfx/platform/freetype/font.rs b/servo/components/gfx/platform/freetype/font.rs deleted file mode 100644 index 57b8861ed96b..000000000000 --- a/servo/components/gfx/platform/freetype/font.rs +++ /dev/null @@ -1,373 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -use app_units::Au; -use font::{FontHandleMethods, FontMetrics, FontTableMethods}; -use font::{FontTableTag, FractionalPixel, GPOS, GSUB, KERN}; -use freetype::freetype::{FT_Done_Face, FT_New_Memory_Face}; -use freetype::freetype::{FT_F26Dot6, FT_Face, FT_FaceRec}; -use freetype::freetype::{FT_Get_Char_Index, FT_Get_Postscript_Name}; -use freetype::freetype::{FT_Get_Kerning, FT_Get_Sfnt_Table, FT_Load_Sfnt_Table}; -use freetype::freetype::{FT_GlyphSlot, FT_Library, FT_Long, FT_ULong}; -use freetype::freetype::{FT_Int32, FT_Kerning_Mode, FT_STYLE_FLAG_ITALIC}; -use freetype::freetype::{FT_Load_Glyph, FT_Set_Char_Size}; -use freetype::freetype::{FT_SizeRec, FT_Size_Metrics, FT_UInt, FT_Vector}; -use freetype::freetype::FT_Sfnt_Tag; -use freetype::tt_os2::TT_OS2; -use platform::font_context::FontContextHandle; -use platform::font_template::FontTemplateData; -use servo_atoms::Atom; -use std::{mem, ptr}; -use std::os::raw::{c_char, c_long}; -use std::sync::Arc; -use style::computed_values::font_stretch::T as FontStretch; -use style::computed_values::font_weight::T as FontWeight; -use super::c_str_to_string; -use text::glyph::GlyphId; -use text::util::fixed_to_float; - -// This constant is not present in the freetype -// bindings due to bindgen not handling the way -// the macro is defined. -const FT_LOAD_TARGET_LIGHT: FT_Int32 = 1 << 16; - -// Default to slight hinting, which is what most -// Linux distros use by default, and is a better -// default than no hinting. -// TODO(gw): Make this configurable. -const GLYPH_LOAD_FLAGS: FT_Int32 = FT_LOAD_TARGET_LIGHT; - -fn fixed_to_float_ft(f: i32) -> f64 { - fixed_to_float(6, f) -} - -#[derive(Debug)] -pub struct FontTable { - buffer: Vec, -} - -impl FontTableMethods for FontTable { - fn buffer(&self) -> &[u8] { - &self.buffer - } -} - -/// Data from the OS/2 table of an OpenType font. -/// See https://www.microsoft.com/typography/otspec/os2.htm -#[derive(Debug)] -struct OS2Table { - us_weight_class: u16, - us_width_class: u16, - y_strikeout_size: i16, - y_strikeout_position: i16, - sx_height: i16, -} - -#[derive(Debug)] -pub struct FontHandle { - // The font binary. This must stay valid for the lifetime of the font, - // if the font is created using FT_Memory_Face. - font_data: Arc, - face: FT_Face, - handle: FontContextHandle, - can_do_fast_shaping: bool, -} - -impl Drop for FontHandle { - fn drop(&mut self) { - assert!(!self.face.is_null()); - unsafe { - if !FT_Done_Face(self.face).succeeded() { - panic!("FT_Done_Face failed"); - } - } - } -} - -impl FontHandleMethods for FontHandle { - fn new_from_template(fctx: &FontContextHandle, - template: Arc, - pt_size: Option) - -> Result { - let ft_ctx: FT_Library = fctx.ctx.ctx; - if ft_ctx.is_null() { return Err(()); } - - return create_face_from_buffer(ft_ctx, &template.bytes, pt_size).map(|face| { - let mut handle = FontHandle { - face: face, - font_data: template.clone(), - handle: fctx.clone(), - can_do_fast_shaping: false, - }; - // TODO (#11310): Implement basic support for GPOS and GSUB. - handle.can_do_fast_shaping = handle.has_table(KERN) && - !handle.has_table(GPOS) && - !handle.has_table(GSUB); - handle - }); - - fn create_face_from_buffer(lib: FT_Library, buffer: &[u8], pt_size: Option) - -> Result { - unsafe { - let mut face: FT_Face = ptr::null_mut(); - let face_index = 0 as FT_Long; - let result = FT_New_Memory_Face(lib, buffer.as_ptr(), buffer.len() as FT_Long, - face_index, &mut face); - - if !result.succeeded() || face.is_null() { - return Err(()); - } - if let Some(s) = pt_size { - FontHandle::set_char_size(face, s).or(Err(()))? - } - Ok(face) - } - } - } - - fn template(&self) -> Arc { - self.font_data.clone() - } - - fn family_name(&self) -> String { - unsafe { - c_str_to_string((*self.face).family_name as *const c_char) - } - } - - fn face_name(&self) -> Option { - unsafe { - let name = FT_Get_Postscript_Name(self.face) as *const c_char; - - if !name.is_null() { - Some(c_str_to_string(name)) - } else { - None - } - } - } - - fn is_italic(&self) -> bool { - unsafe { (*self.face).style_flags & FT_STYLE_FLAG_ITALIC as c_long != 0 } - } - - fn boldness(&self) -> FontWeight { - if let Some(os2) = self.os2_table() { - let weight = os2.us_weight_class as i32; - - if weight < 10 { - FontWeight::from_int(weight * 100).unwrap() - } else if weight >= 100 && weight < 1000 { - FontWeight::from_int(weight / 100 * 100).unwrap() - } else { - FontWeight::normal() - } - } else { - FontWeight::normal() - } - } - - fn stretchiness(&self) -> FontStretch { - if let Some(os2) = self.os2_table() { - match os2.us_width_class { - 1 => FontStretch::UltraCondensed, - 2 => FontStretch::ExtraCondensed, - 3 => FontStretch::Condensed, - 4 => FontStretch::SemiCondensed, - 5 => FontStretch::Normal, - 6 => FontStretch::SemiExpanded, - 7 => FontStretch::Expanded, - 8 => FontStretch::ExtraExpanded, - 9 => FontStretch::UltraExpanded, - _ => FontStretch::Normal - } - } else { - FontStretch::Normal - } - } - - fn glyph_index(&self, codepoint: char) -> Option { - assert!(!self.face.is_null()); - unsafe { - let idx = FT_Get_Char_Index(self.face, codepoint as FT_ULong); - if idx != 0 as FT_UInt { - Some(idx as GlyphId) - } else { - debug!("Invalid codepoint: {}", codepoint); - None - } - } - } - - fn glyph_h_kerning(&self, first_glyph: GlyphId, second_glyph: GlyphId) - -> FractionalPixel { - assert!(!self.face.is_null()); - let mut delta = FT_Vector { x: 0, y: 0 }; - unsafe { - FT_Get_Kerning(self.face, first_glyph, second_glyph, - FT_Kerning_Mode::FT_KERNING_DEFAULT as FT_UInt, - &mut delta); - } - fixed_to_float_ft(delta.x as i32) - } - - fn can_do_fast_shaping(&self) -> bool { - self.can_do_fast_shaping - } - - fn glyph_h_advance(&self, glyph: GlyphId) -> Option { - assert!(!self.face.is_null()); - unsafe { - let res = FT_Load_Glyph(self.face, - glyph as FT_UInt, - GLYPH_LOAD_FLAGS); - if res.succeeded() { - let void_glyph = (*self.face).glyph; - let slot: FT_GlyphSlot = mem::transmute(void_glyph); - assert!(!slot.is_null()); - let advance = (*slot).metrics.horiAdvance; - debug!("h_advance for {} is {}", glyph, advance); - let advance = advance as i32; - Some(fixed_to_float_ft(advance) as FractionalPixel) - } else { - debug!("Unable to load glyph {}. reason: {:?}", glyph, res); - None - } - } - } - - fn metrics(&self) -> FontMetrics { - /* TODO(Issue #76): complete me */ - let face = self.face_rec_mut(); - - let underline_size = self.font_units_to_au(face.underline_thickness as f64); - let underline_offset = self.font_units_to_au(face.underline_position as f64); - let em_size = self.font_units_to_au(face.units_per_EM as f64); - let ascent = self.font_units_to_au(face.ascender as f64); - let descent = self.font_units_to_au(face.descender as f64); - let max_advance = self.font_units_to_au(face.max_advance_width as f64); - - // 'leading' is supposed to be the vertical distance between two baselines, - // reflected by the height attribute in freetype. On OS X (w/ CTFont), - // leading represents the distance between the bottom of a line descent to - // the top of the next line's ascent or: (line_height - ascent - descent), - // see http://stackoverflow.com/a/5635981 for CTFont implementation. - // Convert using a formula similar to what CTFont returns for consistency. - let height = self.font_units_to_au(face.height as f64); - let leading = height - (ascent + descent); - - let mut strikeout_size = Au(0); - let mut strikeout_offset = Au(0); - let mut x_height = Au(0); - - if let Some(os2) = self.os2_table() { - strikeout_size = self.font_units_to_au(os2.y_strikeout_size as f64); - strikeout_offset = self.font_units_to_au(os2.y_strikeout_position as f64); - x_height = self.font_units_to_au(os2.sx_height as f64); - } - - let average_advance = self.glyph_index('0') - .and_then(|idx| self.glyph_h_advance(idx)) - .map_or(max_advance, |advance| self.font_units_to_au(advance)); - - let metrics = FontMetrics { - underline_size: underline_size, - underline_offset: underline_offset, - strikeout_size: strikeout_size, - strikeout_offset: strikeout_offset, - leading: leading, - x_height: x_height, - em_size: em_size, - ascent: ascent, - descent: -descent, // linux font's seem to use the opposite sign from mac - max_advance: max_advance, - average_advance: average_advance, - line_gap: height, - }; - - debug!("Font metrics (@{}px): {:?}", em_size.to_f32_px(), metrics); - metrics - } - - fn table_for_tag(&self, tag: FontTableTag) -> Option { - let tag = tag as FT_ULong; - - unsafe { - // Get the length - let mut len = 0; - if !FT_Load_Sfnt_Table(self.face, tag, 0, ptr::null_mut(), &mut len).succeeded() { - return None - } - // Get the bytes - let mut buf = vec![0u8; len as usize]; - if !FT_Load_Sfnt_Table(self.face, tag, 0, buf.as_mut_ptr(), &mut len).succeeded() { - return None - } - Some(FontTable { buffer: buf }) - } - } - - fn identifier(&self) -> Atom { - self.font_data.identifier.clone() - } -} - -impl<'a> FontHandle { - fn set_char_size(face: FT_Face, pt_size: Au) -> Result<(), ()>{ - let char_size = pt_size.to_f64_px() * 64.0 + 0.5; - - unsafe { - let result = FT_Set_Char_Size(face, char_size as FT_F26Dot6, 0, 0, 0); - if result.succeeded() { Ok(()) } else { Err(()) } - } - } - - fn has_table(&self, tag: FontTableTag) -> bool { - unsafe { - FT_Load_Sfnt_Table(self.face, tag as FT_ULong, 0, ptr::null_mut(), &mut 0).succeeded() - } - } - - fn face_rec_mut(&'a self) -> &'a mut FT_FaceRec { - unsafe { - &mut (*self.face) - } - } - - fn font_units_to_au(&self, value: f64) -> Au { - let face = self.face_rec_mut(); - - // face.size is a *c_void in the bindings, presumably to avoid - // recursive structural types - let size: &FT_SizeRec = unsafe { mem::transmute(&(*face.size)) }; - let metrics: &FT_Size_Metrics = &(*size).metrics; - - let em_size = face.units_per_EM as f64; - let x_scale = (metrics.x_ppem as f64) / em_size as f64; - - // If this isn't true then we're scaling one of the axes wrong - assert_eq!(metrics.x_ppem, metrics.y_ppem); - - Au::from_f64_px(value * x_scale) - } - - fn os2_table(&self) -> Option { - unsafe { - let os2 = FT_Get_Sfnt_Table(self.face_rec_mut(), FT_Sfnt_Tag::FT_SFNT_OS2) as *mut TT_OS2; - let valid = !os2.is_null() && (*os2).version != 0xffff; - - if !valid { - return None - } - - Some(OS2Table { - us_weight_class: (*os2).usWeightClass, - us_width_class: (*os2).usWidthClass, - y_strikeout_size: (*os2).yStrikeoutSize, - y_strikeout_position: (*os2).yStrikeoutPosition, - sx_height: (*os2).sxHeight, - }) - } - } -} diff --git a/servo/components/gfx/platform/freetype/font_context.rs b/servo/components/gfx/platform/freetype/font_context.rs deleted file mode 100644 index 2238561ba9c2..000000000000 --- a/servo/components/gfx/platform/freetype/font_context.rs +++ /dev/null @@ -1,132 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -use freetype::freetype::FT_Add_Default_Modules; -use freetype::freetype::FT_Done_Library; -use freetype::freetype::FT_Library; -use freetype::freetype::FT_Memory; -use freetype::freetype::FT_MemoryRec_; -use freetype::freetype::FT_New_Library; -use malloc_size_of::{MallocSizeOf, MallocSizeOfOps}; -use servo_allocator::libc_compat::{malloc, realloc, free}; -use servo_allocator::usable_size; -use std::os::raw::{c_long, c_void}; -use std::ptr; -use std::rc::Rc; - -// We pass a |User| struct -- via an opaque |void*| -- to FreeType each time a new instance is -// created. FreeType passes it back to the ft_alloc/ft_realloc/ft_free callbacks. We use it to -// record the memory usage of each FreeType instance. -pub struct User { - size: usize, -} - -extern fn ft_alloc(mem: FT_Memory, req_size: c_long) -> *mut c_void { - unsafe { - let ptr = malloc(req_size as usize); - let ptr = ptr as *mut c_void; // libc::c_void vs std::os::raw::c_void - let actual_size = usable_size(ptr); - let user = (*mem).user as *mut User; - (*user).size += actual_size; - ptr - } -} - -extern fn ft_free(mem: FT_Memory, ptr: *mut c_void) { - unsafe { - let actual_size = usable_size(ptr); - let user = (*mem).user as *mut User; - (*user).size -= actual_size; - free(ptr as *mut _); - } -} - -extern fn ft_realloc(mem: FT_Memory, _old_size: c_long, new_req_size: c_long, - old_ptr: *mut c_void) -> *mut c_void { - unsafe { - let old_actual_size = usable_size(old_ptr); - let new_ptr = realloc(old_ptr as *mut _, new_req_size as usize); - let new_ptr = new_ptr as *mut c_void; - let new_actual_size = usable_size(new_ptr); - let user = (*mem).user as *mut User; - (*user).size += new_actual_size; - (*user).size -= old_actual_size; - new_ptr - } -} - -// A |*mut User| field in a struct triggers a "use of `#[derive]` with a raw pointer" warning from -// rustc. But using a typedef avoids this, so... -pub type UserPtr = *mut User; - -// WARNING: We need to be careful how we use this struct. See the comment about Rc<> in -// FontContextHandle. -#[derive(Clone, Debug)] -pub struct FreeTypeLibraryHandle { - pub ctx: FT_Library, - mem: FT_Memory, - user: UserPtr, -} - -impl Drop for FreeTypeLibraryHandle { - fn drop(&mut self) { - assert!(!self.ctx.is_null()); - unsafe { - FT_Done_Library(self.ctx); - Box::from_raw(self.mem); - Box::from_raw(self.user); - } - } -} - -impl MallocSizeOf for FreeTypeLibraryHandle { - fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize { - unsafe { - (*self.user).size + - ops.malloc_size_of(self.ctx as *const _) + - ops.malloc_size_of(self.mem as *const _) + - ops.malloc_size_of(self.user as *const _) - } - } -} - -#[derive(Clone, Debug)] -pub struct FontContextHandle { - // WARNING: FreeTypeLibraryHandle contains raw pointers, is clonable, and also implements - // `Drop`. This field needs to be Rc<> to make sure that the `drop` function is only called - // once, otherwise we'll get crashes. Yuk. - pub ctx: Rc, -} - -impl MallocSizeOf for FontContextHandle { - fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize { - self.ctx.size_of(ops) - } -} - -impl FontContextHandle { - pub fn new() -> FontContextHandle { - let user = Box::into_raw(Box::new(User { - size: 0, - })); - let mem = Box::into_raw(Box::new(FT_MemoryRec_ { - user: user as *mut c_void, - alloc: Some(ft_alloc), - free: Some(ft_free), - realloc: Some(ft_realloc), - })); - unsafe { - let mut ctx: FT_Library = ptr::null_mut(); - - let result = FT_New_Library(mem, &mut ctx); - if !result.succeeded() { panic!("Unable to initialize FreeType library"); } - - FT_Add_Default_Modules(ctx); - - FontContextHandle { - ctx: Rc::new(FreeTypeLibraryHandle { ctx: ctx, mem: mem, user: user }), - } - } - } -} diff --git a/servo/components/gfx/platform/freetype/font_list.rs b/servo/components/gfx/platform/freetype/font_list.rs deleted file mode 100644 index 9b85db624d81..000000000000 --- a/servo/components/gfx/platform/freetype/font_list.rs +++ /dev/null @@ -1,143 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -use fontconfig::fontconfig::{FcChar8, FcResultMatch, FcSetSystem}; -use fontconfig::fontconfig::{FcConfigGetCurrent, FcConfigGetFonts, FcConfigSubstitute}; -use fontconfig::fontconfig::{FcDefaultSubstitute, FcFontMatch, FcNameParse, FcPatternGetString}; -use fontconfig::fontconfig::{FcFontSetDestroy, FcMatchPattern, FcPatternCreate, FcPatternDestroy}; -use fontconfig::fontconfig::{FcFontSetList, FcObjectSetCreate, FcObjectSetDestroy, FcPatternAddString}; -use fontconfig::fontconfig::{FcObjectSetAdd, FcPatternGetInteger}; -use libc; -use libc::{c_char, c_int}; -use std::borrow::ToOwned; -use std::ffi::CString; -use std::ptr; -use super::c_str_to_string; - -static FC_FAMILY: &'static [u8] = b"family\0"; -static FC_FILE: &'static [u8] = b"file\0"; -static FC_INDEX: &'static [u8] = b"index\0"; -static FC_FONTFORMAT: &'static [u8] = b"fontformat\0"; - -pub fn for_each_available_family(mut callback: F) where F: FnMut(String) { - unsafe { - let config = FcConfigGetCurrent(); - let font_set = FcConfigGetFonts(config, FcSetSystem); - for i in 0..((*font_set).nfont as isize) { - let font = (*font_set).fonts.offset(i); - let mut family: *mut FcChar8 = ptr::null_mut(); - let mut format: *mut FcChar8 = ptr::null_mut(); - let mut v: c_int = 0; - if FcPatternGetString(*font, FC_FONTFORMAT.as_ptr() as *mut c_char, v, &mut format) != FcResultMatch { - continue; - } - - // Skip bitmap fonts. They aren't supported by FreeType. - let fontformat = c_str_to_string(format as *const c_char); - if fontformat != "TrueType" && - fontformat != "CFF" && - fontformat != "Type 1" { - continue; - } - - while FcPatternGetString(*font, FC_FAMILY.as_ptr() as *mut c_char, v, &mut family) == FcResultMatch { - let family_name = c_str_to_string(family as *const c_char); - callback(family_name); - v += 1; - } - } - } -} - -pub fn for_each_variation(family_name: &str, mut callback: F) - where F: FnMut(String) -{ - debug!("getting variations for {}", family_name); - unsafe { - let config = FcConfigGetCurrent(); - let mut font_set = FcConfigGetFonts(config, FcSetSystem); - let font_set_array_ptr = &mut font_set; - let pattern = FcPatternCreate(); - assert!(!pattern.is_null()); - let family_name_c = CString::new(family_name).unwrap(); - let family_name = family_name_c.as_ptr(); - let ok = FcPatternAddString(pattern, FC_FAMILY.as_ptr() as *mut c_char, family_name as *mut FcChar8); - assert_ne!(ok, 0); - - let object_set = FcObjectSetCreate(); - assert!(!object_set.is_null()); - - FcObjectSetAdd(object_set, FC_FILE.as_ptr() as *mut c_char); - FcObjectSetAdd(object_set, FC_INDEX.as_ptr() as *mut c_char); - - let matches = FcFontSetList(config, font_set_array_ptr, 1, pattern, object_set); - - debug!("found {} variations", (*matches).nfont); - - for i in 0..((*matches).nfont as isize) { - let font = (*matches).fonts.offset(i); - let mut file: *mut FcChar8 = ptr::null_mut(); - let result = FcPatternGetString(*font, FC_FILE.as_ptr() as *mut c_char, 0, &mut file); - let file = if result == FcResultMatch { - c_str_to_string(file as *const c_char) - } else { - panic!(); - }; - let mut index: libc::c_int = 0; - let result = FcPatternGetInteger(*font, FC_INDEX.as_ptr() as *mut c_char, 0, &mut index); - let index = if result == FcResultMatch { - index - } else { - panic!(); - }; - - debug!("variation file: {}", file); - debug!("variation index: {}", index); - - callback(file); - } - - FcFontSetDestroy(matches); - FcPatternDestroy(pattern); - FcObjectSetDestroy(object_set); - } -} - -pub fn system_default_family(generic_name: &str) -> Option { - let generic_name_c = CString::new(generic_name).unwrap(); - let generic_name_ptr = generic_name_c.as_ptr(); - - unsafe { - let pattern = FcNameParse(generic_name_ptr as *mut FcChar8); - - FcConfigSubstitute(ptr::null_mut(), pattern, FcMatchPattern); - FcDefaultSubstitute(pattern); - - let mut result = 0; - let family_match = FcFontMatch(ptr::null_mut(), pattern, &mut result); - - let family_name = if result == FcResultMatch { - let mut match_string: *mut FcChar8 = ptr::null_mut(); - FcPatternGetString(family_match, FC_FAMILY.as_ptr() as *mut c_char, 0, &mut match_string); - let result = c_str_to_string(match_string as *const c_char); - FcPatternDestroy(family_match); - Some(result) - } else { - None - }; - - FcPatternDestroy(pattern); - family_name - } -} - -pub fn last_resort_font_families() -> Vec { - vec!( - "Fira Sans".to_owned(), - "DejaVu Sans".to_owned(), - "Arial".to_owned() - ) -} - -pub static SANS_SERIF_FONT_FAMILY: &'static str = "DejaVu Sans"; diff --git a/servo/components/gfx/platform/freetype/font_template.rs b/servo/components/gfx/platform/freetype/font_template.rs deleted file mode 100644 index 13209e3a0167..000000000000 --- a/servo/components/gfx/platform/freetype/font_template.rs +++ /dev/null @@ -1,70 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -use servo_atoms::Atom; -use std::fmt; -use std::fs::File; -use std::io::{Read, Error}; -use webrender_api::NativeFontHandle; - -/// Platform specific font representation for Linux. -/// The identifier is an absolute path, and the bytes -/// field is the loaded data that can be passed to -/// freetype and azure directly. -#[derive(Deserialize, Serialize)] -pub struct FontTemplateData { - // If you add members here, review the Debug impl below - - pub bytes: Vec, - pub identifier: Atom, -} - -impl fmt::Debug for FontTemplateData { - fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { - fmt.debug_struct("FontTemplateData") - .field("bytes", &format!("[{} bytes]", self.bytes.len())) - .field("identifier", &self.identifier) - .finish() - } -} - -impl FontTemplateData { - pub fn new(identifier: Atom, font_data: Option>) -> Result { - let bytes = match font_data { - Some(bytes) => { - bytes - }, - None => { - // TODO: Handle file load failure! - let mut file = File::open(&*identifier)?; - let mut buffer = vec![]; - file.read_to_end(&mut buffer).unwrap(); - buffer - }, - }; - - Ok(FontTemplateData { - bytes: bytes, - identifier: identifier, - }) - } - - /// Returns a clone of the data in this font. This may be a hugely expensive - /// operation (depending on the platform) which performs synchronous disk I/O - /// and should never be done lightly. - pub fn bytes(&self) -> Vec { - self.bytes.clone() - } - - /// Returns a clone of the bytes in this font if they are in memory. This function never - /// performs disk I/O. - pub fn bytes_if_in_memory(&self) -> Option> { - Some(self.bytes()) - } - - /// Returns the native font that underlies this font template, if applicable. - pub fn native_font(&self) -> Option { - None - } -} diff --git a/servo/components/gfx/platform/macos/font.rs b/servo/components/gfx/platform/macos/font.rs deleted file mode 100644 index ca719ddf5b77..000000000000 --- a/servo/components/gfx/platform/macos/font.rs +++ /dev/null @@ -1,326 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -/// Implementation of Quartz (CoreGraphics) fonts. - -use app_units::Au; -use byteorder::{BigEndian, ByteOrder}; -use core_foundation::base::CFIndex; -use core_foundation::data::CFData; -use core_foundation::string::UniChar; -use core_graphics::font::CGGlyph; -use core_graphics::geometry::CGRect; -use core_text::font::CTFont; -use core_text::font_descriptor::{SymbolicTraitAccessors, TraitAccessors}; -use core_text::font_descriptor::kCTFontDefaultOrientation; -use font::{FontHandleMethods, FontMetrics, FontTableMethods, FontTableTag, FractionalPixel}; -use font::{GPOS, GSUB, KERN}; -use platform::font_template::FontTemplateData; -use platform::macos::font_context::FontContextHandle; -use servo_atoms::Atom; -use std::{fmt, ptr}; -use std::ops::Range; -use std::sync::Arc; -use style::computed_values::font_stretch::T as FontStretch; -use style::computed_values::font_weight::T as FontWeight; -use text::glyph::GlyphId; - -const KERN_PAIR_LEN: usize = 6; - -pub struct FontTable { - data: CFData, -} - -// assumes 72 points per inch, and 96 px per inch -fn px_to_pt(px: f64) -> f64 { - px / 96. * 72. -} - -// assumes 72 points per inch, and 96 px per inch -fn pt_to_px(pt: f64) -> f64 { - pt / 72. * 96. -} - -fn au_from_pt(pt: f64) -> Au { - Au::from_f64_px(pt_to_px(pt)) -} - -impl FontTable { - pub fn wrap(data: CFData) -> FontTable { - FontTable { data: data } - } -} - -impl FontTableMethods for FontTable { - fn buffer(&self) -> &[u8] { - self.data.bytes() - } -} - -#[derive(Debug)] -pub struct FontHandle { - font_data: Arc, - ctfont: CTFont, - h_kern_subtable: Option, - can_do_fast_shaping: bool, -} - -impl FontHandle { - /// Cache all the data needed for basic horizontal kerning. This is used only as a fallback or - /// fast path (when the GPOS table is missing or unnecessary) so it needn't handle every case. - fn find_h_kern_subtable(&self) -> Option { - let font_table = self.table_for_tag(KERN)?; - let mut result = CachedKernTable { - font_table: font_table, - pair_data_range: 0..0, - px_per_font_unit: 0.0, - }; - - // Look for a subtable with horizontal kerning in format 0. - // https://www.microsoft.com/typography/otspec/kern.htm - const KERN_COVERAGE_HORIZONTAL_FORMAT_0: u16 = 1; - const SUBTABLE_HEADER_LEN: usize = 6; - const FORMAT_0_HEADER_LEN: usize = 8; - { - let table = result.font_table.buffer(); - let version = BigEndian::read_u16(table); - if version != 0 { - return None; - } - let num_subtables = BigEndian::read_u16(&table[2..]); - let mut start = 4; - for _ in 0..num_subtables { - // TODO: Check the subtable version number? - let len = BigEndian::read_u16(&table[start + 2..]) as usize; - let cov = BigEndian::read_u16(&table[start + 4..]); - let end = start + len; - if cov == KERN_COVERAGE_HORIZONTAL_FORMAT_0 { - // Found a matching subtable. - if result.pair_data_range.len() > 0 { - debug!("Found multiple horizontal kern tables. Disable fast path."); - return None; - } - // Read the subtable header. - let subtable_start = start + SUBTABLE_HEADER_LEN; - let n_pairs = BigEndian::read_u16(&table[subtable_start..]) as usize; - let pair_data_start = subtable_start + FORMAT_0_HEADER_LEN; - - result.pair_data_range = pair_data_start..end; - if result.pair_data_range.len() != n_pairs * KERN_PAIR_LEN { - debug!("Bad data in kern header. Disable fast path."); - return None; - } - - let pt_per_font_unit = self.ctfont.pt_size() as f64 / - self.ctfont.units_per_em() as f64; - result.px_per_font_unit = pt_to_px(pt_per_font_unit); - } - start = end; - } - } - if result.pair_data_range.len() > 0 { - Some(result) - } else { - None - } - } -} - -struct CachedKernTable { - font_table: FontTable, - pair_data_range: Range, - px_per_font_unit: f64, -} - -impl CachedKernTable { - /// Search for a glyph pair in the kern table and return the corresponding value. - fn binary_search(&self, first_glyph: GlyphId, second_glyph: GlyphId) -> Option { - let pairs = &self.font_table.buffer()[self.pair_data_range.clone()]; - - let query = first_glyph << 16 | second_glyph; - let (mut start, mut end) = (0, pairs.len() / KERN_PAIR_LEN); - while start < end { - let i = (start + end) / 2; - let key = BigEndian::read_u32(&pairs[i * KERN_PAIR_LEN..]); - if key > query { - end = i; - } else if key < query { - start = i + 1; - } else { - return Some(BigEndian::read_i16(&pairs[i * KERN_PAIR_LEN + 4..])); - } - } - None - } -} - -impl fmt::Debug for CachedKernTable { - fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { - write!(f, "CachedKernTable") - } -} - - -impl FontHandleMethods for FontHandle { - fn new_from_template(_fctx: &FontContextHandle, - template: Arc, - pt_size: Option) - -> Result { - let size = match pt_size { - Some(s) => s.to_f64_px(), - None => 0.0 - }; - match template.ctfont(size) { - Some(ref ctfont) => { - let mut handle = FontHandle { - font_data: template.clone(), - ctfont: ctfont.clone_with_font_size(size), - h_kern_subtable: None, - can_do_fast_shaping: false, - }; - handle.h_kern_subtable = handle.find_h_kern_subtable(); - // TODO (#11310): Implement basic support for GPOS and GSUB. - handle.can_do_fast_shaping = handle.h_kern_subtable.is_some() && - handle.table_for_tag(GPOS).is_none() && - handle.table_for_tag(GSUB).is_none(); - Ok(handle) - } - None => { - Err(()) - } - } - } - - fn template(&self) -> Arc { - self.font_data.clone() - } - - fn family_name(&self) -> String { - self.ctfont.family_name() - } - - fn face_name(&self) -> Option { - Some(self.ctfont.face_name()) - } - - fn is_italic(&self) -> bool { - self.ctfont.symbolic_traits().is_italic() - } - - fn boldness(&self) -> FontWeight { - let normalized = self.ctfont.all_traits().normalized_weight(); // [-1.0, 1.0] - let normalized = if normalized <= 0.0 { - 4.0 + normalized * 3.0 // [1.0, 4.0] - } else { - 4.0 + normalized * 5.0 // [4.0, 9.0] - }; // [1.0, 9.0], centered on 4.0 - FontWeight::from_int(normalized.round() as i32 * 100).unwrap() - } - - fn stretchiness(&self) -> FontStretch { - let normalized = self.ctfont.all_traits().normalized_width(); // [-1.0, 1.0] - let normalized = (normalized + 1.0) / 2.0 * 9.0; // [0.0, 9.0] - match normalized { - v if v < 1.0 => FontStretch::UltraCondensed, - v if v < 2.0 => FontStretch::ExtraCondensed, - v if v < 3.0 => FontStretch::Condensed, - v if v < 4.0 => FontStretch::SemiCondensed, - v if v < 5.0 => FontStretch::Normal, - v if v < 6.0 => FontStretch::SemiExpanded, - v if v < 7.0 => FontStretch::Expanded, - v if v < 8.0 => FontStretch::ExtraExpanded, - _ => FontStretch::UltraExpanded, - } - } - - fn glyph_index(&self, codepoint: char) -> Option { - let characters: [UniChar; 1] = [codepoint as UniChar]; - let mut glyphs: [CGGlyph; 1] = [0 as CGGlyph]; - let count: CFIndex = 1; - - let result = self.ctfont.get_glyphs_for_characters(&characters[0], - &mut glyphs[0], - count); - - if !result { - // No glyph for this character - return None; - } - - assert_ne!(glyphs[0], 0); // FIXME: error handling - return Some(glyphs[0] as GlyphId); - } - - fn glyph_h_kerning(&self, first_glyph: GlyphId, second_glyph: GlyphId) -> FractionalPixel { - if let Some(ref table) = self.h_kern_subtable { - if let Some(font_units) = table.binary_search(first_glyph, second_glyph) { - return font_units as f64 * table.px_per_font_unit; - } - } - 0.0 - } - - fn can_do_fast_shaping(&self) -> bool { - self.can_do_fast_shaping - } - - fn glyph_h_advance(&self, glyph: GlyphId) -> Option { - let glyphs = [glyph as CGGlyph]; - let advance = self.ctfont.get_advances_for_glyphs(kCTFontDefaultOrientation, - &glyphs[0], - ptr::null_mut(), - 1); - Some(advance as FractionalPixel) - } - - fn metrics(&self) -> FontMetrics { - let bounding_rect: CGRect = self.ctfont.bounding_box(); - let ascent = self.ctfont.ascent() as f64; - let descent = self.ctfont.descent() as f64; - let em_size = Au::from_f64_px(self.ctfont.pt_size() as f64); - let leading = self.ctfont.leading() as f64; - - let scale = px_to_pt(self.ctfont.pt_size() as f64) / (ascent + descent); - let line_gap = (ascent + descent + leading + 0.5).floor(); - - let max_advance_width = au_from_pt(bounding_rect.size.width as f64); - let average_advance = self.glyph_index('0') - .and_then(|idx| self.glyph_h_advance(idx)) - .map(Au::from_f64_px) - .unwrap_or(max_advance_width); - - let metrics = FontMetrics { - underline_size: au_from_pt(self.ctfont.underline_thickness() as f64), - // TODO(Issue #201): underline metrics are not reliable. Have to pull out of font table - // directly. - // - // see also: https://bugs.webkit.org/show_bug.cgi?id=16768 - // see also: https://bugreports.qt-project.org/browse/QTBUG-13364 - underline_offset: au_from_pt(self.ctfont.underline_position() as f64), - strikeout_size: Au(0), // FIXME(Issue #942) - strikeout_offset: Au(0), // FIXME(Issue #942) - leading: au_from_pt(leading), - x_height: au_from_pt((self.ctfont.x_height() as f64) * scale), - em_size: em_size, - ascent: au_from_pt(ascent * scale), - descent: au_from_pt(descent * scale), - max_advance: max_advance_width, - average_advance: average_advance, - line_gap: Au::from_f64_px(line_gap), - }; - debug!("Font metrics (@{} pt): {:?}", self.ctfont.pt_size() as f64, metrics); - metrics - } - - fn table_for_tag(&self, tag: FontTableTag) -> Option { - let result: Option = self.ctfont.get_font_table(tag); - result.and_then(|data| { - Some(FontTable::wrap(data)) - }) - } - - fn identifier(&self) -> Atom { - self.font_data.identifier.clone() - } -} diff --git a/servo/components/gfx/platform/macos/font_context.rs b/servo/components/gfx/platform/macos/font_context.rs deleted file mode 100644 index 358d4e5dfd4f..000000000000 --- a/servo/components/gfx/platform/macos/font_context.rs +++ /dev/null @@ -1,15 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -#[derive(Clone, Debug, MallocSizeOf)] -pub struct FontContextHandle { - ctx: () -} - -impl FontContextHandle { - // this is a placeholder until NSFontManager or whatever is bound in here. - pub fn new() -> FontContextHandle { - FontContextHandle { ctx: () } - } -} diff --git a/servo/components/gfx/platform/macos/font_list.rs b/servo/components/gfx/platform/macos/font_list.rs deleted file mode 100644 index d72111f9c1ec..000000000000 --- a/servo/components/gfx/platform/macos/font_list.rs +++ /dev/null @@ -1,35 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -use core_text; -use std::borrow::ToOwned; - -pub fn for_each_available_family(mut callback: F) where F: FnMut(String) { - let family_names = core_text::font_collection::get_family_names(); - for family_name in family_names.iter() { - callback(family_name.to_string()); - } -} - -pub fn for_each_variation(family_name: &str, mut callback: F) where F: FnMut(String) { - debug!("Looking for faces of family: {}", family_name); - - let family_collection = core_text::font_collection::create_for_family(family_name); - if let Some(family_collection) = family_collection { - let family_descriptors = family_collection.get_descriptors(); - for family_descriptor in family_descriptors.iter() { - callback(family_descriptor.font_name()); - } - } -} - -pub fn system_default_family(_generic_name: &str) -> Option { - None -} - -pub fn last_resort_font_families() -> Vec { - vec!("Arial Unicode MS".to_owned(), "Arial".to_owned()) -} - -pub static SANS_SERIF_FONT_FAMILY: &'static str = "Helvetica"; diff --git a/servo/components/gfx/platform/macos/font_template.rs b/servo/components/gfx/platform/macos/font_template.rs deleted file mode 100644 index 15cc2a8689c1..000000000000 --- a/servo/components/gfx/platform/macos/font_template.rs +++ /dev/null @@ -1,168 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -use app_units::Au; -use core_graphics::data_provider::CGDataProvider; -use core_graphics::font::CGFont; -use core_text; -use core_text::font::CTFont; -use serde::{Deserialize, Deserializer, Serialize, Serializer}; -use serde::de::{Error, Visitor}; -use servo_atoms::Atom; -use servo_url::ServoUrl; -use std::borrow::ToOwned; -use std::collections::HashMap; -use std::fmt; -use std::fs::File; -use std::io::{Read, Error as IoError}; -use std::ops::Deref; -use std::sync::{Arc, Mutex}; -use webrender_api::NativeFontHandle; - -/// Platform specific font representation for mac. -/// The identifier is a PostScript font name. The -/// CTFont object is cached here for use by the -/// paint functions that create CGFont references. -#[derive(Deserialize, Serialize)] -pub struct FontTemplateData { - // If you add members here, review the Debug impl below - - /// The `CTFont` object, if present. This is cached here so that we don't have to keep creating - /// `CTFont` instances over and over. It can always be recreated from the `identifier` and/or - /// `font_data` fields. - /// - /// When sending a `FontTemplateData` instance across processes, this will be cleared out on - /// the other side, because `CTFont` instances cannot be sent across processes. This is - /// harmless, however, because it can always be recreated. - ctfont: CachedCTFont, - - pub identifier: Atom, - pub font_data: Option>> -} - -impl fmt::Debug for FontTemplateData { - fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { - fmt.debug_struct("FontTemplateData") - .field("ctfont", &self.ctfont) - .field("identifier", &self.identifier) - .field( - "font_data", - &self.font_data - .as_ref() - .map(|bytes| format!("[{} bytes]", bytes.len())) - ) - .finish() - } -} - -unsafe impl Send for FontTemplateData {} -unsafe impl Sync for FontTemplateData {} - -impl FontTemplateData { - pub fn new(identifier: Atom, font_data: Option>) -> Result { - Ok(FontTemplateData { - ctfont: CachedCTFont(Mutex::new(HashMap::new())), - identifier: identifier.to_owned(), - font_data: font_data.map(Arc::new) - }) - } - - /// Retrieves the Core Text font instance, instantiating it if necessary. - pub fn ctfont(&self, pt_size: f64) -> Option { - let mut ctfonts = self.ctfont.lock().unwrap(); - let pt_size_key = Au::from_f64_px(pt_size); - if !ctfonts.contains_key(&pt_size_key) { - // If you pass a zero font size to one of the Core Text APIs, it'll replace it with - // 12.0. We don't want that! (Issue #10492.) - let clamped_pt_size = pt_size.max(0.01); - let ctfont = match self.font_data { - Some(ref bytes) => { - let fontprov = CGDataProvider::from_buffer(bytes.clone()); - let cgfont_result = CGFont::from_data_provider(fontprov); - match cgfont_result { - Ok(cgfont) => { - Some(core_text::font::new_from_CGFont(&cgfont, clamped_pt_size)) - } - Err(_) => None - } - } - None => core_text::font::new_from_name(&*self.identifier, clamped_pt_size).ok(), - }; - if let Some(ctfont) = ctfont { - ctfonts.insert(pt_size_key, ctfont); - } - } - ctfonts.get(&pt_size_key).map(|ctfont| (*ctfont).clone()) - } - - /// Returns a clone of the data in this font. This may be a hugely expensive - /// operation (depending on the platform) which performs synchronous disk I/O - /// and should never be done lightly. - pub fn bytes(&self) -> Vec { - if let Some(font_data) = self.bytes_if_in_memory() { - return font_data; - } - - let path = ServoUrl::parse(&*self.ctfont(0.0) - .expect("No Core Text font available!") - .url() - .expect("No URL for Core Text font!") - .get_string() - .to_string()).expect("Couldn't parse Core Text font URL!") - .as_url().to_file_path() - .expect("Core Text font didn't name a path!"); - let mut bytes = Vec::new(); - File::open(path).expect("Couldn't open font file!").read_to_end(&mut bytes).unwrap(); - bytes - } - - /// Returns a clone of the bytes in this font if they are in memory. This function never - /// performs disk I/O. - pub fn bytes_if_in_memory(&self) -> Option> { - self.font_data.as_ref().map(|bytes| (**bytes).clone()) - } - - /// Returns the native font that underlies this font template, if applicable. - pub fn native_font(&self) -> Option { - self.ctfont(0.0).map(|ctfont| NativeFontHandle(ctfont.copy_to_CGFont())) - } -} - -#[derive(Debug)] -pub struct CachedCTFont(Mutex>); - -impl Deref for CachedCTFont { - type Target = Mutex>; - fn deref(&self) -> &Mutex> { - &self.0 - } -} - -impl Serialize for CachedCTFont { - fn serialize(&self, serializer: S) -> Result where S: Serializer { - serializer.serialize_none() - } -} - -impl<'de> Deserialize<'de> for CachedCTFont { - fn deserialize(deserializer: D) -> Result - where D: Deserializer<'de> { - struct NoneOptionVisitor; - - impl<'de> Visitor<'de> for NoneOptionVisitor { - type Value = CachedCTFont; - - fn expecting(&self, fmt: &mut fmt::Formatter) -> fmt::Result { - write!(fmt, "none") - } - - #[inline] - fn visit_none(self) -> Result where E: Error { - Ok(CachedCTFont(Mutex::new(HashMap::new()))) - } - } - - deserializer.deserialize_option(NoneOptionVisitor) - } -} diff --git a/servo/components/gfx/platform/mod.rs b/servo/components/gfx/platform/mod.rs deleted file mode 100644 index 897fbe9e8d31..000000000000 --- a/servo/components/gfx/platform/mod.rs +++ /dev/null @@ -1,59 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -#[cfg(any(target_os = "linux", target_os = "android"))] -pub use platform::freetype::{font, font_context}; - -#[cfg(any(target_os = "linux", target_os = "android"))] -pub use platform::freetype::{font_list, font_template}; - -#[cfg(target_os = "windows")] -pub use platform::windows::{font, font_context, font_list, font_template}; - -#[cfg(target_os = "macos")] -pub use platform::macos::{font, font_context, font_list, font_template}; - -#[cfg(any(target_os = "linux", target_os = "android"))] -mod freetype { - use libc::c_char; - use std::ffi::CStr; - use std::str; - - /// Creates a String from the given null-terminated buffer. - /// Panics if the buffer does not contain UTF-8. - unsafe fn c_str_to_string(s: *const c_char) -> String { - str::from_utf8(CStr::from_ptr(s).to_bytes()).unwrap().to_owned() - } - - pub mod font; - pub mod font_context; - - #[cfg(target_os = "linux")] - pub mod font_list; - #[cfg(target_os = "android")] - mod android { - pub mod font_list; - } - #[cfg(target_os = "android")] - pub use self::android::font_list; - - #[cfg(any(target_os = "linux", target_os = "android"))] - pub mod font_template; -} - -#[cfg(target_os = "macos")] -mod macos { - pub mod font; - pub mod font_context; - pub mod font_list; - pub mod font_template; -} - -#[cfg(target_os = "windows")] -mod windows { - pub mod font; - pub mod font_context; - pub mod font_list; - pub mod font_template; -} diff --git a/servo/components/gfx/platform/windows/font.rs b/servo/components/gfx/platform/windows/font.rs deleted file mode 100644 index 12df6d547d26..000000000000 --- a/servo/components/gfx/platform/windows/font.rs +++ /dev/null @@ -1,382 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -// NOTE: https://www.chromium.org/directwrite-font-proxy has useful -// information for an approach that we'll likely need to take when the -// renderer moves to a sandboxed process. - -use app_units::Au; -use dwrote; -use dwrote::{Font, FontFace, FontFile}; -use dwrote::{FontWeight, FontStretch, FontStyle}; -use font::{FontHandleMethods, FontMetrics, FontTableMethods}; -use font::{FontTableTag, FractionalPixel}; -use platform::font_template::FontTemplateData; -use platform::windows::font_context::FontContextHandle; -use platform::windows::font_list::font_from_atom; -use servo_atoms::Atom; -use std::sync::Arc; -use style::computed_values::font_stretch::T as StyleFontStretch; -use style::computed_values::font_weight::T as StyleFontWeight; -use text::glyph::GlyphId; -use truetype; - -// 1em = 12pt = 16px, assuming 72 points per inch and 96 px per inch -fn pt_to_px(pt: f64) -> f64 { pt / 72. * 96. } -fn em_to_px(em: f64) -> f64 { em * 16. } -fn au_from_em(em: f64) -> Au { Au::from_f64_px(em_to_px(em)) } -fn au_from_pt(pt: f64) -> Au { Au::from_f64_px(pt_to_px(pt)) } - -pub struct FontTable { - data: Vec, -} - -impl FontTable { - pub fn wrap(data: &[u8]) -> FontTable { - FontTable { data: data.to_vec() } - } -} - -impl FontTableMethods for FontTable { - fn buffer(&self) -> &[u8] { - &self.data - } -} - -fn make_tag(tag_bytes: &[u8]) -> FontTableTag { - assert_eq!(tag_bytes.len(), 4); - unsafe { *(tag_bytes.as_ptr() as *const FontTableTag) } -} - -macro_rules! try_lossy(($result:expr) => ($result.map_err(|_| (()))?)); - -// Given a set of records, figure out the string indices for the family and face -// names. We want name_id 1 and 2, and we need to use platform_id == 1 and -// language_id == 0 to avoid limitations in the truetype crate. We *could* just -// do our own parsing here, and use the offset/length data and pull the values out -// ourselves. -fn get_family_face_indices(records: &[truetype::naming_table::Record]) -> Option<(usize, usize)> { - let mut family_name_index = None; - let mut face_name_index = None; - - for i in 0..records.len() { - // the truetype crate can only decode mac platform format names - if records[i].platform_id != 1 { - continue; - } - - if records[i].language_id != 0 { - continue; - } - - if records[i].name_id == 1 { - family_name_index = Some(i); - } else if records[i].name_id == 2 { - face_name_index = Some(i); - } - } - - if family_name_index.is_some() && face_name_index.is_some() { - Some((family_name_index.unwrap(), face_name_index.unwrap())) - } else { - None - } -} - -// We need the font (DWriteFont) in order to be able to query things like -// the family name, face name, weight, etc. On Windows 10, the -// DWriteFontFace3 interface provides this on the FontFace, but that's only -// available on Win10+. -// -// Instead, we do the parsing work using the truetype crate for raw fonts. -// We're just extracting basic info, so this is sufficient for now. - -#[derive(Debug)] -struct FontInfo { - family_name: String, - face_name: String, - weight: StyleFontWeight, - stretch: StyleFontStretch, - style: FontStyle, -} - -impl FontInfo { - fn new_from_face(face: &FontFace) -> Result { - use std::cmp::{min, max}; - use std::io::Cursor; - use truetype::{NamingTable, Value, WindowsMetrics}; - - let name_table_bytes = face.get_font_table(make_tag(b"name")); - let os2_table_bytes = face.get_font_table(make_tag(b"OS/2")); - if name_table_bytes.is_none() || os2_table_bytes.is_none() { - return Err(()); - } - - let mut name_table_cursor = Cursor::new(name_table_bytes.as_ref().unwrap()); - let names = try_lossy!(NamingTable::read(&mut name_table_cursor)); - let (family, face) = match names { - NamingTable::Format0(ref table) => { - if let Some((family_index, face_index)) = get_family_face_indices(&table.records) { - let strings = table.strings().unwrap(); - let family = strings[family_index].clone(); - let face = strings[face_index].clone(); - ((family, face)) - } else { - return Err(()); - } - }, - NamingTable::Format1(ref table) => { - if let Some((family_index, face_index)) = get_family_face_indices(&table.records) { - let strings = table.strings().unwrap(); - let family = strings[family_index].clone(); - let face = strings[face_index].clone(); - ((family, face)) - } else { - return Err(()); - } - } - }; - - let mut os2_table_cursor = Cursor::new(os2_table_bytes.as_ref().unwrap()); - let metrics = try_lossy!(WindowsMetrics::read(&mut os2_table_cursor)); - let (weight_val, width_val, italic_bool) = match metrics { - WindowsMetrics::Version0(ref m) => { - (m.weight_class, m.width_class, m.selection_flags.0 & 1 == 1) - }, - WindowsMetrics::Version1(ref m) => { - (m.weight_class, m.width_class, m.selection_flags.0 & 1 == 1) - }, - WindowsMetrics::Version2(ref m) | - WindowsMetrics::Version3(ref m) | - WindowsMetrics::Version4(ref m) => { - (m.weight_class, m.width_class, m.selection_flags.0 & 1 == 1) - }, - WindowsMetrics::Version5(ref m) => { - (m.weight_class, m.width_class, m.selection_flags.0 & 1 == 1) - }, - }; - - let weight = - StyleFontWeight::from_int( - min(9, max(1, weight_val as i32 / 100)) * 100 - ).unwrap(); - - let stretch = match min(9, max(1, width_val)) { - 1 => StyleFontStretch::UltraCondensed, - 2 => StyleFontStretch::ExtraCondensed, - 3 => StyleFontStretch::Condensed, - 4 => StyleFontStretch::SemiCondensed, - 5 => StyleFontStretch::Normal, - 6 => StyleFontStretch::SemiExpanded, - 7 => StyleFontStretch::Expanded, - 8 => StyleFontStretch::ExtraExpanded, - 9 => StyleFontStretch::UltraExpanded, - _ => return Err(()), - }; - - let style = if italic_bool { - FontStyle::Italic - } else { - FontStyle::Normal - }; - - Ok(FontInfo { - family_name: family, - face_name: face, - weight: weight, - stretch: stretch, - style: style, - }) - } - - fn new_from_font(font: &Font) -> Result { - let style = font.style(); - let weight = StyleFontWeight(match font.weight() { - FontWeight::Thin => 100, - FontWeight::ExtraLight => 200, - FontWeight::Light => 300, - // slightly grayer gray - FontWeight::SemiLight => 300, - FontWeight::Regular => 400, - FontWeight::Medium => 500, - FontWeight::SemiBold => 600, - FontWeight::Bold => 700, - FontWeight::ExtraBold => 800, - FontWeight::Black => 900, - // slightly blacker black - FontWeight::ExtraBlack => 900, - }); - let stretch = match font.stretch() { - FontStretch::Undefined => StyleFontStretch::Normal, - FontStretch::UltraCondensed => StyleFontStretch::UltraCondensed, - FontStretch::ExtraCondensed => StyleFontStretch::ExtraCondensed, - FontStretch::Condensed => StyleFontStretch::Condensed, - FontStretch::SemiCondensed => StyleFontStretch::SemiCondensed, - FontStretch::Normal => StyleFontStretch::Normal, - FontStretch::SemiExpanded => StyleFontStretch::SemiExpanded, - FontStretch::Expanded => StyleFontStretch::Expanded, - FontStretch::ExtraExpanded => StyleFontStretch::ExtraExpanded, - FontStretch::UltraExpanded => StyleFontStretch::UltraExpanded, - }; - - Ok(FontInfo { - family_name: font.family_name(), - face_name: font.face_name(), - style: style, - weight: weight, - stretch: stretch, - }) - } -} - -#[derive(Debug)] -pub struct FontHandle { - font_data: Arc, - face: FontFace, - info: FontInfo, - em_size: f32, - du_per_em: f32, - du_to_px: f32, - scaled_du_to_px: f32, -} - -impl FontHandle { -} - -impl FontHandleMethods for FontHandle { - fn new_from_template(_: &FontContextHandle, template: Arc, pt_size: Option) - -> Result - { - let (info, face) = if let Some(ref raw_font) = template.bytes { - let font_file = FontFile::new_from_data(&raw_font); - if font_file.is_none() { - // failed to load raw font - return Err(()); - } - - let face = font_file.unwrap().create_face(0, dwrote::DWRITE_FONT_SIMULATIONS_NONE); - let info = FontInfo::new_from_face(&face)?; - (info, face) - } else { - let font = font_from_atom(&template.identifier); - let face = font.create_font_face(); - let info = FontInfo::new_from_font(&font)?; - (info, face) - }; - - let pt_size = pt_size.unwrap_or(au_from_pt(12.)); - let du_per_em = face.metrics().designUnitsPerEm as f32; - - let em_size = pt_size.to_f32_px() / 16.; - let design_units_per_pixel = du_per_em / 16.; - - let design_units_to_pixels = 1. / design_units_per_pixel; - let scaled_design_units_to_pixels = em_size / design_units_per_pixel; - - Ok(FontHandle { - font_data: template.clone(), - face: face, - info: info, - em_size: em_size, - du_per_em: du_per_em, - du_to_px: design_units_to_pixels, - scaled_du_to_px: scaled_design_units_to_pixels, - }) - } - - fn template(&self) -> Arc { - self.font_data.clone() - } - - fn family_name(&self) -> String { - self.info.family_name.clone() - } - - fn face_name(&self) -> Option { - Some(self.info.face_name.clone()) - } - - fn is_italic(&self) -> bool { - match self.info.style { - FontStyle::Normal => false, - FontStyle::Oblique | FontStyle::Italic => true, - } - } - - fn boldness(&self) -> StyleFontWeight { - self.info.weight - } - - fn stretchiness(&self) -> StyleFontStretch { - self.info.stretch - } - - fn glyph_index(&self, codepoint: char) -> Option { - let glyph = self.face.get_glyph_indices(&[codepoint as u32])[0]; - if glyph == 0 { - return None; - } - Some(glyph as GlyphId) - } - - fn glyph_h_advance(&self, glyph: GlyphId) -> Option { - if glyph == 0 { - return None; - } - - let gm = self.face.get_design_glyph_metrics(&[glyph as u16], false)[0]; - let f = (gm.advanceWidth as f32 * self.scaled_du_to_px) as FractionalPixel; - - Some(f) - } - - /// Can this font do basic horizontal LTR shaping without Harfbuzz? - fn can_do_fast_shaping(&self) -> bool { - // TODO copy CachedKernTable from the MacOS X implementation to - // somehwere global and use it here. We could also implement the - // IDirectWriteFontFace1 interface and use the glyph kerning pair - // methods there. - false - } - - fn glyph_h_kerning(&self, _: GlyphId, _: GlyphId) -> FractionalPixel { - 0.0 - } - - fn metrics(&self) -> FontMetrics { - let dm = self.face.metrics(); - - let au_from_du = |du| -> Au { Au::from_f32_px(du as f32 * self.du_to_px) }; - let au_from_du_s = |du| -> Au { Au:: from_f32_px(du as f32 * self.scaled_du_to_px) }; - - // anything that we calculate and don't just pull out of self.face.metrics - // is pulled out here for clarity - let leading = dm.ascent - dm.capHeight; - - let metrics = FontMetrics { - underline_size: au_from_du(dm.underlineThickness as i32), - underline_offset: au_from_du_s(dm.underlinePosition as i32), - strikeout_size: au_from_du(dm.strikethroughThickness as i32), - strikeout_offset: au_from_du_s(dm.strikethroughPosition as i32), - leading: au_from_du_s(leading as i32), - x_height: au_from_du_s(dm.xHeight as i32), - em_size: au_from_em(self.em_size as f64), - ascent: au_from_du_s(dm.ascent as i32), - descent: au_from_du_s(dm.descent as i32), - max_advance: au_from_pt(0.0), // FIXME - average_advance: au_from_pt(0.0), // FIXME - line_gap: au_from_du_s((dm.ascent + dm.descent + dm.lineGap as u16) as i32), - }; - debug!("Font metrics (@{} pt): {:?}", self.em_size * 12., metrics); - metrics - } - - fn table_for_tag(&self, tag: FontTableTag) -> Option { - self.face.get_font_table(tag).map(|bytes| FontTable { data: bytes }) - } - - fn identifier(&self) -> Atom { - self.font_data.identifier.clone() - } -} diff --git a/servo/components/gfx/platform/windows/font_context.rs b/servo/components/gfx/platform/windows/font_context.rs deleted file mode 100644 index 7d304ed138db..000000000000 --- a/servo/components/gfx/platform/windows/font_context.rs +++ /dev/null @@ -1,15 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -#[derive(Clone, Debug)] -pub struct FontContextHandle; - -impl FontContextHandle { - // *shrug* - pub fn new() -> FontContextHandle { - FontContextHandle {} - } -} - -malloc_size_of_is_0!(FontContextHandle); diff --git a/servo/components/gfx/platform/windows/font_list.rs b/servo/components/gfx/platform/windows/font_list.rs deleted file mode 100644 index 27dfd5e73fe9..000000000000 --- a/servo/components/gfx/platform/windows/font_list.rs +++ /dev/null @@ -1,71 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -use dwrote::{Font, FontDescriptor, FontCollection}; -use servo_atoms::Atom; -use std::collections::HashMap; -use std::sync::Mutex; -use std::sync::atomic::{Ordering, AtomicUsize}; - -lazy_static! { - static ref FONT_ATOM_COUNTER: AtomicUsize = AtomicUsize::new(1); - static ref FONT_ATOM_MAP: Mutex> = Mutex::new(HashMap::new()); -} - -pub static SANS_SERIF_FONT_FAMILY: &'static str = "Arial"; - -pub fn system_default_family(_: &str) -> Option { - Some("Verdana".to_owned()) -} - -pub fn last_resort_font_families() -> Vec { - vec!("Arial".to_owned()) -} - -pub fn for_each_available_family(mut callback: F) where F: FnMut(String) { - let system_fc = FontCollection::system(); - for family in system_fc.families_iter() { - callback(family.name()); - } -} - -// for_each_variation is supposed to return a string that can be -// atomized and then uniquely used to return back to this font. -// Some platforms use the full postscript name (MacOS X), or -// a font filename. -// -// For windows we're going to use just a basic integer value that -// we'll stringify, and then put them all in a HashMap with -// the actual FontDescriptor there. - -pub fn for_each_variation(family_name: &str, mut callback: F) where F: FnMut(String) { - let system_fc = FontCollection::system(); - if let Some(family) = system_fc.get_font_family_by_name(family_name) { - let count = family.get_font_count(); - for i in 0..count { - let font = family.get_font(i); - let index = FONT_ATOM_COUNTER.fetch_add(1, Ordering::Relaxed); - let index_str = format!("{}", index); - let atom = Atom::from(index_str.clone()); - - { - let descriptor = font.to_descriptor(); - let mut fonts = FONT_ATOM_MAP.lock().unwrap(); - fonts.insert(atom, descriptor); - } - - callback(index_str); - } - } -} - -pub fn descriptor_from_atom(ident: &Atom) -> FontDescriptor { - let fonts = FONT_ATOM_MAP.lock().unwrap(); - fonts.get(ident).unwrap().clone() -} - -pub fn font_from_atom(ident: &Atom) -> Font { - let fonts = FONT_ATOM_MAP.lock().unwrap(); - FontCollection::system().get_font_from_descriptor(fonts.get(ident).unwrap()).unwrap() -} diff --git a/servo/components/gfx/platform/windows/font_template.rs b/servo/components/gfx/platform/windows/font_template.rs deleted file mode 100644 index 5aff546701ff..000000000000 --- a/servo/components/gfx/platform/windows/font_template.rs +++ /dev/null @@ -1,66 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -use platform::windows::font_list::{descriptor_from_atom, font_from_atom}; -use servo_atoms::Atom; -use std::fmt; -use std::io; -use webrender_api::NativeFontHandle; - -#[derive(Deserialize, Serialize)] -pub struct FontTemplateData { - // If you add members here, review the Debug impl below - - pub bytes: Option>, - pub identifier: Atom, -} - -impl fmt::Debug for FontTemplateData { - fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { - fmt.debug_struct("FontTemplateData") - .field( - "bytes", - &self.bytes - .as_ref() - .map(|bytes| format!("[{} bytes]", bytes.len())) - ) - .field("identifier", &self.identifier) - .finish() - } -} - -impl FontTemplateData { - pub fn new(identifier: Atom, - font_data: Option>) -> Result { - Ok(FontTemplateData { - bytes: font_data, - identifier: identifier, - }) - } - - pub fn bytes(&self) -> Vec { - if self.bytes.is_some() { - self.bytes.as_ref().unwrap().clone() - } else { - let font = font_from_atom(&self.identifier); - let face = font.create_font_face(); - let files = face.get_files(); - assert!(files.len() > 0); - - files[0].get_font_file_bytes() - } - } - - pub fn bytes_if_in_memory(&self) -> Option> { - self.bytes.clone() - } - - pub fn native_font(&self) -> Option { - if self.bytes.is_none() { - Some(descriptor_from_atom(&self.identifier)) - } else { - None - } - } -} diff --git a/servo/components/gfx/tests/font_context.rs b/servo/components/gfx/tests/font_context.rs deleted file mode 100644 index f7fef58a5c29..000000000000 --- a/servo/components/gfx/tests/font_context.rs +++ /dev/null @@ -1,174 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -extern crate app_units; -extern crate gfx; -extern crate servo_arc; -extern crate servo_atoms; -extern crate style; -extern crate webrender_api; - -use app_units::Au; -use gfx::font::FontHandleMethods; -use gfx::font_cache_thread::{FontTemplates, FontTemplateInfo}; -use gfx::font_context::{FontContext, FontContextHandle, FontSource}; -use gfx::font_template::FontTemplateDescriptor; -use servo_arc::Arc; -use servo_atoms::Atom; -use std::cell::Cell; -use std::collections::HashMap; -use std::fs::File; -use std::io::prelude::*; -use std::path::PathBuf; -use std::rc::Rc; -use style::properties::longhands::font_stretch::computed_value::T as FontStretch; -use style::properties::longhands::font_style::computed_value::T as FontStyle; -use style::properties::longhands::font_variant_caps::computed_value::T as FontVariantCaps; -use style::properties::style_structs::Font as FontStyleStruct; -use style::values::computed::font::{FamilyName, FamilyNameSyntax, FontFamily, FontFamilyList, FontSize}; -use style::values::computed::font::{FontWeight, SingleFontFamily}; - -struct TestFontSource { - handle: FontContextHandle, - families: HashMap, - find_font_count: Rc>, -} - -impl TestFontSource { - fn new() -> TestFontSource { - let mut csstest_ascii = FontTemplates::new(); - Self::add_face(&mut csstest_ascii, "csstest-ascii"); - - let mut csstest_basic = FontTemplates::new(); - Self::add_face(&mut csstest_basic, "csstest-basic-regular"); - - let mut families = HashMap::new(); - families.insert(Atom::from("CSSTest ASCII"), csstest_ascii); - families.insert(Atom::from("CSSTest Basic"), csstest_basic); - - TestFontSource { - handle: FontContextHandle::new(), - families, - find_font_count: Rc::new(Cell::new(0)), - } - } - - fn add_face(family: &mut FontTemplates, name: &str) { - let mut path: PathBuf = [ - env!("CARGO_MANIFEST_DIR"), - "tests", - "support", - "CSSTest", - ].iter().collect(); - path.push(format!("{}.ttf", name)); - - let file = File::open(path).unwrap(); - - family.add_template( - Atom::from(name), - Some(file.bytes().map(|b| b.unwrap()).collect()) - ) - } -} - -impl FontSource for TestFontSource { - fn get_font_instance(&mut self, _key: webrender_api::FontKey, _size: Au) -> webrender_api::FontInstanceKey { - webrender_api::FontInstanceKey(webrender_api::IdNamespace(0), 0) - } - - fn find_font_template( - &mut self, - family: SingleFontFamily, - desc: FontTemplateDescriptor - ) -> Option { - let handle = &self.handle; - - self.find_font_count.set(self.find_font_count.get() + 1); - self.families - .get_mut(family.atom()) - .and_then(|family| family.find_font_for_style(&desc, handle)) - .map(|template| { - FontTemplateInfo { - font_template: template, - font_key: webrender_api::FontKey(webrender_api::IdNamespace(0), 0), - } - }) - } - - fn last_resort_font_template(&mut self, _desc: FontTemplateDescriptor) -> FontTemplateInfo { - unimplemented!(); - } -} - -fn style() -> FontStyleStruct { - let mut style = FontStyleStruct { - font_family: FontFamily::serif(), - font_style: FontStyle::Normal, - font_variant_caps: FontVariantCaps::Normal, - font_weight: FontWeight::normal(), - font_size: FontSize::medium(), - font_stretch: FontStretch::Normal, - hash: 0, - }; - style.compute_font_hash(); - style -} - -fn font_family(names: Vec<&str>) -> FontFamily { - let names: Vec = names.into_iter().map(|name| - SingleFontFamily::FamilyName(FamilyName { - name: Atom::from(name), - syntax: FamilyNameSyntax::Quoted, - }) - ).collect(); - - FontFamily(FontFamilyList::new(names.into_boxed_slice())) -} - -#[test] -fn test_font_group_is_cached_by_style() { - let source = TestFontSource::new(); - let mut context = FontContext::new(source); - - let style1 = style(); - - let mut style2 = style(); - style2.set_font_style(FontStyle::Italic); - - assert_eq!( - context.font_group(Arc::new(style1.clone())).as_ptr(), - context.font_group(Arc::new(style1.clone())).as_ptr(), - "the same font group should be returned for two styles with the same hash" - ); - - assert_ne!( - context.font_group(Arc::new(style1.clone())).as_ptr(), - context.font_group(Arc::new(style2.clone())).as_ptr(), - "different font groups should be returned for two styles with different hashes" - ) -} - -#[test] -fn test_font_group_find_by_codepoint() { - let source = TestFontSource::new(); - let count = source.find_font_count.clone(); - let mut context = FontContext::new(source); - - let mut style = style(); - style.set_font_family(font_family(vec!("CSSTest ASCII", "CSSTest Basic"))); - - let group = context.font_group(Arc::new(style)); - - let font = group.borrow_mut().find_by_codepoint(&mut context, 'a').unwrap(); - assert_eq!(font.borrow().handle.family_name(), "CSSTest ASCII"); - assert_eq!(count.get(), 1, "only the first font in the list should have been loaded"); - - let font = group.borrow_mut().find_by_codepoint(&mut context, 'a').unwrap(); - assert_eq!(font.borrow().handle.family_name(), "CSSTest ASCII"); - assert_eq!(count.get(), 1, "we shouldn't load the same font a second time"); - - let font = group.borrow_mut().find_by_codepoint(&mut context, 'á').unwrap(); - assert_eq!(font.borrow().handle.family_name(), "CSSTest Basic"); - assert_eq!(count.get(), 2, "both fonts should now have been loaded"); -} diff --git a/servo/components/gfx/tests/font_template.rs b/servo/components/gfx/tests/font_template.rs deleted file mode 100644 index 4b513d9f0c4c..000000000000 --- a/servo/components/gfx/tests/font_template.rs +++ /dev/null @@ -1,67 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -#[cfg(not(target_os = "macos"))] extern crate gfx; -#[cfg(not(target_os = "macos"))] extern crate servo_atoms; -#[cfg(not(target_os = "macos"))] extern crate style; - -// Test doesn't yet run on Mac, see https://github.com/servo/servo/pull/19928 for explanation. -#[cfg(not(target_os = "macos"))] -#[test] -fn test_font_template_descriptor() { - use gfx::font_context::FontContextHandle; - use gfx::font_template::{FontTemplate, FontTemplateDescriptor}; - use servo_atoms::Atom; - use std::fs::File; - use std::io::prelude::*; - use std::path::PathBuf; - use style::computed_values::font_stretch::T as FontStretch; - use style::values::computed::font::FontWeight; - - fn descriptor(filename: &str) -> FontTemplateDescriptor { - let mut path: PathBuf = [ - env!("CARGO_MANIFEST_DIR"), - "tests", - "support", - "dejavu-fonts-ttf-2.37", - "ttf", - ].iter().collect(); - path.push(format!("{}.ttf", filename)); - - let file = File::open(path).unwrap(); - - let mut template = FontTemplate::new( - Atom::from(filename), - Some(file.bytes().map(|b| b.unwrap()).collect()) - ).unwrap(); - - let context = FontContextHandle::new(); - - template.descriptor(&context).unwrap() - } - - assert_eq!(descriptor("DejaVuSans"), FontTemplateDescriptor { - weight: FontWeight::normal(), - stretch: FontStretch::Normal, - italic: false, - }); - - assert_eq!(descriptor("DejaVuSans-Bold"), FontTemplateDescriptor { - weight: FontWeight::bold(), - stretch: FontStretch::Normal, - italic: false, - }); - - assert_eq!(descriptor("DejaVuSans-Oblique"), FontTemplateDescriptor { - weight: FontWeight::normal(), - stretch: FontStretch::Normal, - italic: true, - }); - - assert_eq!(descriptor("DejaVuSansCondensed-BoldOblique"), FontTemplateDescriptor { - weight: FontWeight::bold(), - stretch: FontStretch::SemiCondensed, - italic: true, - }); -} diff --git a/servo/components/gfx/tests/support/CSSTest/LICENSE b/servo/components/gfx/tests/support/CSSTest/LICENSE deleted file mode 100644 index 9b3c1a6df547..000000000000 --- a/servo/components/gfx/tests/support/CSSTest/LICENSE +++ /dev/null @@ -1,94 +0,0 @@ -Copyright (c) 2003-2008 SIL International (http://www.sil.org/), -with Reserved Font Names "Gentium" and "SIL". - -This Font Software is licensed under the SIL Open Font License, Version 1.1. -This license is copied below, and is also available with a FAQ at: -http://scripts.sil.org/OFL - - ------------------------------------------------------------ -SIL OPEN FONT LICENSE Version 1.1 - 1 February 2007 ------------------------------------------------------------ - -PREAMBLE -The goals of the Open Font License (OFL) are to stimulate worldwide -development of collaborative font projects, to support the font creation -efforts of academic and linguistic communities, and to provide a free and -open framework in which fonts may be shared and improved in partnership -with others. - -The OFL allows the licensed fonts to be used, studied, modified and -redistributed freely as long as they are not sold by themselves. The -fonts, including any derivative works, can be bundled, embedded, -redistributed and/or sold with any software provided that the font -names of derivative works are changed. The fonts and derivatives, -however, cannot be released under any other type of license. The -requirement for fonts to remain under this license does not apply -to any document created using the fonts or their derivatives. - -DEFINITIONS -"Font Software" refers to the set of files released by the Copyright -Holder(s) under this license and clearly marked as such. This may -include source files, build scripts and documentation. - -"Reserved Font Name" refers to any names specified as such after the -copyright statement(s). - -"Original Version" refers to the collection of Font Software components as -distributed by the Copyright Holder(s). - -"Modified Version" refers to any derivative made by adding to, deleting, -or substituting -- in part or in whole -- any of the components of the -Original Version, by changing formats or by porting the Font Software to a -new environment. - -"Author" refers to any designer, engineer, programmer, technical -writer or other person who contributed to the Font Software. - -PERMISSION & CONDITIONS -Permission is hereby granted, free of charge, to any person obtaining -a copy of the Font Software, to use, study, copy, merge, embed, modify, -redistribute, and sell modified and unmodified copies of the Font -Software, subject to the following conditions: - -1) Neither the Font Software nor any of its individual components, -in Original or Modified Versions, may be sold by itself. - -2) Original or Modified Versions of the Font Software may be bundled, -redistributed and/or sold with any software, provided that each copy -contains the above copyright notice and this license. These can be -included either as stand-alone text files, human-readable headers or -in the appropriate machine-readable metadata fields within text or -binary files as long as those fields can be easily viewed by the user. - -3) No Modified Version of the Font Software may use the Reserved Font -Name(s) unless explicit written permission is granted by the corresponding -Copyright Holder. This restriction only applies to the primary font name as -presented to the users. - -4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font -Software shall not be used to promote, endorse or advertise any -Modified Version, except to acknowledge the contribution(s) of the -Copyright Holder(s) and the Author(s) or with their explicit written -permission. - -5) The Font Software, modified or unmodified, in part or in whole, -must be distributed entirely under this license, and must not be -distributed under any other license. The requirement for fonts to -remain under this license does not apply to any document created -using the Font Software. - -TERMINATION -This license becomes null and void if any of the above conditions are -not met. - -DISCLAIMER -THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT -OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE -COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL -DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM -OTHER DEALINGS IN THE FONT SOFTWARE. diff --git a/servo/components/gfx/tests/support/CSSTest/README b/servo/components/gfx/tests/support/CSSTest/README deleted file mode 100644 index d4fe8fb50aef..000000000000 --- a/servo/components/gfx/tests/support/CSSTest/README +++ /dev/null @@ -1,25 +0,0 @@ -These fonts are a copy of the CSSTest fonts in web-platform-tests, so that we -can use them for unit-testing our font code. Here is the README from -web-platform-tests: - ------ - -These fonts were created to support the testing of the font features -in CSS, and are required to run some of the tests for those features. - -The fonts are modified versions of Gentium Basic, licensed by SIL under -the Open Font License which allows modifications as long as the terms -of the license are met. - -The original fonts were used to create the family 'CSSTest Basic'. This -family has four faces and can be used for testing bold / italics. -A subsetted version of this font with only glyphs for basic ASCII -characters is 'CSSTest ASCII'. This was used to make the other -variations. Most of the modications are to the name table and character -maps, for the most part glyphs were not modified. - -The fonts are available for download both individually and as a -ZIP package below. - -The files test.html and test.xhtml test that the fonts have been -correctly installed. diff --git a/servo/components/gfx/tests/support/CSSTest/csstest-ascii.ttf b/servo/components/gfx/tests/support/CSSTest/csstest-ascii.ttf deleted file mode 100644 index 076788e9ce37..000000000000 Binary files a/servo/components/gfx/tests/support/CSSTest/csstest-ascii.ttf and /dev/null differ diff --git a/servo/components/gfx/tests/support/CSSTest/csstest-basic-bold.ttf b/servo/components/gfx/tests/support/CSSTest/csstest-basic-bold.ttf deleted file mode 100644 index 8c53e6fdd422..000000000000 Binary files a/servo/components/gfx/tests/support/CSSTest/csstest-basic-bold.ttf and /dev/null differ diff --git a/servo/components/gfx/tests/support/CSSTest/csstest-basic-bolditalic.ttf b/servo/components/gfx/tests/support/CSSTest/csstest-basic-bolditalic.ttf deleted file mode 100644 index 5b58f1ffa247..000000000000 Binary files a/servo/components/gfx/tests/support/CSSTest/csstest-basic-bolditalic.ttf and /dev/null differ diff --git a/servo/components/gfx/tests/support/CSSTest/csstest-basic-italic.ttf b/servo/components/gfx/tests/support/CSSTest/csstest-basic-italic.ttf deleted file mode 100644 index 10926ce4e110..000000000000 Binary files a/servo/components/gfx/tests/support/CSSTest/csstest-basic-italic.ttf and /dev/null differ diff --git a/servo/components/gfx/tests/support/CSSTest/csstest-basic-regular.ttf b/servo/components/gfx/tests/support/CSSTest/csstest-basic-regular.ttf deleted file mode 100644 index c98d6130b680..000000000000 Binary files a/servo/components/gfx/tests/support/CSSTest/csstest-basic-regular.ttf and /dev/null differ diff --git a/servo/components/gfx/tests/support/CSSTest/csstest-fallback.ttf b/servo/components/gfx/tests/support/CSSTest/csstest-fallback.ttf deleted file mode 100644 index 4f20f261f4da..000000000000 Binary files a/servo/components/gfx/tests/support/CSSTest/csstest-fallback.ttf and /dev/null differ diff --git a/servo/components/gfx/tests/support/CSSTest/csstest-familyname-bold.ttf b/servo/components/gfx/tests/support/CSSTest/csstest-familyname-bold.ttf deleted file mode 100644 index 4bddbc2d16f5..000000000000 Binary files a/servo/components/gfx/tests/support/CSSTest/csstest-familyname-bold.ttf and /dev/null differ diff --git a/servo/components/gfx/tests/support/CSSTest/csstest-familyname-funkyA.ttf b/servo/components/gfx/tests/support/CSSTest/csstest-familyname-funkyA.ttf deleted file mode 100644 index 9f605f9190f8..000000000000 Binary files a/servo/components/gfx/tests/support/CSSTest/csstest-familyname-funkyA.ttf and /dev/null differ diff --git a/servo/components/gfx/tests/support/CSSTest/csstest-familyname-funkyB.ttf b/servo/components/gfx/tests/support/CSSTest/csstest-familyname-funkyB.ttf deleted file mode 100644 index 0a3688c53ab9..000000000000 Binary files a/servo/components/gfx/tests/support/CSSTest/csstest-familyname-funkyB.ttf and /dev/null differ diff --git a/servo/components/gfx/tests/support/CSSTest/csstest-familyname-funkyC.ttf b/servo/components/gfx/tests/support/CSSTest/csstest-familyname-funkyC.ttf deleted file mode 100644 index feb463b15d97..000000000000 Binary files a/servo/components/gfx/tests/support/CSSTest/csstest-familyname-funkyC.ttf and /dev/null differ diff --git a/servo/components/gfx/tests/support/CSSTest/csstest-familyname.ttf b/servo/components/gfx/tests/support/CSSTest/csstest-familyname.ttf deleted file mode 100644 index 5131280c2feb..000000000000 Binary files a/servo/components/gfx/tests/support/CSSTest/csstest-familyname.ttf and /dev/null differ diff --git a/servo/components/gfx/tests/support/CSSTest/csstest-verify.ttf b/servo/components/gfx/tests/support/CSSTest/csstest-verify.ttf deleted file mode 100644 index 1d0b62a200bf..000000000000 Binary files a/servo/components/gfx/tests/support/CSSTest/csstest-verify.ttf and /dev/null differ diff --git a/servo/components/gfx/tests/support/CSSTest/csstest-weights-100.ttf b/servo/components/gfx/tests/support/CSSTest/csstest-weights-100.ttf deleted file mode 100644 index 964558a94992..000000000000 Binary files a/servo/components/gfx/tests/support/CSSTest/csstest-weights-100.ttf and /dev/null differ diff --git a/servo/components/gfx/tests/support/CSSTest/csstest-weights-1479-w1.ttf b/servo/components/gfx/tests/support/CSSTest/csstest-weights-1479-w1.ttf deleted file mode 100644 index 181d1a70e1da..000000000000 Binary files a/servo/components/gfx/tests/support/CSSTest/csstest-weights-1479-w1.ttf and /dev/null differ diff --git a/servo/components/gfx/tests/support/CSSTest/csstest-weights-1479-w4.ttf b/servo/components/gfx/tests/support/CSSTest/csstest-weights-1479-w4.ttf deleted file mode 100644 index 1751716d7a35..000000000000 Binary files a/servo/components/gfx/tests/support/CSSTest/csstest-weights-1479-w4.ttf and /dev/null differ diff --git a/servo/components/gfx/tests/support/CSSTest/csstest-weights-1479-w7.ttf b/servo/components/gfx/tests/support/CSSTest/csstest-weights-1479-w7.ttf deleted file mode 100644 index f38fca9ff208..000000000000 Binary files a/servo/components/gfx/tests/support/CSSTest/csstest-weights-1479-w7.ttf and /dev/null differ diff --git a/servo/components/gfx/tests/support/CSSTest/csstest-weights-1479-w9.ttf b/servo/components/gfx/tests/support/CSSTest/csstest-weights-1479-w9.ttf deleted file mode 100644 index 7f34bbff8299..000000000000 Binary files a/servo/components/gfx/tests/support/CSSTest/csstest-weights-1479-w9.ttf and /dev/null differ diff --git a/servo/components/gfx/tests/support/CSSTest/csstest-weights-15-w1.ttf b/servo/components/gfx/tests/support/CSSTest/csstest-weights-15-w1.ttf deleted file mode 100644 index 851f29b9f0bd..000000000000 Binary files a/servo/components/gfx/tests/support/CSSTest/csstest-weights-15-w1.ttf and /dev/null differ diff --git a/servo/components/gfx/tests/support/CSSTest/csstest-weights-15-w5.ttf b/servo/components/gfx/tests/support/CSSTest/csstest-weights-15-w5.ttf deleted file mode 100644 index cb06f50f905d..000000000000 Binary files a/servo/components/gfx/tests/support/CSSTest/csstest-weights-15-w5.ttf and /dev/null differ diff --git a/servo/components/gfx/tests/support/CSSTest/csstest-weights-200.ttf b/servo/components/gfx/tests/support/CSSTest/csstest-weights-200.ttf deleted file mode 100644 index 306d89549864..000000000000 Binary files a/servo/components/gfx/tests/support/CSSTest/csstest-weights-200.ttf and /dev/null differ diff --git a/servo/components/gfx/tests/support/CSSTest/csstest-weights-24-w2.ttf b/servo/components/gfx/tests/support/CSSTest/csstest-weights-24-w2.ttf deleted file mode 100644 index 4c8533e658de..000000000000 Binary files a/servo/components/gfx/tests/support/CSSTest/csstest-weights-24-w2.ttf and /dev/null differ diff --git a/servo/components/gfx/tests/support/CSSTest/csstest-weights-24-w4.ttf b/servo/components/gfx/tests/support/CSSTest/csstest-weights-24-w4.ttf deleted file mode 100644 index 63cecb9aa308..000000000000 Binary files a/servo/components/gfx/tests/support/CSSTest/csstest-weights-24-w4.ttf and /dev/null differ diff --git a/servo/components/gfx/tests/support/CSSTest/csstest-weights-2569-w2.ttf b/servo/components/gfx/tests/support/CSSTest/csstest-weights-2569-w2.ttf deleted file mode 100644 index 99e03e90e674..000000000000 Binary files a/servo/components/gfx/tests/support/CSSTest/csstest-weights-2569-w2.ttf and /dev/null differ diff --git a/servo/components/gfx/tests/support/CSSTest/csstest-weights-2569-w5.ttf b/servo/components/gfx/tests/support/CSSTest/csstest-weights-2569-w5.ttf deleted file mode 100644 index 9300aeef4c1f..000000000000 Binary files a/servo/components/gfx/tests/support/CSSTest/csstest-weights-2569-w5.ttf and /dev/null differ diff --git a/servo/components/gfx/tests/support/CSSTest/csstest-weights-2569-w6.ttf b/servo/components/gfx/tests/support/CSSTest/csstest-weights-2569-w6.ttf deleted file mode 100644 index 546489031e20..000000000000 Binary files a/servo/components/gfx/tests/support/CSSTest/csstest-weights-2569-w6.ttf and /dev/null differ diff --git a/servo/components/gfx/tests/support/CSSTest/csstest-weights-2569-w9.ttf b/servo/components/gfx/tests/support/CSSTest/csstest-weights-2569-w9.ttf deleted file mode 100644 index 66a1a06015cf..000000000000 Binary files a/servo/components/gfx/tests/support/CSSTest/csstest-weights-2569-w9.ttf and /dev/null differ diff --git a/servo/components/gfx/tests/support/CSSTest/csstest-weights-258-w2.ttf b/servo/components/gfx/tests/support/CSSTest/csstest-weights-258-w2.ttf deleted file mode 100644 index 95b048816cf2..000000000000 Binary files a/servo/components/gfx/tests/support/CSSTest/csstest-weights-258-w2.ttf and /dev/null differ diff --git a/servo/components/gfx/tests/support/CSSTest/csstest-weights-258-w5.ttf b/servo/components/gfx/tests/support/CSSTest/csstest-weights-258-w5.ttf deleted file mode 100644 index 3de6631d0bc0..000000000000 Binary files a/servo/components/gfx/tests/support/CSSTest/csstest-weights-258-w5.ttf and /dev/null differ diff --git a/servo/components/gfx/tests/support/CSSTest/csstest-weights-258-w8.ttf b/servo/components/gfx/tests/support/CSSTest/csstest-weights-258-w8.ttf deleted file mode 100644 index 25d64dfb8c1d..000000000000 Binary files a/servo/components/gfx/tests/support/CSSTest/csstest-weights-258-w8.ttf and /dev/null differ diff --git a/servo/components/gfx/tests/support/CSSTest/csstest-weights-300.ttf b/servo/components/gfx/tests/support/CSSTest/csstest-weights-300.ttf deleted file mode 100644 index 87fcd310aeed..000000000000 Binary files a/servo/components/gfx/tests/support/CSSTest/csstest-weights-300.ttf and /dev/null differ diff --git a/servo/components/gfx/tests/support/CSSTest/csstest-weights-3589-w3.ttf b/servo/components/gfx/tests/support/CSSTest/csstest-weights-3589-w3.ttf deleted file mode 100644 index fb071c03dfe4..000000000000 Binary files a/servo/components/gfx/tests/support/CSSTest/csstest-weights-3589-w3.ttf and /dev/null differ diff --git a/servo/components/gfx/tests/support/CSSTest/csstest-weights-3589-w5.ttf b/servo/components/gfx/tests/support/CSSTest/csstest-weights-3589-w5.ttf deleted file mode 100644 index 2b9e530a816f..000000000000 Binary files a/servo/components/gfx/tests/support/CSSTest/csstest-weights-3589-w5.ttf and /dev/null differ diff --git a/servo/components/gfx/tests/support/CSSTest/csstest-weights-3589-w8.ttf b/servo/components/gfx/tests/support/CSSTest/csstest-weights-3589-w8.ttf deleted file mode 100644 index 745a60ae25fb..000000000000 Binary files a/servo/components/gfx/tests/support/CSSTest/csstest-weights-3589-w8.ttf and /dev/null differ diff --git a/servo/components/gfx/tests/support/CSSTest/csstest-weights-3589-w9.ttf b/servo/components/gfx/tests/support/CSSTest/csstest-weights-3589-w9.ttf deleted file mode 100644 index e805f01d8fd7..000000000000 Binary files a/servo/components/gfx/tests/support/CSSTest/csstest-weights-3589-w9.ttf and /dev/null differ diff --git a/servo/components/gfx/tests/support/CSSTest/csstest-weights-400.ttf b/servo/components/gfx/tests/support/CSSTest/csstest-weights-400.ttf deleted file mode 100644 index 9938a378bd63..000000000000 Binary files a/servo/components/gfx/tests/support/CSSTest/csstest-weights-400.ttf and /dev/null differ diff --git a/servo/components/gfx/tests/support/CSSTest/csstest-weights-47-w4.ttf b/servo/components/gfx/tests/support/CSSTest/csstest-weights-47-w4.ttf deleted file mode 100644 index f6108ab2100e..000000000000 Binary files a/servo/components/gfx/tests/support/CSSTest/csstest-weights-47-w4.ttf and /dev/null differ diff --git a/servo/components/gfx/tests/support/CSSTest/csstest-weights-47-w7.ttf b/servo/components/gfx/tests/support/CSSTest/csstest-weights-47-w7.ttf deleted file mode 100644 index 9496c5fdf274..000000000000 Binary files a/servo/components/gfx/tests/support/CSSTest/csstest-weights-47-w7.ttf and /dev/null differ diff --git a/servo/components/gfx/tests/support/CSSTest/csstest-weights-500.ttf b/servo/components/gfx/tests/support/CSSTest/csstest-weights-500.ttf deleted file mode 100644 index 0c132d28cdb5..000000000000 Binary files a/servo/components/gfx/tests/support/CSSTest/csstest-weights-500.ttf and /dev/null differ diff --git a/servo/components/gfx/tests/support/CSSTest/csstest-weights-600.ttf b/servo/components/gfx/tests/support/CSSTest/csstest-weights-600.ttf deleted file mode 100644 index ce776c01a2da..000000000000 Binary files a/servo/components/gfx/tests/support/CSSTest/csstest-weights-600.ttf and /dev/null differ diff --git a/servo/components/gfx/tests/support/CSSTest/csstest-weights-700.ttf b/servo/components/gfx/tests/support/CSSTest/csstest-weights-700.ttf deleted file mode 100644 index 156b0287a986..000000000000 Binary files a/servo/components/gfx/tests/support/CSSTest/csstest-weights-700.ttf and /dev/null differ diff --git a/servo/components/gfx/tests/support/CSSTest/csstest-weights-800.ttf b/servo/components/gfx/tests/support/CSSTest/csstest-weights-800.ttf deleted file mode 100644 index 0f41c304677f..000000000000 Binary files a/servo/components/gfx/tests/support/CSSTest/csstest-weights-800.ttf and /dev/null differ diff --git a/servo/components/gfx/tests/support/CSSTest/csstest-weights-900.ttf b/servo/components/gfx/tests/support/CSSTest/csstest-weights-900.ttf deleted file mode 100644 index 97c8735125bc..000000000000 Binary files a/servo/components/gfx/tests/support/CSSTest/csstest-weights-900.ttf and /dev/null differ diff --git a/servo/components/gfx/tests/support/CSSTest/csstest-weights-full-w1.ttf b/servo/components/gfx/tests/support/CSSTest/csstest-weights-full-w1.ttf deleted file mode 100644 index dd1f6a9101c9..000000000000 Binary files a/servo/components/gfx/tests/support/CSSTest/csstest-weights-full-w1.ttf and /dev/null differ diff --git a/servo/components/gfx/tests/support/CSSTest/csstest-weights-full-w2.ttf b/servo/components/gfx/tests/support/CSSTest/csstest-weights-full-w2.ttf deleted file mode 100644 index c42a506e21a1..000000000000 Binary files a/servo/components/gfx/tests/support/CSSTest/csstest-weights-full-w2.ttf and /dev/null differ diff --git a/servo/components/gfx/tests/support/CSSTest/csstest-weights-full-w3.ttf b/servo/components/gfx/tests/support/CSSTest/csstest-weights-full-w3.ttf deleted file mode 100644 index f16a77b6edd0..000000000000 Binary files a/servo/components/gfx/tests/support/CSSTest/csstest-weights-full-w3.ttf and /dev/null differ diff --git a/servo/components/gfx/tests/support/CSSTest/csstest-weights-full-w4.ttf b/servo/components/gfx/tests/support/CSSTest/csstest-weights-full-w4.ttf deleted file mode 100644 index 8b1abae2f3ff..000000000000 Binary files a/servo/components/gfx/tests/support/CSSTest/csstest-weights-full-w4.ttf and /dev/null differ diff --git a/servo/components/gfx/tests/support/CSSTest/csstest-weights-full-w5.ttf b/servo/components/gfx/tests/support/CSSTest/csstest-weights-full-w5.ttf deleted file mode 100644 index 94aa99968272..000000000000 Binary files a/servo/components/gfx/tests/support/CSSTest/csstest-weights-full-w5.ttf and /dev/null differ diff --git a/servo/components/gfx/tests/support/CSSTest/csstest-weights-full-w6.ttf b/servo/components/gfx/tests/support/CSSTest/csstest-weights-full-w6.ttf deleted file mode 100644 index 9badb99f5008..000000000000 Binary files a/servo/components/gfx/tests/support/CSSTest/csstest-weights-full-w6.ttf and /dev/null differ diff --git a/servo/components/gfx/tests/support/CSSTest/csstest-weights-full-w7.ttf b/servo/components/gfx/tests/support/CSSTest/csstest-weights-full-w7.ttf deleted file mode 100644 index 049d93d76981..000000000000 Binary files a/servo/components/gfx/tests/support/CSSTest/csstest-weights-full-w7.ttf and /dev/null differ diff --git a/servo/components/gfx/tests/support/CSSTest/csstest-weights-full-w8.ttf b/servo/components/gfx/tests/support/CSSTest/csstest-weights-full-w8.ttf deleted file mode 100644 index 80169bf0715e..000000000000 Binary files a/servo/components/gfx/tests/support/CSSTest/csstest-weights-full-w8.ttf and /dev/null differ diff --git a/servo/components/gfx/tests/support/CSSTest/csstest-weights-full-w9.ttf b/servo/components/gfx/tests/support/CSSTest/csstest-weights-full-w9.ttf deleted file mode 100644 index 542e4ab199ee..000000000000 Binary files a/servo/components/gfx/tests/support/CSSTest/csstest-weights-full-w9.ttf and /dev/null differ diff --git a/servo/components/gfx/tests/support/CSSTest/csstest-weights.ttf b/servo/components/gfx/tests/support/CSSTest/csstest-weights.ttf deleted file mode 100644 index b9c5a507f238..000000000000 Binary files a/servo/components/gfx/tests/support/CSSTest/csstest-weights.ttf and /dev/null differ diff --git a/servo/components/gfx/tests/support/dejavu-fonts-ttf-2.37/AUTHORS b/servo/components/gfx/tests/support/dejavu-fonts-ttf-2.37/AUTHORS deleted file mode 100644 index 55c2bc9906fb..000000000000 --- a/servo/components/gfx/tests/support/dejavu-fonts-ttf-2.37/AUTHORS +++ /dev/null @@ -1,57 +0,0 @@ -abysta at yandex.ru -Adrian Schroeter -Aleksey Chalabyan -Andrey Valentinovich Panov -Ben Laenen -Besarion Gugushvili -Bhikkhu Pesala -Clayborne Arevalo -Dafydd Harries -Danilo Segan -Davide Viti -David Jez -David Lawrence Ramsey -Denis Jacquerye -Dwayne Bailey -Eugeniy Meshcheryakov -Frédéric Wang -Gee Fung Sit -Heikki Lindroos -James Cloos -James Crippen -John Karp -Keenan Pepper -Lars Næsbye Christensen -Lior Halphon -MaEr -Mashrab Kuvatov -Max Berger -Mederic Boquien -Michael Everson -MihailJP -Misu Moldovan -Nguyen Thai Ngoc Duy -Nicolas Mailhot -Norayr Chilingarian -Olleg Samoylov -Ognyan Kulev -Ondrej Koala Vacha -Peter Cernak -Remy Oudompheng -Roozbeh Pournader -Rouben Hakobian -Sahak Petrosyan -Sami Tarazi -Sander Vesik -Stepan Roh -Stephen Hartke -Steve Tinney -Tavmjong Bah -Thomas Henlich -Tim May -Valentin Stoykov -Vasek Stodulka -Wesley Transue -Yoshiki Ohshima - -$Id$ diff --git a/servo/components/gfx/tests/support/dejavu-fonts-ttf-2.37/BUGS b/servo/components/gfx/tests/support/dejavu-fonts-ttf-2.37/BUGS deleted file mode 100644 index 43d1c940138f..000000000000 --- a/servo/components/gfx/tests/support/dejavu-fonts-ttf-2.37/BUGS +++ /dev/null @@ -1,3 +0,0 @@ -See http://dejavu.sourceforge.net/wiki/index.php/Bugs - -$Id$ diff --git a/servo/components/gfx/tests/support/dejavu-fonts-ttf-2.37/LICENSE b/servo/components/gfx/tests/support/dejavu-fonts-ttf-2.37/LICENSE deleted file mode 100644 index df52c1709bea..000000000000 --- a/servo/components/gfx/tests/support/dejavu-fonts-ttf-2.37/LICENSE +++ /dev/null @@ -1,187 +0,0 @@ -Fonts are (c) Bitstream (see below). DejaVu changes are in public domain. -Glyphs imported from Arev fonts are (c) Tavmjong Bah (see below) - - -Bitstream Vera Fonts Copyright ------------------------------- - -Copyright (c) 2003 by Bitstream, Inc. All Rights Reserved. Bitstream Vera is -a trademark of Bitstream, Inc. - -Permission is hereby granted, free of charge, to any person obtaining a copy -of the fonts accompanying this license ("Fonts") and associated -documentation files (the "Font Software"), to reproduce and distribute the -Font Software, including without limitation the rights to use, copy, merge, -publish, distribute, and/or sell copies of the Font Software, and to permit -persons to whom the Font Software is furnished to do so, subject to the -following conditions: - -The above copyright and trademark notices and this permission notice shall -be included in all copies of one or more of the Font Software typefaces. - -The Font Software may be modified, altered, or added to, and in particular -the designs of glyphs or characters in the Fonts may be modified and -additional glyphs or characters may be added to the Fonts, only if the fonts -are renamed to names not containing either the words "Bitstream" or the word -"Vera". - -This License becomes null and void to the extent applicable to Fonts or Font -Software that has been modified and is distributed under the "Bitstream -Vera" names. - -The Font Software may be sold as part of a larger software package but no -copy of one or more of the Font Software typefaces may be sold by itself. - -THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF COPYRIGHT, PATENT, -TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL BITSTREAM OR THE GNOME -FOUNDATION BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, INCLUDING -ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, -WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF -THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM OTHER DEALINGS IN THE -FONT SOFTWARE. - -Except as contained in this notice, the names of Gnome, the Gnome -Foundation, and Bitstream Inc., shall not be used in advertising or -otherwise to promote the sale, use or other dealings in this Font Software -without prior written authorization from the Gnome Foundation or Bitstream -Inc., respectively. For further information, contact: fonts at gnome dot -org. - -Arev Fonts Copyright ------------------------------- - -Copyright (c) 2006 by Tavmjong Bah. All Rights Reserved. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of the fonts accompanying this license ("Fonts") and -associated documentation files (the "Font Software"), to reproduce -and distribute the modifications to the Bitstream Vera Font Software, -including without limitation the rights to use, copy, merge, publish, -distribute, and/or sell copies of the Font Software, and to permit -persons to whom the Font Software is furnished to do so, subject to -the following conditions: - -The above copyright and trademark notices and this permission notice -shall be included in all copies of one or more of the Font Software -typefaces. - -The Font Software may be modified, altered, or added to, and in -particular the designs of glyphs or characters in the Fonts may be -modified and additional glyphs or characters may be added to the -Fonts, only if the fonts are renamed to names not containing either -the words "Tavmjong Bah" or the word "Arev". - -This License becomes null and void to the extent applicable to Fonts -or Font Software that has been modified and is distributed under the -"Tavmjong Bah Arev" names. - -The Font Software may be sold as part of a larger software package but -no copy of one or more of the Font Software typefaces may be sold by -itself. - -THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT -OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL -TAVMJONG BAH BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL -DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM -OTHER DEALINGS IN THE FONT SOFTWARE. - -Except as contained in this notice, the name of Tavmjong Bah shall not -be used in advertising or otherwise to promote the sale, use or other -dealings in this Font Software without prior written authorization -from Tavmjong Bah. For further information, contact: tavmjong @ free -. fr. - -TeX Gyre DJV Math ------------------ -Fonts are (c) Bitstream (see below). DejaVu changes are in public domain. - -Math extensions done by B. Jackowski, P. Strzelczyk and P. Pianowski -(on behalf of TeX users groups) are in public domain. - -Letters imported from Euler Fraktur from AMSfonts are (c) American -Mathematical Society (see below). -Bitstream Vera Fonts Copyright -Copyright (c) 2003 by Bitstream, Inc. All Rights Reserved. Bitstream Vera -is a trademark of Bitstream, Inc. - -Permission is hereby granted, free of charge, to any person obtaining a copy -of the fonts accompanying this license (“Fonts”) and associated -documentation -files (the “Font Software”), to reproduce and distribute the Font Software, -including without limitation the rights to use, copy, merge, publish, -distribute, -and/or sell copies of the Font Software, and to permit persons to whom -the Font Software is furnished to do so, subject to the following -conditions: - -The above copyright and trademark notices and this permission notice -shall be -included in all copies of one or more of the Font Software typefaces. - -The Font Software may be modified, altered, or added to, and in particular -the designs of glyphs or characters in the Fonts may be modified and -additional -glyphs or characters may be added to the Fonts, only if the fonts are -renamed -to names not containing either the words “Bitstream” or the word “Vera”. - -This License becomes null and void to the extent applicable to Fonts or -Font Software -that has been modified and is distributed under the “Bitstream Vera” -names. - -The Font Software may be sold as part of a larger software package but -no copy -of one or more of the Font Software typefaces may be sold by itself. - -THE FONT SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS -OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF COPYRIGHT, PATENT, -TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL BITSTREAM OR THE GNOME -FOUNDATION -BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, INCLUDING ANY GENERAL, -SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, WHETHER IN AN -ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF THE USE OR -INABILITY TO USE -THE FONT SOFTWARE OR FROM OTHER DEALINGS IN THE FONT SOFTWARE. -Except as contained in this notice, the names of GNOME, the GNOME -Foundation, -and Bitstream Inc., shall not be used in advertising or otherwise to promote -the sale, use or other dealings in this Font Software without prior written -authorization from the GNOME Foundation or Bitstream Inc., respectively. -For further information, contact: fonts at gnome dot org. - -AMSFonts (v. 2.2) copyright - -The PostScript Type 1 implementation of the AMSFonts produced by and -previously distributed by Blue Sky Research and Y&Y, Inc. are now freely -available for general use. This has been accomplished through the -cooperation -of a consortium of scientific publishers with Blue Sky Research and Y&Y. -Members of this consortium include: - -Elsevier Science IBM Corporation Society for Industrial and Applied -Mathematics (SIAM) Springer-Verlag American Mathematical Society (AMS) - -In order to assure the authenticity of these fonts, copyright will be -held by -the American Mathematical Society. This is not meant to restrict in any way -the legitimate use of the fonts, such as (but not limited to) electronic -distribution of documents containing these fonts, inclusion of these fonts -into other public domain or commercial font collections or computer -applications, use of the outline data to create derivative fonts and/or -faces, etc. However, the AMS does require that the AMS copyright notice be -removed from any derivative versions of the fonts which have been altered in -any way. In addition, to ensure the fidelity of TeX documents using Computer -Modern fonts, Professor Donald Knuth, creator of the Computer Modern faces, -has requested that any alterations which yield different font metrics be -given a different name. - -$Id$ diff --git a/servo/components/gfx/tests/support/dejavu-fonts-ttf-2.37/NEWS b/servo/components/gfx/tests/support/dejavu-fonts-ttf-2.37/NEWS deleted file mode 100644 index 2a2ee3708062..000000000000 --- a/servo/components/gfx/tests/support/dejavu-fonts-ttf-2.37/NEWS +++ /dev/null @@ -1,1455 +0,0 @@ -Changes from 2.35 to 2.36 - -* Fix issue with empty glyphs in condensed typefaces in the released source files. - -Changes from 2.35 to 2.36 - -* Math: added DejaVu Math Tex Gyre by B. Jackowski, P. Strzelczyk and - P. Pianowski (on behalf of TeX users groups) -* Sans: removed dot of U+06BA in all forms -* Sans: fixed position of three dots of U+06BD in init and medi forms (by - Denis Jacquerye) -* Sans: corrected direction of contours in U+05E7 (by Lior Halphon) -* Sans: added U+1F643 (by Olleg Samoylov) -* Serif: moved up U+0360-0361 (by Gee Fung Sit 薛至峰) -* Serif: increased spacing of Roman numerals U+2161-2163, U+2165-2168, - U+216A-216B (by Gee Fung Sit 薛至峰) -* Serif: fixed anchor position of U+00E6 (by Gee Fung Sit 薛至峰) -* Sans: fixed vertical position of U+20BA (by Gee Fung Sit 薛至峰) -* Sans, Serif: fixed glyph height of Block Elements (by Gee Fung Sit 薛至峰) -* Sans, Serif: added U+A698-A699 (by Gee Fung Sit 薛至峰) -* Sans, Mono, Serif: added U+037F (by Gee Fung Sit 薛至峰) -* Mono: added U+0376-0377, U+037B-037D (by Gee Fung Sit 薛至峰) -* Serif: removed duplicate point from U+1D05 (by Gee Fung Sit 薛至峰) -* Mono: added U+20BA, U+20BD (by Gee Fung Sit 薛至峰) -* Sans: added moon symbols U+1F311-1F318 (by Ben Laenen) - -Changes from 2.34 to 2.35 - -* Sans, SansMono, Serif: added U+0E3F, U+A7F8-U+A7F9 (by Gee Fung Sit 薛至峰) -* Sans, SansMono, Serif: moved inverted marks U+00A1, U+00BF, U+2E18 to x-height - and added 'case' feature using original glyphs+hints (by Gee Fung Sit 薛至峰) -* Sans, SansMono, Serif: fixed glyph heights in Box Drawing block (by Gee Fung - Sit 薛至峰) -* SansMono, Serif: adjusted U+016E to prevent cut-off (by Gee Fung Sit 薛至峰) -* Sans: added U+269E-U+269F (by Lars Næsbye Christensen) -* Sans: added U+06C7-U+06C8, U+06CB, U+06D0 and their presentation forms - U+FBD7-U+FBD8, U+FBDB-U+FBDC, U+FBDE-U+FBDF, U+FBE4-U+FBE7 (by MihailJP) -* Sans: added isolated, initial and stretched forms in the Arabic Mathematical - Alphabetic Symbols block, U+1EE00 et seq. (by Gee Fung Sit 薛至峰) -* Sans: restored GSUB tables for Hebrew (by Gee Fung Sit 薛至峰) -* Sans: fixed U+1D301-U+1D303 (bug 73532) (by Gee Fung Sit 薛至峰) -* Sans: fixed instructions for U+0394, U+039B in Bold (bug 16442) (by Gee Fung - Sit 薛至峰) -* Sans: minor improvements/fixes to U+07D4, U+203D, U+20A6, U+20BA, U+2E18, - U+A782-U+A783 (by Gee Fung Sit 薛至峰) -* Sans: moved U+2E1F to correct code point, was off by one (by Gee Fung Sit - 薛至峰) -* SansExtraLight: added U+0184-U+0185, U+019B, U+01B7-U+01B9, U+01EE-U+01EF, - U+0292, U+0298, U+0E3F, U+04E0-U+04E1, U+0516-U+0519 (by Gee Fung Sit 薛至峰) -* SansMono: added U+203F, U+2150-U+2151, U+2189, U+220E, U+2210, U+2223, - U+228D-U+228E, U+2293-U+2294, U+22B2-U+22B5, U+22B8, U+22C2-U+22C3, - U+22CE-U+22D1, U+27DC, U+27EA-U+27EB, U+27F5-U+27F7, U+2987-U+2988, - U+2997-U+2998, U+2A00 (by Gee Fung Sit 薛至峰) -* SansMono: minor improvements/fixes to U+018C and U+018D, U+026F-U+0270 (by - Gee Fung Sit 薛至峰) -* SansMono: fixed glyph heights in Block Elements block (bug 14316) (by Gee - Fung Sit 薛至峰) -* Serif: replaced inverted breve on U+0202, U+0206, U+020A, U+020E, U+0212, - U+0216 with its case form to prevent cut-off (by Gee Fung Sit 薛至峰) -* Serif: redesigned/redrawn U+01E5, U+025E, U+0262, U+0277-U+0278, - U+029A-U+029B (by Gee Fung Sit 薛至峰) -* Serif: minor improvements/fixes to U+00DF, U+017B, U+01E4, U+0265, - U+026F-U+0270, U+0280-U+0281, U+0294-U+0297, U+029F, U+02A1-U+02A2, U+03FB, - U+1D0C, U+20A6, U+20B8, U+A731 (by Gee Fung Sit 薛至峰) -* Serif: added stylistic alternatives for U+0110-U+0111, U+01E4-U+01E5 (by Gee - Fung Sit 薛至峰) -* Serif: added or adjusted anchors for U+0294, U+0256, U+041D (by Denis - Jacquerye) -* Sans, Serif: added OpenType MATH table (by Frédéric Wang) -* Sans, Serif: added displaystyle math operators (by Frédéric Wang) -* Serif: added italic mathematical alphanumeric characterd (by Frédéric Wang) -* Serif: added construction for stretchy radical symbol (by Frédéric Wang) -* Serif: added stylistic ssty variants for prime symbols -* Sans, Serif: fixed incorrect glyph for U+22C4 (by Gee Fung Sit 薛至峰) -* SansMono: added U+22C4 (by Gee Fung Sit 薛至峰) -* SansMono: added to U+2336, U+233F-U+2340, U+2345-U+2346, U+234A, - U+234E-U+234F, U+2351, U+2355-U+2356, U+235D, U+2361-U+2362, U+2366-U+2367, - U+236A, U+2371-U+2372 (by Sami Tarazi) -* Serif: added U+20BA (by Gee Fung Sit 薛至峰) -* Sans, Serif: added U+20BD (by Gee Fung Sit 薛至峰) - -Changes from 2.33 to 2.34 - -* Sans, SansMono, Serif: unlinked references of U+2596 for bug 50848 - (by Denis Jacquerye) -* Sans, SansMono, Serif: added U+A7AA (by Denis Jacquerye) -* Sans, SansMono, Serif: added U+2A6A, U+2A6B, U+2E1F based on U+223B - (by Denis Jacquerye) -* Sans, Serif: removed superfluous ligature definitions for ffl und ffi - (bug 55363) (by Gee Fung Sit 薛至峰) -* Sans, Serif: swapped glyphs for U+25D2 and U+25D3 (bug 55197) - (by Gee Fung Sit 薛至峰) -* Sans, Serif: added U+A740, U+A741 (by Denis Jacquerye) -* Sans: added U+20BA Turkish Lira sign (by Denis Jacquerye) -* Sans: replaced Georgian Asomtavruli U+10A0-U+10C5 and Mkhedruli U+10D0-U+10FC - with new version (by Besarion Gugushvili) -* Sans: added Georgian Nuskhuri U+2D00-U+U+2D25 (by Besarion Gugushvili) -* Sans: added Private Use Area glyphs for Georgian U+F400-U+F441 - (by Besarion Gugushvili) -* Sans: tweaked U+0250, U+0254 (by Denis Jacquerye) -* Sans: adjusted hinting of U+032C-U+032D, avoiding problem on some platforms - (by Denis Jacquerye) -* Sans: added U+A7A0-U+A7A9, pre-1921 Latvian letters with oblique stroke - (by Denis Jacquerye) -* Sans: added anchors to U+2C6D (by Denis Jacquerye) -* Sans: added cedilla anchor to some Latin characters (by Denis Jacquerye) -* Sans: added ogonek anchor to A, E, O, U, Y (by Denis Jacquerye) -* Sans: adjusted ogonek reference in U+0172, U+01EA, U+01EB - (by Denis Jacquerye) -* Sans: added anchors to U+0104, U+0105 (by Denis Jacquerye) -* Sans: added U+1F600, U+1F611, U+1F615, U+1F617, U+1F619, U+1F61B, U+1F61F, - U+1F626-U+1F627, U+1F62E-U+1F62F, U+1F634 (by Gee Fung Sit 薛至峰) -* Sans: replaced U+27A1 with mirror image of U+2B05 for consistency - (by Gee Fung Sit 薛至峰) -* Sans: copied hints from U+14A3, U+14A7 to U+2142-U+2143 - (by Gee Fung Sit 薛至峰) -* Sans: added Lisu block (by Gee Fung Sit 薛至峰) -* Sans: typographical improvements to U+0166-U+0167, U+02A6, U+02AA - (by Gee Fung Sit 薛至峰) -* Sans: slightly change hinting of "2" to fix bug 37395 (by Ben Laenen) -* Sans: fixed U+1444 which had wrong top dot that shouldn't be there - (by Denis Jacquerye) -* Sans: added anchors for diacritics to U+01B7, U+01B8, U+01B9, U+0292 - (by Denis Jacquerye) -* Sans: added U+01B7, U+01B8 to context for case diacritics above -* SansMono: fixed U+0574 (by Ruben Hakobian) -* SansMono: added U+2016, U+27C2 (by Yoshiki Ohshima) -* SansMono: added U+02CE, U+02CF (by Denis Jacquerye) -* SansMono: added U+2148, U+27E6-U+27E7, U+2B05-U+2B0D, U+1D55A - (by Gee Fung Sit 薛至峰) -* Serif: added U+02BA, U+02C2-U+02C5, U+02CA-U+02CB, U+02D7, U+02F3, U+02F7, - U+046C-U+046D, U+0476-U+0477, U+1D7C-U+1D7F, U+20B8, U+2132, U+214E, U+2C7B - to Serif (by Gee Fung Sit 薛至峰) -* Serif: typographic improvements to U+0194, U+01B1, U+0263, U+028A, U+02A6, - U+02A8, U+02AA, U+02E0, U+03DC, U+1D3B, U+1D7B (by Gee Fung Sit 薛至峰) -* Serif: added small cap versions of q, x (in italic styles), delta, theta, xi, - sigma, phi, omega, not wired in yet (by Gee Fung Sit 薛至峰) -* Serif: added anchors to U+0234-U+0236 (by Gee Fung Sit 薛至峰) -* Serif: added U+02EC, U+02EF, U+02F0, U+0360 (by Denis Jacquerye) - -Changes from 2.32 to 2.33 - -* added Old Italic block to Sans (by MaEr) -* added U+051E, U+051F to Sans (by MaEr) -* added U+01BA, U+0372-U+0373, U+0376-U+0377, U+03CF, U+1D00-U+1D01, - U+1D03-U+1D07, U+1D0A-U+1D13, U+1D15, U+1D18-U+1D1C, U+1D20-U+1D2B, - U+1D2F, U+1D3D, U+1D5C-U+1D61, U+1D66-U+1D6B, U+1DB8, U+1E9C-U+1E9D, - U+1EFA-U+1EFB, U+2C60-U+2C61, U+2C63, U+A726-U+A73C, U+A73E-U+A73F, - U+A746-U+A747, U+A74A-U+A74B, U+A74E+U+A74F, U+A768-U+A769, U+A77B-U+A77C, - U+A780-U+A787, U+A790-U+A791, U+A7FA-U+A7FF to Serif (by Gee Fung Sit 薛至峰) -* added alternate forms to U+014A and U+01B7 in Serif (by Gee Fung Sit 薛至峰) -* typographical improvements to U+0166-U+0167, U+0197, U+01B5-U+01B6, U+01BB, - U+0222-U+0223, U+023D, U+0250-U+0252, U+026E, U+0274, U+028F, U+029F, - U+02A3-U+02A5, U+02AB, U+03FE-U+03FF, U+1D02, U+1D14, U+1D1D-U+1D1F, U+1D3B, - U+1D43-U+1D46, U+1D59, U+1D9B, U+2C71, U+2C73 in Serif (by Gee Fung Sit 薛至峰) -* fixed bugs #31762 and #34700 plus other small fixes (wrong direction, - duplicate points, etc.) for Sans and Serif (by Gee Fung Sit 薛至峰) -* added U+204B to Mono (by Gee Fung Sit 薛至峰) -* added U+26E2 to Sans (by Gee Fung Sit 薛至峰) -* added Playing Cards block (U+1F0A0-U+1F0DF) to Sans (by Gee Fung Sit 薛至峰) -* emoticons in Sans: replace U+2639-U+263B with better versions, add - U+1F601-U+1F610, U+1F612-U+1F614, U+1F616, U+1F618, U+1F61A, U+1F61C-U+1F61E, - U+1F620-U+1F624, U+1F625, U+1F628-U+1F62B, U+1F62D, U+1F630-U+1F633, - U+1F635-U+1F640 (by Ben Laenen and Denis Jacquerye) -* added U+A78E, U+A790-U+A791 to Sans and Mono (by Denis Jacquerye) -* added U+A7FA to Sans (by Denis Jacquerye) -* subscripts: added U+2095-U+209C to Sans, Serif and Mono, adjusted - U+1D49-U+1D4A in Sans and Mono (by Denis Jacquerye) -* added U+0243 to Mono (by Denis Jacquerye) -* adjusted U+0307 to match dot of i, replaced dotaccent U+02D9 with U+0307 in -most dependencies in Sans (by Denis Jacquerye) -* adjusted anchors of f and added them to long s in Sans (by Denis Jacquerye) -* added anchors to precomposed dependencies of D and d (by Denis Jacquerye) -* added debug glyphs U+F002 and U+F003 which will show current point size (by - Ben Laenen) -* use correct version for Serbian italic be (by Eugeniy Meshcheryakov) -* added pictograms U+1F42D-U+1F42E, U+1F431, U+1F435 (by Denis Jacquerye) -* improved Hebrew in Sans (by Lior Halphon) -* improved Armenian in Sans, and added Armenian in Serif and Mono (by Rouben - Hakobian (Tarumian), Aleksey Chalabyan and Norayr Chilingarian) -* remove "locl" feature for Romanian for S/T/s/t with cedilla/comma accent (by - Ben Laenen) -* replace wrong "dflt" script tag in Mono with "DFLT" (by Ben Laenen) - -Changes from 2.31 to 2.32 - -* added to Sans: Latin small letter p with stroke (U+1D7D), Latin capital - letter p with stroke through descender (U+A750), Latin small letter p with - stroke through descender (U+A751), Latin capital letter thorn with stroke - (U+A764), Latin small letter thorn with stroke (U+A765), Latin capital letter - thorn with stroke through descender (U+A766), Latin small letter thorn with - stroke through descender (U+A767), Latin capital letter q with stroke through - descender (U+A756), Latin small letter q with stroke through descender - (U+A757), Latin capital letter p with flourish (U+A752), Latin small letter p - with flourish (U+A753) (by Ben Laenen) -* add new Indian rupee symbol (U+20B9) to Sans, Serif and Mono (although - standardization in Unicode not complete yet, UTC did assign this code point) - (by Ben Laenen) -* Sans: adjusted U+0E3F, U+20AB, U+20AD-U+20AE, U+20B1, U+20B5, U+20B8 to have - them take up the same width as digits (by Gee Fung Sit 薛至峰) -* added U+23E8 to Sans (by Thomas Henlich) -* fixed numerous bugs (#22579, #28189, #28977, N'Ko in Windows, fixed U+FB4F, - anchors for U+0332-U+0333, made extensions in Misc. Technical connect, and - other small fixes) (by Gee Fung Sit 薛至峰) -* added looptail g as stylistic variant to Serif (by Gee Fung Sit 薛至峰) -* added the remaining precomposed characters in Latin Extended Additional in - Serif (by Gee Fung Sit 薛至峰) -* added Georgian Mkhedruli (U+10D0-U+10FC) to Sans ExtraLight (by Besarion - Gugushvili) -* fix spacing in hinting of U+042E (Ю) in Mono (by Ben Laenen) -* replaced U+2650 and minor changes to U+2640-U+2642, U+2699, U+26A2-U+26A5, - U+26B2-U+26B5, U+26B8 in Sans (by Gee Fung Sit 薛至峰) -* added U+1E9C-U+1E9D, U+1EFA-U+1EFB, U+2028-U+2029, U+20B8, U+2150-U+2152, - U+2189, U+26C0-U+26C3, U+A722-U+A725, U+1F030-U+1F093 to Sans (by Gee Fung - Sit 薛至峰) -* added U+1E9C-U+1E9E, U+1EFA-U+1EFB, U+2028-U+2029, U+20B8, U+2181-U+2182, - U+2185 U+A722-U+A725, to Sans ExtraLight (by Gee Fung Sit 薛至峰) -* added U+20B8, U+22A2-U+22A5, U+A722-U+A725 to Mono (by Gee Fung Sit 薛至峰) -* added U+02CD, U+01BF, U+01F7, U+0222-U+0223, U+0243-U+0244, U+0246-U+024F, - U+2150-U+2152, U+2189, U+239B-U+23AD and U+A73D to Serif (by Gee Fung Sit - 薛至峰) - -Changes from 2.30 to 2.31 - -* fixed bug where Serif Condensed Italic wouldn't get proper subfamily tags (by - Ben Laenen) -* added math operators U+2234-U+2237 to Mono (by Ben Laenen) -* removed buggy instructions of U+032D (by Eugeniy Meshcheryakov) -* added U+2C70, U+2C7E, U+2C7F to Sans and Sans Mono (by Denis Jacquerye) -* added U+2C7D to Sans Mono (by Denis Jacquerye) -* added U+2C6D, U+2C70-2C73, U+2C7E-2C7F to Serif (by Denis Jacquerye) -* added extremas to alpha U+03B1 in Serif-Italic (by Denis Jacquerye) -* added U+4A4, U+4A5 to Mono (by Andrey V. Panov) -* added Arabic letters U+0657, U+0670, U+0688-U+0690, U+0693-U+0694, - U+0696-U+0697, U+0699-U+06A0, U+06A2-U+06A3, U+06A5, U+06A7-U+06A8, - U+06AA-U+06AE, U+06B0-U+06B4, U+06B6-U+06B9, U+06BB-U+06BE and their - contextual forms to Sans (by MihailJP) -* added U+A78D LATIN CAPITAL LETTER TURNED H for coming Unicode 6.0 (by Denis - Jacquerye) - -Changes from 2.29 to 2.30 - -* added U+0462-U+0463 to Mono (by Denis Jacquerye) -* corrected U+1E53 in Serif (by Gee Fung Sit) -* added U+1E4C-U+1E4D to Mono and Serif (by Gee Fung Sit) -* added U+1E78-U+1E79 to Mono (by Gee Fung Sit) -* fixed missing diacritics in Latin Extended Additional in Sans ExtraLight - (moved stacked diacritics out of PUA in the process) (by Gee Fung Sit) -* fixed anchors on U+1E78 in Serif (by Gee Fung Sit) -* added U+1DC4-U+1DC9 to Serif (by Denis Jacquerye) -* renamed above-mark to above-mark in Serif-Italic (by Denis Jacquerye) -* added U+1DC4-U+1DC9 to context class for dotless substitution (by Denis - Jacquerye) -* changed Doubleacute to Doublegrave in Sans ExtraLight (by Gee Fung Sit) -* removed redundant reference in U+01FB in Sans Oblique (by Gee Fung Sit) -* added U+A726-U+A727 to Mono (Denis Jacquerye) -* changed U+04BE and U+04BF according to recommedations of Sasha Ankwab in Sans - (by Andrey V. Panov) -* remove "Symbol Charset" from set of codepages in Sans (by Eugeniy - Meshcheryakov) - -Changes from 2.28 to 2.29 - -* modified U+10FB in Sans to be a mirror image of U+2056, since U+10FB is not - Georgian-specific (by Roozbeh Pournader) -* added U+2B1F, U+2B24, U+2B53, U+2B54 in Sans (by Roozbeh Pournader) -* fixed TUR opentype language tag to TRK in Serif (bug 19825) (by Ben Laenen) -* early implementation of Abkhaz letter U+0524-U+0525 in Sans - (by Michael Everson and abysta) -* flipped U+1D538 in Sans (by Gee Fung Sit) -* added U+26B3-U+26B8, U+1D7D8-U+1D7E1 in Sans (by Gee Fung Sit) -* corrected U+1D7A9 in Sans Bold Oblique (by Gee Fung Sit) -* Fixed U+0649 to be dual-joining in Sans Mono (by Roozbeh Pournader) -* Remove unnecessary 'isol' feature from Sans Mono (by Roozbeh Pournader) -* Remove 'cmap' mappings for U+066E, U+066F, U+067C, U+067D, U+0681, U+0682, - U+0685, U+0692, U+06A1, U+06B5, U+06BA, U+06C6, U+06CE, and U+06D5 - in Sans Mono (bug 20323) (by Roozbeh Pournader) -* add half brackets (U+2E22 - U+2E25, by Steve Tinney) - -Changes from 2.27 to 2.28 - -* added U+A789, U+A78A in Sans and Sans Mono (by Denis Jacquerye) -* modified U+02D6, U+02D7, U+02EE in Sans and Sans Mono (by Denis Jacquerye) -* added U+1E9E (German capital ß) to Sans and Serif (by Denis Jacquerye) -* adjusted width of U+01B7-U+01B9 in Serif Italic (by Denis Jacquerye) -* modified U+021C, U+021D in Sans (by Denis Jacquerye) -* added U+021C, U+021D in Mono (by Denis Jacquerye) -* added U+F428 (Georgian Nuskhuri "f") in private use area (by Besarion - Gugushvili) -* updated Georgian mkhedruli (U+10D0-U+10FA) with new version (by Besarion - Gugushvili) -* updated Georgian asomtavruli (U+10A0-U+10C5) with new version (by Besarion - Gugushvili) -* added Georgian nuskhuri (U+2D00-U+2D25) (by Besarion Gugushvili) -* added Georgian mtavruli in private use area (U+F400-U+F426) (by Besarion - Gugushvili) -* added mark anchors above to Cyrillic U+0430-U+0438, U+043A-U+044F, - U+0454-U+0455 in Mono (by Ben Laenen) -* modified/moved up U+0318-U+0319, U+031C-U+031F, U+0329-U+032A, U+032C-U+032D, - U+0339-U+033B, U+0348 and U+0353 in Sans to prevent cut-off (by Gee Fung Sit) -* added U+035A to Sans (by Gee Fung Sit) -* updated fontconfig files (by Nicolas Mailhot) -* added U+2032-2037 to Mono (by Denis Jacquerye) -* added Ogham to Sans ExtraLight (by Gee Fung Sit) -* added U+2C6F, U+2C79, U+2C7C-2C7D to Mono (by Gee Fung Sit) -* added U+210F to Serif and Sans ExtraLight (by Gee Fung Sit) -* changed U+210F to a more common glyph in Sans and Mono (by Gee Fung Sit) - -Changes from 2.26 to 2.27 - -* added some of Michael Everson's new Cyrillic glyphs to Sans (by Wesley - Transue) -* removed blank glyph at U+05EF from Sans Bold Oblique (by Gee Fung Sit) -* small adjustments to existing tone bars in Sans and Mono (by Gee Fung Sit) -* added U+0372-U+0373, U+0376-U+0377, U+03CF, U+A668-U+A66E, U+A708-U+A711, - U+A71B-U+A71F to Sans (by Gee Fung Sit) -* copied U+02E5-U+02E9 over from Sans to fix inconsistencies in Serif (by Gee - Fung Sit) -* added U+021C-U+021D, U+0370-U+0371, U+037B-U+037D, U+0470-U+0471, - U+0510-U+0515, U+051A-U+051D, U+1E9F, U+2C64, U+2C6E-U+2C6F, U+2C79, - U+2C7C-U+2C7D, U+A644-U+A647, U+A650-U+A651, U+A654-U+A657, U+A708-U+A716, - U+A71B-U+A71F to Serif (by Gee Fung Sit) -* added U+A708-U+A716, U+A71B-U+A71F to Mono (by Gee Fung Sit) -* added anchors to U+017F (ſ) and fixed U+1E9B (ẛ) in Serif (by Gee Fung Sit) -* made U+0325 smaller in Sans Bold and Serif to match Sans Book (by Gee Fung - Sit) -* fixes to U+02F3 (moved up), U+228F-U+2294 (more square-like) and - U+22CE-U+22CF (stroke width) in Sans (by Gee Fung Sit) -* replaced U+2202 ∂ (Sans and Mono) and U+221D ∝, U+221E ∞ (Sans) with glyphs - from Arev (with small changes) (by Gee Fung Sit) -* added U+22B0-U+22B1, U+22C7, U+22D0-U+22D5 from Arev to Sans to complete the - block (by Gee Fung Sit) -* added U+0514-U+0515 to Sans ExtraLight (by Gee Fung Sit) -* skewed U+A78C in all Oblique/Italic fonts (by Gee Fung Sit) -* moved U+2215 to U+2044 in Sans and Serif and replaced U+2215 with reference - to U+002F in all fonts (by Gee Fung Sit) -* added U+2C6E to Mono (by Denis Jacquerye) -* added U+A782 and U+A783 in Sans (by Wesley Transue) -* added U+0244, U+024C-024D, U+2C64 in Sans Mono (by Denis Jacquerye) -* modified U+01AE in Sans Mono (by Denis Jacquerye) -* added U+2C7A to all fonts (by Gee Fung Sit) -* italicized/small changes to U+2C76 in Serif (Bold) Italic (by Gee Fung Sit) -* improved outlines of U+2C68, U+2C6A, U+2C6C in Serif (Bold) Italic (by Gee - Fung Sit) -* rounded U+2C77 at the bottom in Serif (by Gee Fung Sit) -* added joining behavior for tone letters (U+02E5-U+02E9) in Sans (bug #15669) - (by Gee Fung Sit) -* fixed outline of y.alt in Sans Regular (by Denis Jacquerye) -* changed references of U+1D5A8, U+1D5C5, U+1D5DC, U+1D5F9, U+1D610, U+1D62D, - U+1D644 and U+1D661 to stylistic alternates to have a better distinction (by - Gee Fung Sit) -* hinted I.alt in Sans Regular (by Gee Fung Sit) -* added U+0487, completing Cyrillic block (by Gee Fung Sit) -* extended the bar of U+0463 to the right and moved the anchor (by Gee Fung - Sit) -* added anchors to glyphs in Cyrillic block (by Gee Fung Sit) -* added (preliminary) hints to tone letter forms (U+02E5.5, U+02E9.1, stem) in - Sans Book (by Gee Fung Sit) - -Changes from 2.25 to 2.26 - -- added glyphs for Cyrillic-B to Sans (by Wesley Transue) -- added U+0370-U+0371 to Sans (by Wesley Transue) -- added U+019C, U+01A2-U+01A3, U+01A6, U+01E4-U+01E5, U+024C-U+024D, U+0285, - U+0290, U+02A0, U+0370-U+0371, U+03F1, U+03FC to Sans ExtraLight (by Wesley - Transue) -- added U+20A0-U+20A5, U+20A7-U+20B3, U+2105, U+210D, U+210F, U+2115, U+2117, - U+2119-U+211A, U+211D, U+2124, U+212E, U+2200-U+2204 to Mono (by Heikki - Lindroos) -- added U+01BA and U+01BF to Mono (by Heikki Lindroos) -- merged OpenType "aalt" feature in Latin in Sans (by Denis Jacquerye) -- added alternative shape for y in Sans (by Denis Jacquerye) -- added saltillo (U+A78B-U+A78C) to all faces (by James Cloos) -- changed U+047C-U+047D to references instead of outlines in Sans (by Wesley - Transue) -- added Latin letter tresillo U+A72A-U+A72B to Sans (by Wesley Transue) -- added U+A734-U+A737 to Sans (by Wesley Transue) -- added U+2053 to Serif and fixed it bug:9425 in Sans (by Gee Fung Sit) -- removed problematic hints for U+0423 bug:10025 (by Gee Fung Sit) -- added U+27C5-U+27C6 bug:10255 to all faces (by Gee Fung Sit) -- fixed width of U+2016 in Sans Oblique (by Gee Fung Sit) -- added U+2016, U+2032-U+2038, U+2042, U+2045-U+2046, U+204B-U+204F, - U+2051-U+2052, U+2057 to Serif (by Gee Fung Sit) -- made U+2140 bigger to match other n-ary operators (by Gee Fung Sit) -- added U+0606-U+0607, U+0609-U+060A to Sans (by Gee Fung Sit) -- added U+221B-U+221C to Mono (by Gee Fung Sit) -- small adjustments to U+221B-U+221C in Sans and Serif (by Gee Fung Sit) -- update U+04B4-U+04B5 in Serif (by Andrey V. Panov) -- increased max-storage value from maxp table to 153 (by Andrey V. Panov) -- added U+0472-U+0473, U+0510-U+0511, U+051A-U+051D, U+0606-U+0607, - U+0609-U+060A, U+1E26-U+1E27, U+1E54-U+1E55, U+1E7C-U+1E7D, U+1E8C-U+1E8D, - U+1E90-U+1E91, U+1E97-U+1E99, U+1E9F, U+1EAC-U+1EAD, U+1EB6-U+1EB7, - U+1EC6-U+1EC7, U+1ED8-U+1EDD, U+1EE0-U+1EE3, U+1EE8-U+1EEB, U+1EEE-U+1EF1 to - Mono (by Gee Fung Sit) -- added locl rules for S/T cedilla for Romanian and Moldavian so they get - rendered as S/T with comma accent (see Redhat bug #455981) (by Ben Laenen) -- removed ligature rule from Armenian U+0587 bug:16113 (by Gee Fung Sit) - -Changes from 2.24 to 2.25 - -- moved/added U+2E18 (by Gee Fung Sit) -- added empty glyph for U+2064 in Sans and Serif (by Gee Fung Sit) -- added U+22CE-U+22CF to Sans (by Gee Fung Sit) -- Sans Oblique and Bold Oblique, Serif: reverted digits hinting instructions back to before revision 1590, which fixed mistaken debian bug #471024. This fixes Debian bug #411308. The original bug was in freetype not in the fonts (by Denis Jacquerye) -- added U+A726-U+A729, U+A730-U+A733, U+A738-U+A73F, U+A746-U+A74B, U+A74E-U+A74F, U+A780-U+A781, U+A7FB-U+A7FF to Sans (by Gee Fung Sit) -- added Macedonian italic glyph shape for U+0453 in Serif (by Ben Laenen) -- changed descenders in U+0446, U+0449, U+0497, U+04A3, U+04AD (by Andrey V. Panov) -- updated main SFD files to SplineFontDB 3.0 (Denis Jacquerye and Gee Fung Sit) -- moved U+0561 2 up since it wasn't aligned with the baseline well (by Ben Laenen) -- added U+2E2E to Sans (by Gee Fung Sit) -- replaced U+2699 with simpler version in Sans (by Gee Fung Sit) -- added a lot of hinting instructions to Latin Extended B, Greek and Coptic glyphs Sans Book (by Wesley Transue) -- differentiated U+2219 from U+22C5 and adjusted affected references in Sans and Mono (by Gee Fung Sit) -- made Hebrew narrower in Sans Bold and Sans Bold Oblique (by Denis Jacquerye) -- added Kurdish and Chuvash letters from Unicode 5.1 Cyrillic Extended block (by Wesley Transue) -- added U+1E9F, U+A644-U+A647, U+A64C-U+A64D, U+A650-U+A651, U+A654-U+A655, U+A712U+A716 to Sans (by Gee Fung Sit) -- added several glyphs to Sans ExtraLight (by Gee Fung Sit) -- added hinting instructions to U+046A-U+046B, U+0508-U+0509, U+050B, U+0512-U+0513 in Sans Book (by Wesley Transue) -- corrected width of U+027E in Sans Book (by Gee Fung Sit) -- added U+2C79, U+2C7B-U+2C7D to Sans (by Gee Fung Sit) -- added a bunch of glyphs+small corrections to Sans Light (by Gee Fung Sit) -- added U+0496, U+0497, U+04B0, U+04B1 (by Andrey V. Panov) -- updated U+0493, U+049B, U+04B3, U+04B7, U+04F7 (by Andrey V. Panov) -- further improvements in extended Cyrillic (by Andrey V. Panov) - -Changes from 2.23 to 2.24 - -- instructions for U+05C0 ׀, U+05C3 ׃, U+05F3 ׳, and U+05F4 ״ in DejaVu - Sans. (by Wesley Transue) -- instructions for U+2116 in Sans (by Andrey V. Panov) -- Unicode 5.1 update: moved U+F208 to U+2C6D, U+F25F to U+2C71, added - U+2C6E-U+2C6F, U+2C72-U+2C73, updated outline of U+2C71 in Sans. (by - Denis Jacquerye) -- updated and instructed U+0401 in Sans (by Andrey V. Panov) -- fixed the bug in Sans faces where U+02EC ˬ faced the wrong direction. - Also, added a few more glyph instructions. (by Wesley Transue) -- removed OS2Sub and OS2Strike that weren't intentional in Sans - ExtraLight. (by Denis Jacquerye) -- updated instructions for U+401, U+44F in Serif Book. (by Andrey V. - Panov) -- instructions for U+02C4 ˄, U+02C5 ˅, U+03D8 Ϙ, U+03D9 ϙ, U+0494 Ҕ, and - U+0495 ҕ in Sans Book. (by Wesley Transue) -- instructions for U+01A6 Ʀ, U+0238 ȸ, U+0239 ȹ, U+02EC ˬ, and U+05C6 ׆ - in Sans Book. (by Wesley Transue) -- DejaVuSans.sfd DejaVuSerif.sfd: updated instructions for U+447 and - U+451 using code generated with xgridfit (by Andrey V. Panov) -- instructions for a few glyphs in the Latin Extended-B Block, Greek - Block, Cyrillic Block, and N'Ko block. (by Wesley Transue) -- updated sfdnormalize.pl, and SFD files to new SFD format with empty - lines. (by Denis Jacquerye) - -Changes from 2.22 to 2.23 - -- fixed bug which made Condensed fonts appear instead of normal width ones -- added U+20DB, U+20DC, and U+20E1 to Sans (by Roozbeh Pournader) -- added hinting instructions to U+01A7, U+01AA-U+01AC, U+01AE-U+01AF, - U+01BC-U+01BD, U+01BF, U+01F7, U+0277, U+027F, U+0285-U+0286, U+0297, U+02AF, - U+02B4-U+02B5, U+02BD, U+030D, U+0311, U+0329, U+04A0-U+04A1 in Sans Book (by - Wesley Transue) -- modified hinting instructions of U+04A2 in Sans Book (by Wesley Transue) -- added hinting instructions to U+237D, U+2423 in Mono Book and Mono Bold (by - Wesley Transue) -- added mathematical alphanumeric symbols to all styles (by Max Berger) -- added Unicode 5.1 U+2E18 as U+2E18.u51 (not yet usable) to Sans (by Roozbeh - Pournader) -- dereferenced all glyphs with mixed references and outlines (by Denis - Jacquerye) -- removed non-zero width from U+0344 in Sans (by Denis Jacquerye) - -Changes from 2.21 to 2.22 - -- directory structure has changed, we now use the Makefile -- modified Armenian U+0565 in Sans (by Սահակ Պետրոսյան) -- added double struck letters and numbers U+2102, U+210D, U+2115, - U+2119-U+211A, U+211D, U+2124, U+213C-U+2140, U+2145-U+2149, U+1D538-U+1D539, - U+1D53B-U+1D53E, U+1D540-U+1D544, U+1D546, U+1D54A-U+1D550, U+1D552-U+1D56B, - U+1D7D8-U+1D7E1 to Serif (by Stephen Hartke) -- added letterlike symbols U+2103, U+2109, U+2127, U+214B, U+2141-U+2144 to - Serif (by Ben Laenen) -- fixed outline direction of U+2143 in Sans Bold/Bold Oblique (by Ben Laenen) -- added arrow set in Serif: arrows: U+2194-U+21FF; dingbats: U+27A1; - supplemental arrows A: U+27F0-U+27FF; supplemental arrows B: U+2900-U+2975, - U+297A; miscellaneous symbols and arrows: U+2B00-U+2B11 (by Ben Laenen) -- added U+0180, U+01DE, U+01E0-01E1, U+022A, U+022C, U+0230, U+1E08-U+1E09, - U+1E10-U+1E11, U+1EB0-U+1EB1 to Mono (by Denis Jacquerye) -- adjusted U+01D5, U+01D7, U+01D9, U+1DB in Mono (by Denis Jacquerye) -- added Ogham in Sans (by Wesley Transue) -- added Yijing Hexagram Symbols in Sans (by Wesley Transue) -- hinting instructions added to Cyrillic U+0460, U+04A6-U+04A7, U+04AC-U+04AD, - U+04C7-U+04C8, U+04F6-U+04F7, U+04FA-U+04FB, U+050C-U+050D in Sans Book (by - Wesley Transue) -- adjusted Cyrillic letters U+042A, U+044A, U+044C, U+0459-U+045B, U+0462, - U+048C-U+048D in Serif (by Andrey V. Panov) -- hinting instructions added to Lao U+0EB7 in Sans (by Wesley Transue) -- added Roman numerals and Claudian letter U+2160-U+2184 in Serif (by Ben - Laenen) -- added U+FFF9-U+FFFD to Sans, Serif and Mono (by Lars Næsbye Christensen) -- added mathematical symbols to Serif: U+2200, U+2203-U+2204, U+2213-U+2214, - U+2217-U+2218, U+2223-U+2226, U+2250-U+2255, U+2295-U+22AF, U+22C5 (by Ben - Laenen) -- modified bullet symbol U+2219 in Serif (by Ben Laenen) - -Changes from 2.20 to 2.21 - -- added U+FE20-U+FE23 (half diacritics) to Sans (by Denis Jacquerye) -- added anchor "half" to position right half of double marks, U+FE21 or U+FE23 - to Sans (by Denis Jacquerye) -- shifted U+0360 up to avoid collision with some outlines in Sans (by Denis - Jacquerye) -- added anchor above-mark anchor to U+035D, U+035E, U+0360, U+0361 in Sans (by - Denis Jacquerye) -- added instructions for ff, ffi, ffl ligatures in Serif Bold (by Eugeniy - Meshcheryakov) -- added instructions to some N'Ko glyphs (by Wesley Transue) -- added instructions to some Lao glyphs (by Wesley Transue) -- cleaning up 'liga' Standard Ligature in Latin, in Sans and Sans Mono (by - Denis Jacquerye) -- added U+046A, U+046B (big yus) in Serif (by Andrey V. Panov) -- added box drawing symbols to Sans and Serif (by Lars Næsbye Christensen) -- added Makefile to improve font and packages generating (by Nicolas Mailhot) - -Changes from 2.19 to 2.20 - -- removed TeX and TeXData tags from all sfd files (by Eugeniy Meshcheryakov) -- removed all 'frac' lookups (by Eugeniy Meshcheryakov) -- fixed duplicate glyph names (by Eugeniy Meshcheryakov) -- removed standard ligatures with U+00B7 in Mono (by Eugeniy Meshcheryakov) -- use reference to U+002D in U+00AD in Sans Oblique, and adjust instructions - (by Eugeniy Meshcheryakov) -- updated Cyrillic in Sans Extra Light (by Andrey V. Panov) -- added instructions to N'Ko U+07C1-U+07C6, U+07CA, U+07CE-U+07CF, U+07D1, - U+07D3-U+07D4, U+07D8, U+07DB and U+07EB in Sans (by Wesley Transue) -- added instructions to Lao U+0E8A, U+0E95, U+0E97, U+EA5, U+0EB4 and U+0EB5 - (by Wesley Transue) -- adjusted instructions for Hebrew glyphs (by Denis Jacquerye) -- added instructions for U+0265 in Sans Bold (by Denis Jacquerye) -- fix U+1D68 in Sans: it had the shape of delta, where it should be a rho (by - Ben Laenen) -- remove U+1D5C glyph in Sans Oblique (it was empty) (by Ben Laenen) -- fix instructions of U+01AD in Sans Bold (by Ben Laenen) -- fix instructions of U+042D in Serif (by Ben Laenen) -- remove buggy instructions of U+2328 in Serif (by Ben Laenen) -- corrected width of U+2C75-U+2C76 in Sans Bold and Serif Bold (by Gee Fung Sit) -- added U+2C75-U+2C77 to Mono (by Gee Fung Sit) - -Changes from 2.18 to 2.19 - -- fixed misplaced symbols (U+2325,2326) in Sans Oblique (by John Karp) -- added Mark to Base anchors: 'cedilla' for combining cedilla and - 'above-legacy' for stacking above precomposed glyphs (just a,e,i,o,u with - macron for now) in Sans (by Denis Jacquerye). -- added contextual substitution for Case and Dotless forms in all Sans variants - (by Denis Jacquerye). -- renamed 'ccmp' lookups for RTL and Basic (LGC, etc.) (by Denis Jacquerye) -- added anchor 'cedilla' for vowels in Sans. (by Denis Jacquerye) -- extended contextual dotless and case substitutions to handle both below and - above diacritics (by Denis Jacquerye) -- renamed Dotless and Case Form GSUB lookups in Sans with meaningful names (by - Denis Jacquerye) - -Changes from 2.17 to 2.18 - -- Re-encoded the source files for Full Unicode (by Ben Laenen) -- Re-enabled the "ff", "fl", "fi", "ffl", "ffi" ligatures by default in Serif - (by Ben Laenen) -- Disabled the "fi", "ffi" ligatures for languages with dotless i in Serif (by - Ben Laenen) -- added Tifinagh to Sans Book and Bold, U+2D30-U+2D65, U+2D6F, partially hinted - in Sans Book. (by Denis Jacquerye) -- added Tai Xuan Jing Symbols (U+1D300-1D356) to Sans (by Remy Oudompheng) -- added double-struck letters (U+1D538-U+1D56B minus reserved code points) to - Sans (by Gee Fung Sit) -- added U+22EE-U+22F1 to Sans (by Gee Fung Sit) -- added U+2C67-U+2C6C, U+2C75-U+2C77 to Serif (by Gee Fung Sit) -- italicized various glyphs in Latin Extended-B, IPA Extensions, Spacing - Modifier Letters, Phonetic Extension (Supplement) and Super- and Subscripts - in Serif Oblique fonts (by Gee Fung Sit) -- modified outlines, bearings of Hebrew U+05D6, U+05D8, U+05DB, U+05DE, U+05E0, - U+05E1, U+05E2, U+05EA in Sans Book and Oblique, adjusted hinting in Book - based on Yotam Benshalom's comments. (by Denis Jacquerye) -- added Braille Patterns (U+2800-U+28FF) to Serif fonts (by Gee Fung Sit) -- added N'Ko to Sans Book and Bold: U+07C0-U+07E7, U+07EB-U+07F5, U+07F8-U+07FA - (by Eugeniy Meshcheryakov) -- added U+0ED8 (Lao digit 8) to Sans (by Remy Oudompheng) -- added Lao diacritics U+0EB0-0EB9, U+0EBB-0EBC, U+0EC8-0ECD to Mono (by Remy - Oudompheng) -- renamed Serif [Bold] Oblique, make it Italic (by Eugeniy Meshcheryakov) -- added U+29FA-U+29FB to Sans and Sans Mono (by Gee Fung Sit) -- swapped glyphs for Eng U+014A from Sami Eng to African Eng, the latter being - more common (by Denis Jacquerye) -- swapped ae U+00E6 and ae.alt in Serif Italics fonts, thus fixing #8213 (by - Denis Jacquerye) -- minor improvements to Misc. Symbols in Sans (by Gee Fung Sit) -- minor improvements and additions to Sans ExtraLight (by Gee Fung Sit) -- improved instructions for various Cyrillic letters (by Eugeniy Meshcheryakov) -- fixed hinting of theta and chi in Sans Book (by Ben Laenen) -- added Georgian Mkhedruli to Sans, Serif and Mono, ASumtavruli to Sans and - Serif (by Besarion Gugushvili) - -Changes from 2.16 to 2.17 - -- Sans fonts: fix position for certain combinations of Arabic fatha, kasra, - shadda, damma, kasratan, dammatan, fathatan and hamza (by Ben Laenen) -- added 'ae.alt' to Serif Oblique fonts, with design matching shape of italic - 'a' instead of slanted 'a', see bug #8213 (by Denis Jacquerye) -- added super- and subscripts to Serif and Mono: U+1D2C-U+1D2E, U+1D30-U+1D3C, - U+1D3E-U+1D42, U+1D62-U+1D65, U+1D78, U+2071, U+207A-U+207E, U+208A-U+208E, - U+2090-U+2094 (by Gee Fung Sit) - -Changes from 2.15 to 2.16 - -- fixed hinting instructions for digits in DejaVu Sans Oblique, Bold Oblique, - and Serif Book to not change glyph width (by Eugeniy Meshcheryakov) -- added instructions for U+0404, U+0411, U+0413, U+0414, U+0417-U+041B, U+041F, - U+0423, U+0424, U+0426-U+0429, U+042C, U+042E, U+042F, U+0490 in Serif Bold - (by Eugeniy Meshcheryakov) -- added U+0220 and Eng.alt to Serif fonts (by Denis Jacquerye) -- added U+232C, U+2394, U+23E3 to Sans fonts (by John Karp) -- added U+230C-U+230F, U+231C-U+231F to Sans fonts, fixing bug:9547 - (by John Karp) -- adjusted dot below, dot above, dieresis above, dieresis below in Sans fonts - (by Denis Jacquerye) -- added U+2300, U+2301, U+2303, U+2304, U+2305, U+2307, U+2326, U+2327, U+232B, - arrow.base to Sans fonts (by John Karp) -- adjusted dot and dieresis below and above in Serif fonts (by Denis Jacquerye) -- added U+1E1C-U+1E1D to Serif fonts (by Denis Jacquerye) -- added U+22BE, U+22BF (by Wesley Transue) -- added U+2324; modified U+2325: more standard proportions, and matches U+2324 - and U+2387; added U+2387 : flipped U+2325 with standard arrowhead - (by John Karp) -- added Lao digits U+0ED0-0ED7, U+0ED9 (by Remy Oudompheng) -- added to Mono in Arabic block : U+060C, U+0615, U+061B, U+061F, - U+0621-U+063A, U+0640-0655, U+065A, U+0660-066F, U+0674, U+0679-0687, U+0691, - U+0692, U+0698, U+06A1, U+06A4, U+06A9, U+06AF, U+06B5, U+06BA, U+06BE, - U+06C6, U+06CC, U+06CE, U+06D5, U+06F0-06F9 (by Remy Oudompheng) -- added to Mono in Arabic Presentations Forms-A : U+FB52-FB81, U+FB8A-FB95, - U+FB9E, U+FB9F, U+FBAA-FBAD, U+FBE8, U+FBE9, U+FBFC-FBFF (by Remy Oudompheng) -- added to Mono in Arabic Presentations Forms-B : U+FE70-FE74, U+FE76-FEFC, - U+FEFF (by Remy Oudompheng) -- added U+05BA, U+05BE, U+05F3, U+05F4, U+FB1E, U+FB21-U+FB28, U+FB4F to Sans - (by Eugeniy Meshcheryakov) -- added U+2102 to Mono (by Eugeniy Meshcheryakov) -- added U+2983-U+2984 to Sans (by Gee Fung Sit) -- added U+2A2F to Sans, Serif and Mono (by Gee Fung Sit) -- added U+2373-2375, U+237A to Sans (by John Karp) -- converted kern pairs to kern classes with Tavmjong Bah's scripts - (by Denis Jacquerye) -- set ScriptLang of kerning classes to just latn because of Pango bug - (by Denis Jacquerye) -- added DNK to ScriptLang latn otherwise it is excluded, and SRB and MDK to - cyrl (by Denis Jacquerye) -- removed flag 0x80 in generate.pe, otherwise it generates kerning tables some - systems don't like; thus loosing Apple tables (by Denis Jacquerye) -- removed ligature for precomposed legacy characters of Sans Oblique fonts - (by Denis Jacquerye) -- added bearings to en dash U+2013, em dash U+2014 and figure dash U+2012 - by making dashes shorter, preserving character width (by Denis Jacquerye) -- reduced U+031C, U+0325 (ring below), U+0339 to be entirely visible; - added instructions in Sans Book; changed U+1e00-U+1e01 to use new ring below - (by Denis Jacquerye) -- adjusted circumflex below on U+1E12-U+1E13, U+1E18-U+1E19, U+1E3C-U+1E3D, - U+1E4A-U+1E4B, U+1E70-U+1E71, U+1E76-U+1E77 in Sans fonts (by Denis Jacquerye) -- Added U+0ED4, U+0ED5 to DejaVu Sans (by Remy Oudompheng) -- Lao-specific anchors (by Remy Oudompheng) -- added alternate I to match the small capital in Sans (by Gee Fung Sit) - -Changes from 2.14 to 2.15 - -- improved hinting in Sans Oblique to deal with some spacing and inconsistency - issues (by Ben Laenen) -- added anchors to Mono Book, and added GPOS rules for combining diacritics to - show up as zero width glyphs (by Ben Laenen) -- removed U+F21C (PUA), it was copy of U+2C64 from Latin Extended C (by Eugeniy - Meshcheryakov) -- added U+27E6-U+27E7 to Sans (by Gee Fung Sit) -- added U+1407, U+1409, U+140C-U+141B, U+141D-U+1425, U+1427-U+142E, - U+1435-U+1438, U+143A-U+1449, U+1452, U+1454, U+1457-U+1465, U+1467-U+146A, - U+1471, U+1474-U+1482, U+1484-U+1488, U+148F, U+1492, U+14A0, U+14A2, U+14A9, - U+14AC-U+14BA, U+14BC, U+14BD, U+14C6, U+14C9-U+14CF, U+14D1, U+14D2, U+14D9, - U+14DC-U+14E9, U+14EC, U+14F3, U+14F6-U+1504, U+1506, U+1507, U+1510-U+1525, - U+152C, U+152F-U+153D, U+1540, U+1541, U+154E, U+154F, U+1552, U+155B, U+155C, - U+1568, U+1569, U+1574-U+157B, U+157D, U+15A7-U+15AE, U+1646, U+1647 (by - Eugeniy Meshcheryakov) -- fixed several contours to not intersect, use horizontal or vertical tangents, - use integer coordinates, etc in Sans Book (by Denis Jacquerye) -- added U+0496-U+0497 in Serif (by Andrey V. Panov) - -Changes from 2.13 to 2.14 - -- added Philippine peso glyph U+20B1 (by Clayborne Arevalo) -- made U+2012 have the same width as digits, according to Unicode 5.0, - page 206 (by Roozbeh Pournader) -- made all of the "above" combining characters remove the dot of "i", - "j", etc (Soft_Dotted characters), according to Unicode 5.0, - page 228 (by Roozbeh Pournader) -- made U+012F, U+03F3, U+0456, U+0458, U+1E2D, and U+1ECB (all fonts - except Mono), U+0249, U+2148, and U+2149 (Sans and Sans Condensed), - U+0268 (Sans ExtraLight, Serif and Serif Condensed), and U+029D (Serif - and Serif Condensed) respect the Soft_Dotted property (by Roozbeh - Pournader) -- added U+223E, U+223F, U+2240, U+22C2, U+22C3 to Sans (by Remy Oudompheng) -- added U+203D to Serif (by Gee Fung Sit) -- added zero-width glyphs for U+2061-U+2063 to Sans and Serif (by Gee - Fung Sit) -- changed isolated forms of Arabic waw (U+0648, U+0624 and U+06C6) (bug #9432) - (by Ben Laenen) -- added Lao consonants U+0E81, U+0E82, U+0E84, U+0E87, U+0E88, U+0E8A, - U+0E8D, U+0E94-0E97, U+0E99-0E9F, U+0EA1-0EA3, U+0EA5, U+0EA7, U+0EAA, - U+0EAB, U+0EAD-0EAF to Sans Mono (by Remy Oudompheng) -- added U+0200-U+0217, U+0226-U+0229, U+02F3, U+1E00-U+1E07, - U+1E0A-U+1E0B, U+1E18-U+1E1F, U+1E22-U+1E23, U+1E28-U+1E2D, - U+1E3A-U+1E3B, U+1E40, U+1E48-U+1E49, U+1E56, U+1E58-U+1E59, - U+1E5E-U+1E5F, U+1E60, U+1E68-U+1E6B, U+1E6E-U+1E6F, U+1E72-U+1E77, - U+1E86-U+1E8B, U+1E92-U+1E96, U+1EA0-U+1EA1, U+1EF4-U+1EF5 to Mono - (by Ben Laenen) -- renamed uppercase variants of diacritics (macron, breve, double grave, - double acute, inverted breve, dot above) to "uni03XX.case" in Mono - (by Ben Laenen) -- moved uppercase variants of diacritics up in Mono so they properly - vertically align on capitals (by Ben Laenen) -- precomposed glyphs with macron, breve, double grave, double acute, - inverted breve, dot above, macron below, breve below, inverted breve - below, dot below, cedilla, caron below, circumflex below, diaeresis - below, tilde below now reference to combining diacritics instead of - space modifiers in Mono (by Ben Laenen) -- made ring below (U+0325), and half rings below (U+031C and U+0339) - smaller in Mono (by Ben Laenen) -- added U+205F to all fonts (by Roozbeh Pournader) -- added U+035E-U+035F to Sans (by Roozbeh Pournader) -- added empty glyphs for U+034F, U+202A-U+202E, U+2060, U+206A-206F, - U+FE00-U+FE0F to non-Mono fonts (by Roozbeh Pournader) -- added U+2101, U+2107-U+2108, U+210B, U+210C, U+2110, U+2112, U+211B, - U+211F, U+2123, U+2125, U+2128-U+2129, U+212C-U+212D, U+212F, - U+2130-U+2131, U+2133, U+2136-U+213A, U+2141-U+2144, U+2B00-U+2B11, - U+2B20-U+2B23 to Sans (by John Karp) -- reshaped omega (U+03C9) in Mono (by Ben Laenen) -- added U+2205, U+22C6, U+2300-U+2301, U+2303-U+2306, U+230C-U+230F, - U+2312-U+2315, U+231C-U+231F, U+2335, U+2337-U+233E, U+2341-U+2344, - U+2347-U+2348, U+234B-U+234D, U+2349-U+2350, U+2352-U+2354, - U+2357-U+2359, U+235A-U+235C, U+235E-U+2360, U+2363-U+2365, - U+2368-U+2369, U+236B-U+2370, U+2373-U+237A, U+2380-U+2383, - U+2388-U+238B, U+2395 in Mono (by Ben Laenen) - -Changes from 2.12 to 2.13 - -- adjusted U+0198B, U+01B3-U+01B4 in Sans, hinted U+01B4 in Sans Book - (by Denis Jacquerye) -- added U+27F0-U+27FF, U+2906-U+2907, U+290A-U+290B, U+2940-U+2941 to Sans - (by Denis Jacquerye) -- added U+01E6-U+01E9, U+01EE-U+01EF, U+01F4-U+01F5, U+01FC-U+01FF, - U+021E-U+021F, U+0245, U+02BD, U+02C9, U+1E9B, U+2045-U+2046, U+2213, U+22C5, - U+22EF to Sans Mono (by Roozbeh Pournader) -- added U+04FA-U+04FD to Sans (by Michael Everson) -- removed U+2329 and U+232A because of their CJK properties, added U+27E8 - and U+27E9 in their stead, fixing part of bug #9038 (by Roozbeh Pournader) -- corrected and improvised U+0466-U+0469, U+046E-U+0471, U+047C-U+047D, U+0482, - U+0484-U+0486, U+0492-U+0493, U+04B0-U+04B1, U+050C-U+050D, and U+204A - in Sans (by Michael Everson) -- added instructions for U+0402, U+0409, U+040A, U+040B, U+044D, U+040F, - U+0452, U+0459-U+045B, U+045F to Sans Book (by Eugeniy Meshcheryakov) -- made italic shape for U+431, U+432, U+437, U+43B, U+43C, U+43D, U+444, U+447, - U+44D, U+44F, U+459, U+45A in SerifOblique and SerifBoldOblique - (by Andrey V. Panov) -- modified U+024C to match glyph in Unicode chart, fixing bug #9039 - (by Denis Jacquerye) -- made some canonically equivalent characters share the same glyph: - U+02B9 = U+0374, U+0343 = U+0313, and U+0387 = U+00B7 also adjusting U+02BA - to look like double U+02B9, fixing parts of bug #9038 (by Roozbeh Pournader) -- changed shapes for U+0478 and U+0479 in Sans to those in the Unicode charts, - based on a recent decision by Unicode Technical Committee to only use - the digraph form (by Michael Everson) -- adjusted width of NBSP U+00A0 and NNBSP U+202F, fixing bug #8401 - (by Denis Jacquerye) -- fixed several contours to not intersect, use horizontal or vertical tangents, - use integer coordinates, etc (by Roozbeh Pournader and Denis Jacquerye) -- added U+1402, U+1430, U+144D, U+146C, U+148A, U+14A4, U+14C1, U+14D4, U+14EE, - U+1527, U+1545, U+157E, U+158E, U+15AF to Sans (by Eugeniy Meshcheryakov) -- enlarged width of U+459 and U+45A in Serif (by Andrey V. Panov) -- made traditional shape for U+452, U+45B (by Andrey V. Panov) -- added euro sign U+20AC to Sans ExtraLight, making fontconfig recognize - the font as supporting English (by Denis Jacquerye) - -Changes from 2.11 to 2.12 - -- added U+0180 to Serif (by Denis Jacquerye) -- improved and/or hinted Armenian letters U+0542, U+0546, U+0562, - U+0563, U+0564, U+0577, U+0582 in Sans (by Ben Laenen) -- added U+4FE-U+4FF, U+512-U+513, U+2114, U+214E, U+26B2 to Sans - (by Gee Fung Sit) -- adjusted U+0496-U+0497, U+049A-U+04A1 in Sans to match U+0416, - U+041A, U+0436 and U+043A (by Gee Fung Sit) -- Mathematical Operators in Sans: changed U+22C0-U+22C1 to match - other n-ary operators, adjusted U+2203-U+2204, changed U+2220 in - Sans to match the style of U+2221 (by Gee Fung Sit) -- added U+1401, U+1403-U+1406, U+140A, U+140B, U+1426, U+142F, - U+1431-U+1434, U+1438, U+1439, U+1449, U+144A, U+144C, - U+144E-U+1451, U+1455, U+1456, U+1466, U+146B, U+146D-U+1470, - U+1472, U+1473, U+1483, U+1489, U+148B-U+148E, U+1490, U+1491, - U+14A1, U+14A3, U+14A5-U+14A8, U+14AA, U+14AB, U+14BB, U+14C0, - U+14C2-U+14C5, U+14C7, U+14C8, U+14D0, U+14D3, U+14D5-U+14D8, - U+14DA, U+14DB, U+14EA, U+14ED, U+14EF-U+14F2, U+14F4, U+14F5, - U+1405, U+1526, U+1528-U+152B, U+152D, U+152E, U+153E, - U+1542-U+1544, U+1546-U+154D, U+1550, U+1553, U+1555-U+155A, - U+1567, U+156A, U+157C, U+157F-U+1585, U+158A-U+158D, - U+158F-U+1596, U+15A0-U+15A6, U+15DE, U+15E1, U+166E-U+1676 to - Sans (by Eugeniy Meshcheryakov) -- re-enabled Latin ligatures fi, ffi, fl, ffl and ff in Sans - (by Ben Laenen) -- made italic shape for U+436, U+44A, U+44B, U+44C, U+44E, U+45F, - U+463 in SerifOblique and SerifBoldOblique (by Andrey V. Panov) -- fixed sub- and superscript metrics in Condensed Sans (bug #8848) - (by Ben Laenen) -- added U+474, U+475 in Serif (by Andrey V. Panov) -- hinted Greek glyphs U+03B7, U+30B8, U+03B9, U+03C1, U+03C3, - U+03C6 in Mono Book (by Ben Laenen) - -Changes from 2.10 to 2.11 - -- added instructions for Hebrew glyphs (Sans Book, by Eugeniy - Meshcheryakov) -- changed U+01A6 (Latin Yr) after bug #8212, in Sans, Serif and - Sans Mono fonts (by Denis Jacquerye). -- removed instruction for U+2600-U+26A1 (by Mederic Boquien) -- added U+202F and set width of U+00A0 (nobreakingspace) to the - same as U+0020, space (by Denis Jacquerye). -- added and improved instructions for various Cyrillic letters - (by Eugeniy Meshcheryakov) -- Changed U+416, U+42F, U+427 (non-Bold), U+436, U+447 (non-Bold), - U+44F, U+437 (Bold), corrected U+40F, U+414, U+424, U+426, U+429, - U+434, U+438 (Bold), U+446, U+449, U+44D (non-Bold), U+45F in - Sans Mono (by Andrey V. Panov) -- made small corrections to Cyrillic, most appreciable to U+409, - U+413, U+41B, U+427 and U+433, U+434, U+43B, U+447, U+459 - (upright fonts) to Serif (by Andrey V. Panov) -- adjusted bearings of U+410, U+416, U+41A, U+42F, U+436, U+43A, - U+443, U+44F in Serif (by Andrey V. Panov) -- enlarged width of U+44A, U+44B, U+44C, U+463 in Serif - (by Andrey V. Panov) -- added ligature "iacute" as "afii10103" (U+456) "acutecomb" in - Serif (by Andrey V. Panov) -- made italic shape to U+446, U+448, U+449 in Serif (by Andrey V. - Panov) -- added "afii10831" (U+F6C7), "afii10832" (U+F6C8) in Serif (by - Andrey V. Panov) -- new minimum version of fontforge is 20061014 (by Ben Laenen) - -Changes from 2.9 to 2.10: - -- added U+0242, U+024A-U+024B, U+024E-U+024F, U+037C-U+037D, U+0E3F, - U+1D2C-U+1D2E, U+1D30-U+1D42, U+1D5D-U+1D6A, U+1D78, U+1DB8, - U+2090-U+2094, U+20D0-U+20D1, U+2C60-U+2C66, U+2C6B-U+2C6C, U+2C74 and - U+FB29 to Sans (by Gee Fung Sit) -- added Lao glyphs : U+0E81-0E82, U+E084, U+0E87-0E88, U+0E8A, U+0E8D, - U+0E94-0E97, U+0E99-0E9F, U+0EA1-0EA3, U+0EA5, U+0EA7, U+0EAA-0EAB, - U+0EAD-0EB9, U+0EBB-0EBD, U+0EC0-0EC4, U+0EC6, U+0EC8-0ECD, U+0EDC-0EDD - (by Remy Oudompheng) -- fixed U+0193 not showing in Windows (bug #7897) (by Ben Laenen) -- changes to U+222B-222D in Sans Mono (by Remy Oudompheng) -- ported the three remaining currency symbols from Arev (U+20B0, - U+20B2-U+20B3), and replaced one (U+20AF) in Sans (by Lars Naesbye - Christensen) -- corrected U+20A5 in Sans (by Gee Fung Sit) -- merged Double-Struck Letters from Arev: U+2102, U+210D, U+2115, - U+2119-U+211A, U+2124, U+213C-U+2140 (by Gee Fung Sit) -- added U+2308-U+230B and U+2329-U+232A to Sans Mono and Serif faces, - fixed incorrect direction of U+2329 in Sans faces, and improved - U+2308-U+230B in Sans faces per Ben Laenen's suggestions (by David - Lawrence Ramsey) -- added U+06D5 and final form of it (needed for Kurdish) (by Ben Laenen) -- added two special glyphs U+F000 and U+F001 in Sans Book that show the - current ppem size (horizontal and vertical) (by Ben Laenen) -- added U+2318 and U+2325 to Sans Mono faces, based on the Sans versions - (by David Lawrence Ramsey) -- added U+2B14-U+2B1A to all faces except Sans ExtraLight (by David - Lawrence Ramsey) -- respaced all Geometric Shapes characters in Serif faces to match those - in Sans faces again, respaced U+23CF in Sans, Sans ExtraLight, and - Serif faces to match U+25A0 (or Sans in Sans ExtraLight's case) again, - and respaced U+2B12-U+2B13 in Sans and Serif faces to match U+25A1 - again (by David Lawrence Ramsey) -- corrected width of Modifier Small Letters U+1D43-1D5B in Sans Oblique - and U+1D9B-U+1DBF in Sans Oblique and Sans Bold Oblique (by Gee Fung Sit) -- added a bunch of glyphs to Sans ExtraLight (see SVN for details) (by - Gee Fung Sit) -- adjusted Cyrillic descenders in Sans ExtraLight to sync with Sans (by - Gee Fung Sit) -- added U+0242, U+0245 to Serif (by Gee Fung Sit) -- replaced the SHPIX routines which gave them bad spacing at certain - sizes in FreeType for A, V, Z, v and z in Sans Bold (by Ben Laenen) - -Changes from 2.8 to 2.9: - -- DejaVuSansExtraLight.sfd: changed family name from "DejaVu Sans" to - "DejaVu Sans Light" (in case we add a Light weight variant), so legacy - apps that understand only 4 styles are happy. (by Denis Jacquerye) -- added Name ID 16, aka preferred family name, and Name ID 17, aka - preferred style name, so contemporary apps that understand more that 4 - styles can use big fonts families "DejaVu Sans" and "DejaVu Serif". For - those, Extralight and Condensed are just styles not different families. - (by Denis Jacquerye) -- added U+22B6-22BD, U+22C0-22C1, U+22D6-22D7 to Sans. (by Remy Oudompheng) -- added U+037B, U+2184, U+2C67-U+2C6A and U+2C75-U+2C77 to Sans (by Gee - Fung Sit) -- adjusted asteriskmath (U+2217) for consistency with other mathematical - operators in Sans (by Ben Laenen) -- hinted some Armenian capitals in Sans Book (by Ben Laenen) -- added U+0246 - U+0249 (by Ben Laenen) -- BUGFIX : swapped U+224E and U+224F, in Sans, Sans Condensed and Sans Mono - (by Remy Oudompheng) -- adjusted U+20B5 (by Mederic Boquien) -- swapped U+21DA and U+21DB which were in wrong order (by Heikki Lindroos) -- added U+222E-2233, U+239B-23AD, U+2A00-2A02, U+2A0F-2A1C to Sans (by Remy - Oudompheng) -- added U+239B-23AD to Mono (by Remy Oudompheng) -- added U+2024-2025 to Serif (by Mederic Boquien) -- added U+222C-222D, U+2A0C-2A0E to Serif (by Remy Oudompheng) -- added U+2190-21FF to Mono (by Heikki Lindroos) -- added Hebrew glyphs - U+05B0-U+05BD, U+05BF-U+05C3, U+05C6, U+05C7, - U+05D0-U+05EA, U+05F0-U+05F2, U+FB1F, U+FB20, U+FB2A-U+FB36, - U+FB38-U+FB3C, U+FB3E, U+FB40, U+FB41, U+FB43, U+FB44, U+FB46-U+FB4E (by - Gee Fung Sit and Eugeniy Meshcheryakov) -- adjustments for Cyrillic in Sans (by Andrey V. Panov) -- made italic shape for U+0434, U+0456, U+0457 in SerifOblique and Serif - Bold Oblique (by Andrey V. Panov) - -Changes from 2.7 to 2.8: - -- fixed instructions for U+0423, U+0427, U+0447, U+0448 in Serif, so they - look good at large sizes too (by Eugeniy Meshcheryakov) -- added U+FB00 and U+FB03 to U+FB06 to Serif typefaces (by Heikki Lindroos) -- added U+26B0-U+26B1, U+2701-U+2704, U+2706-U+2709, U+270C-U+2727, U+2729 - to U+274B, U+274D, U+274F to U+2752, U+2756, U+2758-U+275E, U+2761 to - U+2775 (by Heikki Lindroos) -- added and improved instructions for Cyrillic letters in Mono and Serif - (Book, by Eugeniy Meshcheryakov) -- rotated U+26B0 (was too small in mono) (by Gee Fung Sit) -- adjusted U+1EDA-U+1EDD, U+1EE8-U+1EEB, capitals using capital specific - accent and moved diacritics to match position on U+00F2 (ograve), etc. - (by Denis Jacquerye) -- added U+20D6, U+20D7 to Sans (by Gee Fung Sit) -- made Armenian ligatures discretionary since the Firefox ligature problem - still isn't fixed (by Ben Laenen) -- moved Armenian hyphen U+058A to a higher position (bug #7436) (by Ben - Laenen) -- hinted Greek glyphs in Sans Bold (by Ben Laenen) -- enabled Arabic lam-alif ligatures when diacritics are used (by Ben Laenen) - -Changes from 2.6 to 2.7: - -- added glyphs needed for Kurdish: U+0695, U+06B5, U+06C6, U+06CE and their - init/medi/fina forms in Sans (by Ben Laenen) -- added U+02CD, U+01F8 - U+01F9, U+1E3E - U+1E3F, U+1E30 - U+1E35, U+1EBC - - U+1EBD, U+1EF8 - U+1EF9 (includes glyphs needed for Yoruba, Maori, Guarani - and Twi) (by Ben Laenen) -- added U+22C8-22CC, U+29CE-29D5, U+2A7D-2AA0, U+2AAE-2ABA, U+2AF9-2AFA to - Sans (by Remy Oudompheng) -- adjusted diacritics on Vietnamese, Pinyin and other characters: - U+01A0-U+01A1, U+01AF-U+01B0, U+01D5-U+01DC, U+01DE-01E1, U+01FA-U+01FB - U+022A-U+022D, U+0230-U+0231, U+1E14-U+1E17, U+1E4C-U+1E53, U+1E78-U+1E7B, - U+1EA4-U+1EF1 in Sans (Book, Bold and Oblique) (by Denis Jacquerye) -- added basic arrows U+2190-U+2193 in Serif, which completes MES-1 compliance - for Serif (by Ben Laenen) -- added U+01E4, U+01E5, U+01FA, U+01FB, U+02BD, U+02C9 and U+02EE to Serif - (by Ben Laenen) -- fixed U+0209 in Serif Bold Oblique (by Ben Laenen) -- adjusted Box Drawing block characters U+2500-257F in Mono to fit character - cell, shifting them up by 416 (Denis Jacquerye) -- redid U+0194 in Sans (by Ben Laenen) -- added U+2217-2218, U+2295-22A1 to Mono (by Remy Oudompheng) -- added U+0462 to Serif (by Andrey V. Panov) -- added U+226C, U+228C-228E, U+2293-2294, U+22F2-22FF to Sans (by Remy - Oudompheng) -- adjusted U+2208-220D in Sans (by Remy Oudompheng) -- improved some Cyrillic glyphs in Mono (by Andrey V. Panov), rewritten - instructions for changed glyphs (by Eugeniy Meshcheryakov) -- added U+1E0E-1E0F, U+1E8E-1E8F to Mono fonts (by Denis Jacquerye). (bug - #7166) -- renamed 'Dotabove' to 'Dotaccent' in Mono Sans Oblique to match other fonts - (by Denis Jacquerye). -- added U+200B-U+200F in Sans faces and Serif faces, U+200B and U+200C were - in Sans already (by Lars Naesbye Christensen) -- added U+2601-U+262F, U+263D, U+263E, U+2648-U+265F, U+2668, U+2670-U+268B, - U+2690-U+269C, U+26A0, U+26A1, U+2794, U+2798-U+27AF, U+27B1-U+27BE to Mono - (by Heikki Lindroos) -- replaced the references with unshifted ones for both κ U+03BA and к U+043A - in Mono Book (by Denis Jacquerye) -- fixing glyph for U+04ED in Mono Book, consisted only of dieresis (by Andrey - V. Panov). - -Changes from 2.5 to 2.6: - -- redid U+2032 - U+2037, U+2057 based on Arev in Sans (by Gee Fung Sit) -- added U+0195, corrected U+039E, U+204B in Sans ExtraLight (by Gee Fung Sit) -- added instructions for some Cyrillic letters in Sans Bold (by Eugeniy - Meshcheryakov) -- added vulgar fractions U+2153-U+215F for Serif, made with references (by - Lars Naesbye Christensen) -- added U+228F-2292, U+2299-22AF, U+22B2-22B5, U+22CD, U+22D8-22ED to Sans - (by Remy Oudompheng) -- added U+2208-220D, U+2238-223D, U+2278-2281, U+228A-228B, U+228F-2292, - U+22CD, U+22DA-22E9 to Mono (by Remy Oudompheng) -- fixed misplaced dot in U+2250 in Mono (by Remy Oudompheng) -- added instructions for some Cyrillic letters in Mono Book and Bold(by - Eugeniy Meshcheryakov) -- minor changes to U+2241, U+2261-2263, U+22A4, U+22A5 in Sans (by Remy - Oudompheng) -- added hinting instructions to lowercase Armenian glyphs in Sans Book (by - Ben Laenen) -- changed U+2208, U+220B to match U+2209 and U+220C in Sans Bold (by Remy - Oudompheng) -- added Braille patterns U+2800-U+28FF to Sans (by Mederic Boquien) -- added instructions for some Cyrillic letters in Serif Book (by Eugeniy - Meshcheryakov) -- renamed BoldOblique fonts to Bold Oblique in TTF Name as originally in - Bitstream Vera fonts (by Denis Jacquerye) -- added hinting instructions to some Latin-B Extended and IPA characters in - Sans Book (by Denis Jacquerye and Ben Laenen) -- adjusted bearings, replaced diacritics, hinted hook and horn for - Vietnamese in Sans Book (by Denis Jacquerye) -- made FAX, TM, TEL, etc. discritionary ligatures in Sans and Serif fonts - (by Denis Jacquerye) -- removed ligatures of precomposed characters in Sans and Serif fonts (by - Denis Jacquerye) -- added U+F208, U+F20A, U+F215-F217, U+F21A-F21B, U+F25F in PUA (from SIL's - PUA, probably in Unicode 5.0): U+0243, U+0244, U+0245, U+024C, U+024D, - U+2C64, (U+2C6D), (U+2C71) -- modified some glyphs in Serif Oblique to make them more italic (by Denis - Jacquerye) - -Changes from 2.4 to 2.5: - -- fixed excessive kerning bug that occurs with Pango (by Denis Jacquerye) -- added U+20AF to Sans and Serif (by Lars Naesbye Christensen) -- regenerated Condensed faces (by Ben Laenen) -- added U+035C-U+035D to Sans, fixed U+0361 (by Denis Jacquerye) -- integrated 255 characters from Arev fonts: Latin Extended-B, Spacing - Modifiers, Combining Diacritical Marks, Cyrillic, Cyrillic supplement, - General Punctuation, Letterlike Symbols, Arrows, Mathematical Operators, - Miscellaneous Technical, Dingbats, Alphabetic Presentation Forms (by Denis - Jacquerye) -- added basic Cyrillic and basic Greek to Sans ExtraLight (by Denis Jacquerye) -- added U+0498, U+049A, U+04AA, U+04AB, U+04AF to Serif (by Eugeniy - Meshcheryakov) -- added U+0494, U+0495, U+0498, U+0499, U+04AA, U+04AB, U+04C3, U+04C4, - U+04C7, U+04C8 to Mono (by Eugeniy Meshcheryakov) -- adjusted weight of U+0256, U+0257, U+0260, U+0272, U+0273, U+0277, U+029B, - U+02A0 and modifed U+028B and U+027A in Mono (by Denis Jacquerye) -- added U+2000-200A to Mono (by Denis Jacquerye) -- added vulgar fractions U+2153 - U+215F to Mono (by Gee Fung Sit) -- adapted metrics of Arabic glyphs so they stay above cut-off height in Sans - (by Ben Laenen) -- fixed mkmk anchors for Arabic diacritics so they stack properly in Sans (by - Ben Laenen) -- fixed weight of lowercase upsilon in Sans Bold, make small adjustment to - lowercase omega in Sans (by Ben Laenen) -- added U+210E (by Mederic Boquien) -- unslanted U+2201, U+221B and U+221C in Sans Oblique (by Mederic Boquien) -- added several mathematical relation symbols to Sans and Mono (U+2241-224C, - U+2250-2255, U+2260-2269, U+226E-2277, U+2282-2287) modified U+223C to match - other tildes, and U+2282-2284 to have the same shape. (by Remy Oudompheng) -- made U+2234-U+2237 refer to U+2219 instead of U+00B7 in Sans (by Mederic - Boquien) -- added U+2238-223B, U+226A-226B, U+2278-2281, U+2288-228B to Sans (by Remy - Oudompheng) -- unslanted and changed reference of U+22C5 from U+00B7 to U+2219 in Sans (by - Mederic Boquien) -- added U+224D-225F, U+226D, U+22C6 to Sans and unslanted U+2219 in Sans - Oblique. (by Remy Oudompheng) -- added U+224D-225F, U+226D to Mono, shifted U+2266-2269 higher upwards and - unslanted U+2219 in Oblique. (by Remy Oudompheng) -- merged Coptic glyphs from Arev 0.2 (by Lars Naesbye Christensen) -- fixed and adjusted various Cyrillic glyphs in Serif (by Andrey V. Panov) -- made fi, fl... ligatures discretionary ligatures (by Ben Laenen) - -Changes from 2.3 to 2.4: - -- added U+04A2, U+04A3, U+04AC - U+04AF, U+04BA, U+04BB, U+04C0 - - U+04C2, U+04CB, U+04CD, U+04D8 - U+04DF, U+04E2 - U+04E5, U+04E8 - U+04F5, - U+04F6 - U+04F9 to Mono (by Eugeniy Meshcheryakov) -- added U+048C, U+048D, U+0494, U+0495, U+049E - U+04A7, U+04AC - - U+04AE, U+04B4- U+04B7, U+04BA, U+04BB, U+04C0 - U+04C4, U+04C7, U+04C8, - U+04CB, U+04CC, U+04D8 - U+04DF, U+04E2 - U+04E5, U+04EC - U+04F9 to Serif - (by Eugeniy Meshcheryakov) -- added U+2134 to Sans (by Gee Fung Sit) -- added U+2080 - U+2089 to all faces (by Gee Fung Sit) -- several minor corrections to Sans (by Gee Fung Sit) -- major corrections to Sans Condensed (by Gee Fung Sit) -- corrected Superscripts and Subscripts in Sans (by Gee Fung Sit) -- corrected anchors of U+0316-U+0319 (by Denis Jacquerye) -- Verajja integrated (by Stepan Roh) -- copied U+2328, U+2600, U+2639-U+263C, U+263F-U+2647, U+2660-U+2667, - and U+2669-U+266F from Sans to Serif, and copied scaled-down versions of - them to Sans Mono (by David Lawrence Ramsey) -- added U+20B4 to all faces (by Eugeniy Meshcheryakov) -- added more minor positional adjustments to U+2638 in all faces to - match the other miscellaneous symbols in Verajja, and rescale it in Sans - Mono so that it looks better (by David Lawrence Ramsey) -- added U+2242, U+2243 and U+22A4 (by Mederic Boquien) -- corrected U+2245 in Sans (by Mederic Boquien) -- added U+0221, U+0234-0236 (by Denis Jacquerye) -- added in Arabic block to Sans: U+060C, U+0615, U+061B, U+061F, U+0621 -- U+063A, U+0640 - U+0655, U+0660 - U+066F, U+0679 - U+0687, U+0698, U+06A1, - U+06A9, U+06AF, U+06BA, U+06BF, U+06CC, U+06F0 - U+06F9 (by Ben Laenen) -- added in Arabic Presentation Forms A to Sans: U+FB52 - U+FB81, U+FB8A -- U+FB95, U+FB9E - U+FB9F, U+FBE8 - U+FBE9, U+FBFC - U+FBFF (by Ben Laenen) -- added complete Arabic Presentation Forms B to Sans: U+FE70 - U+FE74, - U+FE76 - U+FEFC, U+FEFF (by Ben Laenen) -- added complete Greek Extended block to Mono (by Ben Laenen) -- modified Greek capitals with tonos in Mono (by Ben Laenen) -- added U+01C4-01CC, U+01D5, U+01DE, U+01E0-U+01E1, U+01E6-U+01E9, - U+01EE-U+01F5, U+01F8-U+0217, U+021E-U+021F, U+0226-U+022A, U+022C to Serif - (by Denis Jacquerye) -- adjusted U+043B and U+044F in Serif (by Denis Jacquerye) -- added U+2000-U+200A (by Denis Jacquerye) -- added U+1E00-U+1E0B, U+1E0E-U+1E11, U+1E14-U+1E1C, U+1E1E-U+1E23, - U+1E26-U+1E2D, U+1E30-U+1E35, U+1E3A-U+1E3B, U+1E3E-U+1E40, U+1E48-U+1E49, - U+1E50-U+1E56, U+1E58-U+1E59, U+1E5E-U+1E60, U+1E68-U+1E6B, U+1E6E-U+1E6F, - U+1E72-U+1E7D, U+1E86-U+1E9B, U+1EA0-U+1EA3, U+1EAC-U+1EB7, U+1EBA-U+1EBD, - U+1EC6-U+1ECF, U+1ED8-U+1ED9, U+1EE6-U+1EE7, U+1EF4-U+1EF9 to Serif (by - Denis Jacquerye) -- added U+048E, U+048F, U+049C-U+049F, U+04B8, U+04B9, U+04BC-U+04BF, - U+04C3, U+04C4 to Sans (by Eugeniy Meshcheryakov) -- added DejaVu Sans Extra Light (by Denis Jacquerye) -- Adjusted underline position for (hopefully) improved legibility in - Sans, Serif, Mono (Tim May) -- added auto-generated DejaVu LGC (by Stepan Roh) - -Changes from 2.2 to 2.3: - -- fixed bug U+042B and U+044B behave badly in Sans Bold or Oblique (by - Keenan Pepper) -- added and improved TrueType instructions and related settings (by - Keenan Pepper) -- added U+04D0-U+04D7, U+04E6, U+04E7 to Mono (by Eugeniy Meshcheryakov) -- added U+048A - U+048D, U+0498, U+0499, U+04AA, U+04AB, U+04B0, U+04B1, - U+04C0, U+04C9, U+04CA, U+04CE, U+04CD, U+04DA, U+04DB, U+04DE, U+04DF, - U+04E2 - U+04E5, U+04EC - U+04F8, U+04F9 to Sans (by Eugeniy Meshcheryakov) -- added U+04E0, U+04E1 to all faces (by Eugeniy Meshcheryakov) -- added Greek Extended to Sans and Serif: U+1F00-U+1F15, U+1F18-U+1F1D, - U+1F20-U+1F45, U+1F48-U+1F4D, U+1F50-U+1F57, U+1F59, U+1F5B, U+1F5D, - U+1F5F-U+1F7D, U+1F80-U+1FB4, U+1FB6-U+1FC4, U+1FC6-U+1FD3, U+1FD6-U+1FDB, - U+1FDD-U+1FEF, U+1FF2-U+1FF4, U+1FF6-U+1FFE (by Ben Laenen) -- added Greek variant letterforms, archaic letters and symbols to Mono: - U+03D0-U+03E1, U+03F0-U+03FF (by Ben Laenen) -- added Armenian block and Armenian ligatures to Sans (U+0531 - U+0556, - U+0559 - U+055F, U+0561 - U+0587, U+0589 - U+058A, U+FB13 - U+FB17) (by Ben - Laenen) -- redid some Greek characters in Sans and Mono to make them look better - and to correct some errors (by Ben Laenen) -- added U+27E0 to all faces (by David Lawrence Ramsey) -- added underscore (U+005F) consistency fixes: extended the Sans Mono - and Sans Mono Oblique underscores to touch both horizontal edges, and - reduced the height of the Sans Bold Oblique underscore to match the Sans - Bold underscore (by David Lawrence Ramsey) -- added underscore (U+005F) derivatives and consistency fixes for them: - made U+0332 a reference to underscore at Denis Jacquerye's suggestion; made - U+0333 two references to underscore; made U+033F two references to U+203E; - added U+2017 as two references to underscore, and made U+0333 a reference to - it; and added U+203E as a reference to underscore, and made U+0305 a - reference to it (by David Lawrence Ramsey) -- added U+201B, U+2220, U+2320-U+2321, U+23AE, U+23CF, all remaining - Geometric Shapes glyphs (U+25A0-U+25C9, U+25CB-U+25D7, U+25D9-U+25E5, - U+25E7-U+25FF), and U+2B12-U+2B13 to all faces (by David Lawrence Ramsey) -- added minor positional adjustments to U+2638 in all faces (by David - Lawrence Ramsey) -- added U+201F to Sans Mono and Serif faces (by David Lawrence Ramsey) -- added U+01B7, U+01F6, U+0464 - U+0465, U+2160 - U+2180, U+2183, - U+220A, U+220D, U+2329, U+232A, U+2422, U+27E8 - U+27EB, U+2680 - U+2685 to - Sans (by Gee Fung Sit ???) -- added U+2116 to Sans and Serif (by Gee Fung Sit) -- changed florin sign U+0192 in Sans (by Gee Fung Sit) -- added anchor points to some glyphs (by Denis Jacquerye) -- adjusted height of IPA superscripts U+02B0-02B8, U+02C0-02C1, - U+02E0-02E4, U+207F to match with height of U+00B2 (by Denis Jacquerye) -- added U+0184-U+0185, U+019C, U+019F, U+01A0-U+01A3, U+01A6, U+01AA, - U+01AF-U+01B0, U+01B2-U+01B4, U+01B7-U+01B8, U+01BC-U+01BC, U+0224-U+0225, - U+023A-U+0240, U+1D16-U+1D17, U+1D1D-U+1D1E, U+1D43-U+1D5B, U+1D7B, - U+1D85,U+1D9B-1DB7, U+1DB9-U+1DBF, U+20A6 to all fonts (by Denis Jacquerye) -- added added U+0182, U+018B, U+018E, U+01A0-U+01A1, U+01B1, U+01B9, - U+01C0-U+01C3, U+0238-U+0239, U+1D02, U+1D08-U+1D09, U+1D14, U+1D1F, U+1D77 - to Serif and Mono (by Denis Jacquerye) -- added U+0181, U+0183, U+0187-U+0188, U+018A-U+018F, U+0191, U+0193, - U+0195-U+019B, U+019D-U+019E, U+01A4-U+01A5, U+01AC-U+01AE, U+01B5-U+01B6, - U+01B9, U+01BB, U+01F6 to Serif (by Denis Jacquerye) -- added U+0181, U+0187-U+0188, U+018A, U+018D, U+018F, U+0191, U+0193, - U+0195-U+019F, U+01A4-01A5, U+01AC-01AD, U+01B5-U+01B6, U+1BB, U+01F6, - U+01D7-U+01DC, U+0238-U+0239, U+0241 to Mono (by Denis Jacquerye) -- added to Mono and Serif (by Denis Jacquerye) - -Changes from 2.1 to 2.2: - -- reworked the vertical orientation of the Blocks Elements characters - in all faces to remove their overly large descenders, in order to fix - problems with e.g. terminal emulators (by David Lawrence Ramsey) -- copied bullet in Sans faces to Serif faces for consistency (by David - Lawrence Ramsey) -- added U+2023, U+25D8, U+25E6, and U+29EB to all faces (by David - Lawrence Ramsey) -- added U+1EB8, U+1EB9, U+1ECA - U+1ECD, U+1EE4, U+1EE5 (by Tim May) -- added U+01DD, U+02BE, U+02BF, U+02D3 to all, changed U+02D2 in - non-Condensed and U+1EE5 in Serif (by Tim May) -- fixed U+01CE, replacing wrong circumflex by caron (by Denis Jacquerye) -- added anchor points to some glyphs (by Denis Jacquerye) -- added U+20B5 (by Denis Jacquerye) -- added U+0181 - U+0183, U+0187, U+0188, U+018A - U+018D, U+0191, - U+0193, U+0195 - U+019B, U+019D, U+019E, U+01A4, U+01A7 - U+01A9, U+01AB - - U+01AE, U+01B1, U+01B5, U+01B6, U+01BB, U+01C0 - U+01C3, U+01F1 - U+01F3, - U+0238, U+0239, U+1D02, U+1D08, U+1D09, U+1D14, U+1D1F, U+1D77, U+2103, - U+2126, U+2127, U+212A, U+212B, U+2132, U+214B, U+2210, U+2217, U+2218, - U+2A0C - U+2A0E, U+FB00, U+FB03 and U+FB04 to Sans (by Gee Fung Sit) -- added U+01A9, U+01C3 and U+2126 to Mono and Serif (by Gee Fung Sit) -- adjusted bearings of U+028B in Sans (by Gee Fung Sit) -- added U+018F, U+0494-U+0497, U+04A0-U+04A7, U+04AC-U+04AF, - U+04B4-U+04B7, U+04BA-U+04BB, U+04C1-U+04C2, U+04C5-U+04C8, U+04CB-U+04CC, - U+04D0-U+04D9, U+04DC-U+04DD, U+04E6-U+04EB to Sans (by Eugeniy - Meshcheryakov) -- replaced with references U+0391-U+0393, U+0395-U+0397, U+0399, U+039A, - U+039C, U+039D, U+039F-U+03A1, U+03A4, U+03A5, U+03A7, U+03BF, U+03DC, - U+0405, U+0406, U+0408, U+0410, U+0412, U+0415, U+0417, U+041A, - U+041C-U+041E, U+0420-U+0422, U+0425, U+0430, U+0435, U+043E, U+0440, - U+0441, U+0443, U+0445, U+0455-U+0458 in Serif and Mono (by Eugeniy - Meshcheryakov) -- added U+04D0-U+04D7, U+04E6-U+04EB to Serif (by Eugeniy Meshcheryakov) -- added U+212A and U+212B to the rest of the faces (by Lars Naesbye - Christensen) -- added U+2318 and U+2325 to Sans and Serif (by Lars Naesbye Christensen) -- added and improved TrueType instructions and related settings (by - Keenan Pepper) -- completed basic Greek alphabet: added U+0374-U+0375, U+037A, U+037E, - U+0384-U+038A, U+038C, U+038E-U+0390, U+03AC-U+03BF, U+03C1-U+03CE (by Ben - Laenen) -- added U+2070 and U+2074-U+2079 (by Mederic Boquien) - -Changes from 2.0 to 2.1: - -*** Be aware that names of some TTF files changed since version 2.0. *** - -- added U+0323, U+1E0C, U+1E0D, U+1E24, U+1E25, U+1E36 - U+1E39, U+1E42, - U+1E43, U+1E46, U+1E47, U+1E5A - U+1E5D, U+1E62, U+1E63, U+1E6C, U+1E6D, - U+1E7E, U+1E7F (by Tim May) -- fixed bug where GNOME applications used Mono Bold Oblique instead of - Mono Oblique (by Keenan Pepper) -- added and improved TrueType instructions and related settings (by - Keenan Pepper) -- added U+1E41, U+1E57, U+1E61 (by Sander Vesik) -- added U+0189, U+0309, U+0313, U+0314, U+031A, U+031B, U+0327, U+0328, - U+032B, U+0333, U+033C (by Denis Jacquerye) -- adjusted and fixed U+0186, U+0254, U+0291, U+0316 - U+0319, U+031C - - U+0320, U+0323 - U+0326, U+0329 - U+032A, U+032C - U+0332, U+0339 - U+033B, - U+033E, U+033F (by Denis Jacquerye) -- fixed U+1E12, U+1E3C, U+1E4A, U+1E70 to have normal below diacritics - (by Denis Jacquerye) -- fixed U+1E82, U+1E84 and U+1EF2 to have uppercase above diacritics (by - Denis Jacquerye) -- added anchor points to some glyphs (by Denis Jacquerye) -- dropped "-Roman" from font names - affects both internal TTF names and - names of generated files (by Stepan Roh) -- attempt to fix bug Vertical spacing too big for Mono by exchanging - LineGap and OS2TypoLinegap values (proofed by Stefan Rank) -- added Greek capitals U+0391 - U+03A1, U+03A3 - U+03A9, U+03AA, U+03AB - in Mono (by Ben Laenen) -- added the per ten thousand sign U+2031 (by Mederic Boquien) -- added U+2207, U+221D, U+221F, U+2227 - U+222A, and U+2261 (by David - Lawrence Ramsey) -- new logo (by Gee Fung Sit) -- added U+0180, U+018E, U+201F, U+2024, U+2025, U+203D, U+2200, U+2203, - U+2213, U+222C, U+222D, U+2263 to Sans (by Gee Fung Sit) - -Changes from 1.15 to 2.0: - -- "Italized" basic glyphs in all Serif Oblique and their Condensed faces - (by David Jez) -- added and improved TrueType instructions and related settings (by Keenan - Pepper) -- added anchor points to some glyphs (by Denis Jacquerye) -- many new spacing and combining accents (by Denis Jacquerye) -- smart substitutions for transforming i and j to dottless form and for - using uppercase diacritics (by Denis Jacquerye) -- fixed remaining erroneously slanted characters in Serif Oblique faces (by - David Lawrence Ramsey) -- copied bullet in Sans faces to Sans Oblique faces for consistency (by - David Lawrence Ramsey) -- added U+203C and U+2047-U+2049 (by David Lawrence Ramsey) -- added Greek glyphs to Serif (by Ben Laenen, Condensed merge by David Jez) -- fixed bug LTR glyphs behaving like RTL (by Ben Laenen) -- fixed wrong glyph directions (by David Jez) -- fixed repositioned accents in Condensed faces (by David Jez) - -Changes from 1.14 to 1.15: - -- added and improved TrueType instructions and related settings (by Keenan - Pepper) -- fixed U+2302, U+2319 (by David Lawrence Ramsey) -- fixed yet another monospace bug (by Stepan Roh) -- fixed potential "too big ascender/descender" bug (by Stepan Roh) -- fixed U+026E and U+028E (by Denis Jacquerye) -- added U+0186, U+0190, U+0300 - U+0304, U+0306 - U+0308, U+030A - U+030C, - U+0321, U+0322 (by Denis Jacquerye) -- added rest of Block Elements: U+2591 - U+2593 (by David Lawrence Ramsey) -- added U+2311, U+237D and U+2638 (by David Lawrence Ramsey) -- added U+01CD - U+01D4 (by Denis Jacquerye) -- fixed accents of U+00F2 - U+00F6 by replacing them with references in Mono - Bold (by David Jez) -- added U+0490, U+0491 (by Eugeniy Meshcheryakov) -- added hints to U+0404 and U+0454 in Sans (by Eugeniy Meshcheryakov) -- completed Greek glyphs from U+0370 to U+03CF in Serif (by Ben Laenen) -- fixed shape of U+0255 in Sans Bold and Sans Bold Oblique (by Denis - Jacquerye) - -Changes from 1.13 to 1.14: - -- fixed bug where Mono faces were not recognized as fixed pitch in Windows - by correcting Venda glyphs (by David Jez) -- added and improved TrueType instructions (by Keenan Pepper) -- added 6 Uzbekian glyphs (by Mashrab Kuvatov) -- added Greek glyphs to Sans and Serif, changed pi and omega to fit in (by - Ben Laenen) -- added IPA and related superscript glyphs (by Denis Jacquerye) -- fixed buggy Venda glyphs (by David Lawrence Ramsey and Stepan Roh) -- added U+2302, U+2310, U+2319 (by David Lawrence Ramsey) -- fixed slanted U+00AC in Serif Oblique faces (by David Lawrence Ramsey) -- added 29 glyphs from Block Elements (by David Lawrence Ramsey) - -Changes from 1.12 to 1.13: - -- removed all stems (PS hints) (requested by David Jez) -- added U+01D6, U+01DF, U+022B, U+022D and U+0231 (by Sander Vesik) -- added 10 Venda glyphs (by Dwayne Bailey) -- fixed bug when fonts had no name on Microsoft Windows (by Stepan Roh) -- updated 'missing' glyph U+FFFD (by David Jez) -- set TTF flag fsType to 'Installable Embedding' (= unrestricted usage) - (idea by C. Tiffany) - -Changes from 1.11 to 1.12: - -- added long s (by James Cloos) -- prettier comma accent in gcommaaccent (by David Jez) -- added Hbar, hbar, kgreenlandic, napostrophe, Eng, eng, Tbar, tbar, - afii57929 (by David Jez) -- changed Iogonek, iogonek, IJ, ij to look better (by David Jez) -- glyph uni0237 renamed to dotlessj (requested by David Jez) -- fixed accents for dcaron, lcaron, tcaron, Uogonek, uogonek in Serif (by - David Jez) -- added U+2500 - U+257F box drawing glyphs to Sans Mono (by David Jez) -- fixed accents in Wcircumflex, Ycircumflex and Zdotaccent (by David Jez) -- extra kerning for F (by Sander Vesik) -- added 'missing' glyph U+FFFD (by David Jez) - -Changes from 1.10 to 1.11: - -- kerning updates (by Sander Vesik) -- added Iogonek, iogonek, IJ, ij, Uogonek, uogonek (from SuSE standard fonts - by Adrian Schroeter, SuSE AG) -- added Gcommaaccent, gcommaaccent, Kcommaaccent, kcommaaccent, - Lcommaaccent, lcommaaccent, Ncommaaccent, ncommaaccent, Rcommaaccent, - rcommaaccent (by Stepan Roh) - -Changes from 1.9 to 1.10: - -- added U+022E, U+022F (by Sander Vesik) -- kerning updates for DejaVu Sans (by Sander Vesik) -- fixed too wide cyrillic glyphs in DejaVu Sans Mono (by Valentin Stoykov) -- fixed ligatures bug in Mono (by Stepan Roh) - -Changes from 1.8 to 1.9: - -- integrated Arev Cyrillics (by Danilo Segan) -- added U+01EA, U+01EB, U+01EC, U+01ED (by Sander Vesik) - -Changes from 1.7 to 1.8: - -- fixed accents in Serif Oblique and Serif Bold Oblique (by Stepan Roh) - -Changes from 1.6 to 1.7: - -- added automatically generated Condensed typefaces (by Stepan Roh) - -Changes from 1.5 to 1.6: - -- monospace bug fixed (by Stepan Roh) -- incorrect Bitstream foundry assigned by fontconfig and KDE Font Installer -fixed (by Stepan Roh) -- added automatically generated Oblique version of Serif typefaces (by -Stepan Roh) -- corrected cyrillic D and d (by Danilo Segan and David Jez) -- fixed accents position in Oblique version of Serif typefaces (by Danilo -Segan and Sander Vesik) -- fixed incorrect computation of OS2Win* fields (by Stepan Roh) -- added visiblespace U+2423 (by David Jez) -- fixed 'line height' bug by fixing ascender and descender values (by David -Jez and Stepan Roh) -- fixed part of 'worse than Vera' bug (by Peter Cernak) -- smaller comma accent U+0326 (by David Jez) - -Changes from 1.4 to 1.5: - -- added Cyrillics (96 characters) and Dcroat to the rest of typefaces (by -Danilo Segan) -- fixed bugs in some Cyrillic characters, some of them reported by Sander -Vesik (by Danilo Segan) -- added U+0100, U+0101, U+0112, U+0113, U+012A, U+012B, U+014C, U+014D, -U+016A, U+016B, U+01E2, U+01E3, U+0232 and U+0233 (by Sander Vesik) -- added Romanian characters (by Misu Moldovan) -- added U+0108, U+0109, U+010A, U+010B, U+0114, U+0115, U+0116, U+0117, -U+011C, U+011D, U+0120, U+0121, U+0124, U+0125, U+0128, U+0129, U+012C, -U+012D, U+0134, U+0135, U+014E, U+014F, U+0150, U+0151, U+015C, U+015D, -U+0168, U+0169, U+016C, U+016D, U+0170, U+0171 and U+0237 (by James -Crippen) -- added U+02BB, U+2010, U+2011, U+2012 and U+2015 (by Stepan Roh) - -Changes from 1.3 to 1.4: - -- added Polish characters (Aogonek, aogonek, Eogonek, eogonek, Nacute, -nacute, Sacute, sacute, Zacute, zacute, Zdotaccent, zdotaccent) (by Stepan -Roh) - -Changes from 1.2 to 1.3: - -- added Cyrillics (96 characters) and Dcroat to Sans typefaces (by Danilo -Segan from his BePa fonts) - -Changes from 1.1 to 1.2: - -- added Ldot, ldot, Wcircumflex, wcircumflex, Ycircumflex, ycircumflex, - Wgrave, wgrave, Wacute, wacute, Wdieresis, wdieresis, Ygrave and ygrave - (from The Olwen Font Family 0.2 by Dafydd Harries) - -Changes from 1.0 to 1.1: - -- added Lacute, lacute, Lcaron, lcaron, Racute and racute (by Peter Cernak) - -Changes from 0.9.4 to 1.0: - -- none, just changed version and updated README - -Changes from 0.9.3 to 0.9.4: - -- fixed TTF generation (kerning tables were missing) - -Changes from 0.9.2 to 0.9.3: - -- kerning of added characters -- proper caron shape for dcaron in Mono (by Ondrej Koala Vacha) -- minor visual changes - -Changes from 0.9.1 to 0.9.2: - -- internal bugged version - -Changes from 0.9 to 0.9.1: - -- proper caron shape for dcaron and tcaron -- minor visual changes - -$Id$ diff --git a/servo/components/gfx/tests/support/dejavu-fonts-ttf-2.37/README.md b/servo/components/gfx/tests/support/dejavu-fonts-ttf-2.37/README.md deleted file mode 100644 index 43148d7c7bfd..000000000000 --- a/servo/components/gfx/tests/support/dejavu-fonts-ttf-2.37/README.md +++ /dev/null @@ -1,67 +0,0 @@ -[![Build Status](https://travis-ci.org/dejavu-fonts/dejavu-fonts.svg)](https://travis-ci.org/dejavu-fonts/dejavu-fonts) - -DejaVu fonts 2.37 (c)2004-2016 DejaVu fonts team ------------------------------------------------- - -The DejaVu fonts are a font family based on the Bitstream Vera Fonts -(http://gnome.org/fonts/). Its purpose is to provide a wider range of -characters (see status.txt for more information) while maintaining the -original look and feel. - -DejaVu fonts are based on Bitstream Vera fonts version 1.10. - -Available fonts (Sans = sans serif, Mono = monospaced): - -DejaVu Sans Mono -DejaVu Sans Mono Bold -DejaVu Sans Mono Bold Oblique -DejaVu Sans Mono Oblique -DejaVu Sans -DejaVu Sans Bold -DejaVu Sans Bold Oblique -DejaVu Sans Oblique -DejaVu Sans ExtraLight (experimental) -DejaVu Serif -DejaVu Serif Bold -DejaVu Serif Bold Italic (experimental) -DejaVu Serif Italic (experimental) -DejaVu Sans Condensed (experimental) -DejaVu Sans Condensed Bold (experimental) -DejaVu Sans Condensed Bold Oblique (experimental) -DejaVu Sans Condensed Oblique (experimental) -DejaVu Serif Condensed (experimental) -DejaVu Serif Condensed Bold (experimental) -DejaVu Serif Condensed Bold Italic (experimental) -DejaVu Serif Condensed Italic (experimental) -DejaVu Math TeX Gyre - -All fonts are also available as derivative called DejaVu LGC with support -only for Latin, Greek and Cyrillic scripts. - -For license information see LICENSE. What's new is described in NEWS. Known -bugs are in BUGS. All authors are mentioned in AUTHORS. - -Fonts are published in source form as SFD files (Spline Font Database from -FontForge - http://fontforge.sf.net/) and in compiled form as TTF files -(TrueType fonts). - -For more information go to http://dejavu.sourceforge.net/. - -Characters from Arev fonts, Copyright (c) 2006 by Tavmjong Bah: ---------------------------- -U+01BA, U+01BF, U+01F7, U+021C-U+021D, U+0220, U+0222-U+0223, -U+02B9, U+02BA, U+02BD, U+02C2-U+02C5, U+02d4-U+02D5, -U+02D7, U+02EC-U+02EE, U+0346-U+034E, U+0360, U+0362, -U+03E2-03EF, U+0460-0463, U+0466-U+0486, U+0488-U+0489, U+04A8-U+04A9, -U+0500-U+050F, U+2055-205E, U+20B0, U+20B2-U+20B3, U+2102, U+210D, U+210F, -U+2111, U+2113, U+2115, U+2118-U+211A, U+211C-U+211D, U+2124, U+2135, -U+213C-U+2140, U+2295-U+2298, U+2308-U+230B, U+26A2-U+26B1, U+2701-U+2704, -U+2706-U+2709, U+270C-U+274B, U+2758-U+275A, U+2761-U+2775, U+2780-U+2794, -U+2798-U+27AF, U+27B1-U+27BE, U+FB05-U+FB06 - -DejaVu Math TeX Gyre --------------------- -TeX Gyre DJV Math by B. Jackowski, P. Strzelczyk and P. Pianowski -(on behalf of TeX users groups). - -$Id$ diff --git a/servo/components/gfx/tests/support/dejavu-fonts-ttf-2.37/fontconfig/20-unhint-small-dejavu-sans-mono.conf b/servo/components/gfx/tests/support/dejavu-fonts-ttf-2.37/fontconfig/20-unhint-small-dejavu-sans-mono.conf deleted file mode 100644 index 102dbcc4a8e6..000000000000 --- a/servo/components/gfx/tests/support/dejavu-fonts-ttf-2.37/fontconfig/20-unhint-small-dejavu-sans-mono.conf +++ /dev/null @@ -1,26 +0,0 @@ - - - - - - - DejaVu Sans Mono - - - 7.5 - - - false - - - diff --git a/servo/components/gfx/tests/support/dejavu-fonts-ttf-2.37/fontconfig/20-unhint-small-dejavu-sans.conf b/servo/components/gfx/tests/support/dejavu-fonts-ttf-2.37/fontconfig/20-unhint-small-dejavu-sans.conf deleted file mode 100644 index ee69996dc0b2..000000000000 --- a/servo/components/gfx/tests/support/dejavu-fonts-ttf-2.37/fontconfig/20-unhint-small-dejavu-sans.conf +++ /dev/null @@ -1,26 +0,0 @@ - - - - - - - DejaVu Sans - - - 7.5 - - - false - - - diff --git a/servo/components/gfx/tests/support/dejavu-fonts-ttf-2.37/fontconfig/20-unhint-small-dejavu-serif.conf b/servo/components/gfx/tests/support/dejavu-fonts-ttf-2.37/fontconfig/20-unhint-small-dejavu-serif.conf deleted file mode 100644 index cf6caa2cd3af..000000000000 --- a/servo/components/gfx/tests/support/dejavu-fonts-ttf-2.37/fontconfig/20-unhint-small-dejavu-serif.conf +++ /dev/null @@ -1,26 +0,0 @@ - - - - - - - DejaVu Serif - - - 7.5 - - - false - - - diff --git a/servo/components/gfx/tests/support/dejavu-fonts-ttf-2.37/fontconfig/57-dejavu-sans-mono.conf b/servo/components/gfx/tests/support/dejavu-fonts-ttf-2.37/fontconfig/57-dejavu-sans-mono.conf deleted file mode 100644 index cc42561e3826..000000000000 --- a/servo/components/gfx/tests/support/dejavu-fonts-ttf-2.37/fontconfig/57-dejavu-sans-mono.conf +++ /dev/null @@ -1,62 +0,0 @@ - - - - - - - Bepa Mono - - DejaVu Sans Mono - - - - Bitstream Prima Sans Mono - - DejaVu Sans Mono - - - - Bitstream Vera Sans Mono - - DejaVu Sans Mono - - - - DejaVu LGC Sans Mono - - DejaVu Sans Mono - - - - Olwen Sans Mono - - DejaVu Sans Mono - - - - SUSE Sans Mono - - DejaVu Sans Mono - - - - - DejaVu Sans Mono - - monospace - - - - - monospace - - DejaVu Sans Mono - - - diff --git a/servo/components/gfx/tests/support/dejavu-fonts-ttf-2.37/fontconfig/57-dejavu-sans.conf b/servo/components/gfx/tests/support/dejavu-fonts-ttf-2.37/fontconfig/57-dejavu-sans.conf deleted file mode 100644 index 565cab5fc501..000000000000 --- a/servo/components/gfx/tests/support/dejavu-fonts-ttf-2.37/fontconfig/57-dejavu-sans.conf +++ /dev/null @@ -1,87 +0,0 @@ - - - - - - - Arev Sans - - DejaVu Sans - - - - Bepa - - DejaVu Sans - - - - Bitstream Prima Sans - - DejaVu Sans - - - - Bitstream Vera Sans - - DejaVu Sans - - - - DejaVu LGC Sans - - DejaVu Sans - - - - Hunky Sans - - DejaVu Sans - - - - Olwen Sans - - DejaVu Sans - - - - SUSE Sans - - DejaVu Sans - - - - Verajja - - DejaVu Sans - - - - - VerajjaPDA - - DejaVu Sans - - - - - DejaVu Sans - - sans-serif - - - - - sans-serif - - DejaVu Sans - - - diff --git a/servo/components/gfx/tests/support/dejavu-fonts-ttf-2.37/fontconfig/57-dejavu-serif.conf b/servo/components/gfx/tests/support/dejavu-fonts-ttf-2.37/fontconfig/57-dejavu-serif.conf deleted file mode 100644 index a922e9b2dca1..000000000000 --- a/servo/components/gfx/tests/support/dejavu-fonts-ttf-2.37/fontconfig/57-dejavu-serif.conf +++ /dev/null @@ -1,69 +0,0 @@ - - - - - - - Bitstream Prima Serif - - DejaVu Serif - - - - Bitstream Vera Serif - - DejaVu Serif - - - - DejaVu LGC Serif - - DejaVu Serif - - - - Hunky Serif - - DejaVu Serif - - - - Olwen Serif - - DejaVu Serif - - - - SUSE Serif - - DejaVu Serif - - - - - Verajja Serif - - DejaVu Serif - - - - - DejaVu Serif - - serif - - - - - serif - - DejaVu Serif - - - diff --git a/servo/components/gfx/tests/support/dejavu-fonts-ttf-2.37/langcover.txt b/servo/components/gfx/tests/support/dejavu-fonts-ttf-2.37/langcover.txt deleted file mode 100644 index 75105316c4e4..000000000000 --- a/servo/components/gfx/tests/support/dejavu-fonts-ttf-2.37/langcover.txt +++ /dev/null @@ -1,250 +0,0 @@ -This is the language coverage file for DejaVu fonts -($Id$) - - Sans Serif Sans Mono -aa Afar 100% (62/62) 100% (62/62) 100% (62/62) -ab Abkhazia 100% (90/90) 93% (84/90) 84% (76/90) -af Afrikaans 100% (69/69) 100% (69/69) 100% (69/69) -ak Akan 100% (73/73) 100% (73/73) 100% (73/73) -am Amharic (0/264) (0/264) (0/264) -an Aragonese 100% (66/66) 100% (66/66) 100% (66/66) -ar Arabic 100% (36/36) (0/36) 100% (36/36) -as Assamese (0/64) (0/64) (0/64) -ast Asturian/Bable/Leonese/Asturleonese 100% (70/70) 100% (70/70) 100% (70/70) -av Avaric 100% (67/67) 100% (67/67) 100% (67/67) -ay Aymara 100% (60/60) 100% (60/60) 100% (60/60) -az-az Azerbaijani in Azerbaijan 100% (66/66) 100% (66/66) 100% (66/66) -az-ir Azerbaijani in Iran 100% (40/40) (0/40) 100% (40/40) -ba Bashkir 100% (82/82) 100% (82/82) 97% (80/82) -be Byelorussian 100% (68/68) 100% (68/68) 100% (68/68) -ber-dz Berber in Algeria 100% (70/70) 100% (70/70) 100% (70/70) -ber-ma Berber in Morocco 100% (32/32) (0/32) (0/32) -bg Bulgarian 100% (60/60) 100% (60/60) 100% (60/60) -bh Bihari (Devanagari script) (0/68) (0/68) (0/68) -bho Bhojpuri (Devanagari script) (0/68) (0/68) (0/68) -bi Bislama 100% (58/58) 100% (58/58) 100% (58/58) -bin Edo or Bini 100% (78/78) 100% (78/78) 100% (78/78) -bm Bambara 100% (60/60) 100% (60/60) 100% (60/60) -bn Bengali (0/63) (0/63) (0/63) -bo Tibetan (0/95) (0/95) (0/95) -br Breton 100% (64/64) 100% (64/64) 100% (64/64) -brx Bodo (Devanagari script) (0/82) (0/82) (0/82) -bs Bosnian 100% (62/62) 100% (62/62) 100% (62/62) -bua Buriat (Buryat) 100% (70/70) 100% (70/70) 100% (70/70) -byn Blin/Bilin (0/255) (0/255) (0/255) -ca Catalan 100% (74/74) 100% (74/74) 100% (74/74) -ce Chechen 100% (67/67) 100% (67/67) 100% (67/67) -ch Chamorro 100% (58/58) 100% (58/58) 100% (58/58) -chm Mari (Lower Cheremis / Upper Cheremis) 100% (76/76) 100% (76/76) 100% (76/76) -chr Cherokee (0/85) (0/85) (0/85) -co Corsican 100% (84/84) 100% (84/84) 100% (84/84) -crh Crimean Tatar/Crimean Turkish 100% (68/68) 100% (68/68) 100% (68/68) -cs Czech 100% (82/82) 100% (82/82) 100% (82/82) -csb Kashubian 100% (74/74) 100% (74/74) 100% (74/74) -cu Old Church Slavonic 100% (103/103) 90% (93/103) 78% (81/103) -cv Chuvash 100% (74/74) 100% (74/74) 100% (74/74) -cy Welsh 100% (78/78) 100% (78/78) 100% (78/78) -da Danish 100% (70/70) 100% (70/70) 100% (70/70) -de German 100% (59/59) 100% (59/59) 100% (59/59) -doi Dogri (0/85) (0/85) (0/85) -dv Divehi/Dhivehi/Maldivian (0/49) (0/49) (0/49) -dz Dzongkha (0/95) (0/95) (0/95) -ee Ewe 100% (99/99) 100% (99/99) 100% (99/99) -el Greek 100% (69/69) 100% (69/69) 100% (69/69) -en English 100% (72/72) 100% (72/72) 100% (72/72) -eo Esperanto 100% (64/64) 100% (64/64) 100% (64/64) -es Spanish 100% (66/66) 100% (66/66) 100% (66/66) -et Estonian 100% (64/64) 100% (64/64) 100% (64/64) -eu Basque 100% (56/56) 100% (56/56) 100% (56/56) -fa Persian 100% (40/40) (0/40) 100% (40/40) -fat Fanti 100% (73/73) 100% (73/73) 100% (73/73) -ff Fulah (Fula) 100% (62/62) 100% (62/62) 100% (62/62) -fi Finnish 100% (62/62) 100% (62/62) 100% (62/62) -fil Filipino 100% (84/84) 100% (84/84) 100% (84/84) -fj Fijian 100% (52/52) 100% (52/52) 100% (52/52) -fo Faroese 100% (68/68) 100% (68/68) 100% (68/68) -fr French 100% (84/84) 100% (84/84) 100% (84/84) -fur Friulian 100% (66/66) 100% (66/66) 100% (66/66) -fy Frisian 100% (75/75) 100% (75/75) 100% (75/75) -ga Irish 100% (80/80) 100% (80/80) 100% (80/80) -gd Scots Gaelic 100% (70/70) 100% (70/70) 100% (70/70) -gez Ethiopic (Geez) (0/218) (0/218) (0/218) -gl Galician 100% (66/66) 100% (66/66) 100% (66/66) -gn Guarani 100% (70/70) 100% (70/70) 100% (70/70) -gu Gujarati (0/68) (0/68) (0/68) -gv Manx Gaelic 100% (54/54) 100% (54/54) 100% (54/54) -ha Hausa 100% (60/60) 100% (60/60) 100% (60/60) -haw Hawaiian 100% (63/63) 100% (63/63) 100% (63/63) -he Hebrew 100% (27/27) (0/27) (0/27) -hi Hindi (Devanagari script) (0/68) (0/68) (0/68) -hne Chhattisgarhi (0/68) (0/68) (0/68) -ho Hiri Motu 100% (52/52) 100% (52/52) 100% (52/52) -hr Croatian 100% (62/62) 100% (62/62) 100% (62/62) -hsb Upper Sorbian 100% (72/72) 100% (72/72) 100% (72/72) -ht Haitian/Haitian Creole 100% (56/56) 100% (56/56) 100% (56/56) -hu Hungarian 100% (70/70) 100% (70/70) 100% (70/70) -hy Armenian 100% (77/77) 100% (77/77) 100% (77/77) -hz Herero 100% (57/57) 100% (57/57) 100% (57/57) -ia Interlingua 100% (52/52) 100% (52/52) 100% (52/52) -id Indonesian 100% (54/54) 100% (54/54) 100% (54/54) -ie Interlingue 100% (52/52) 100% (52/52) 100% (52/52) -ig Igbo 100% (58/58) 100% (58/58) 100% (58/58) -ii Sichuan Yi/Nuosu (0/1165) (0/1165) (0/1165) -ik Inupiaq (Inupiak, Eskimo) 100% (68/68) 100% (68/68) 100% (68/68) -io Ido 100% (52/52) 100% (52/52) 100% (52/52) -is Icelandic 100% (70/70) 100% (70/70) 100% (70/70) -it Italian 100% (72/72) 100% (72/72) 100% (72/72) -iu Inuktitut 100% (161/161) (0/161) (0/161) -ja Japanese (0/2314) (0/2314) (0/2314) -jv Javanese 100% (56/56) 100% (56/56) 100% (56/56) -ka Georgian 100% (33/33) 100% (33/33) 100% (33/33) -kaa Kara-Kalpak (Karakalpak) 100% (78/78) 100% (78/78) 100% (78/78) -kab Kabyle 100% (70/70) 100% (70/70) 100% (70/70) -ki Kikuyu 100% (56/56) 100% (56/56) 100% (56/56) -kj Kuanyama/Kwanyama 100% (52/52) 100% (52/52) 100% (52/52) -kk Kazakh 100% (77/77) 100% (77/77) 100% (77/77) -kl Greenlandic 100% (81/81) 100% (81/81) 100% (81/81) -km Central Khmer (0/63) (0/63) (0/63) -kn Kannada (0/70) (0/70) (0/70) -ko Korean (0/2442) (0/2442) (0/2442) -kok Kokani (Devanagari script) (0/68) (0/68) (0/68) -kr Kanuri 100% (56/56) 100% (56/56) 100% (56/56) -ks Kashmiri 78% (26/33) (0/33) 69% (23/33) -ku-am Kurdish in Armenia 100% (64/64) 100% (64/64) 100% (64/64) -ku-iq Kurdish in Iraq 100% (32/32) (0/32) 87% (28/32) -ku-ir Kurdish in Iran 100% (32/32) (0/32) 87% (28/32) -ku-tr Kurdish in Turkey 100% (62/62) 100% (62/62) 100% (62/62) -kum Kumyk 100% (66/66) 100% (66/66) 100% (66/66) -kv Komi (Komi-Permyak/Komi-Siryan) 100% (70/70) 100% (70/70) 100% (70/70) -kw Cornish 100% (64/64) 100% (64/64) 100% (64/64) -kwm Kwambi 100% (52/52) 100% (52/52) 100% (52/52) -ky Kirgiz 100% (70/70) 100% (70/70) 100% (70/70) -la Latin 100% (68/68) 100% (68/68) 100% (68/68) -lah Lahnda 92% (25/27) (0/27) 85% (23/27) -lb Luxembourgish (Letzeburgesch) 100% (75/75) 100% (75/75) 100% (75/75) -lez Lezghian (Lezgian) 100% (67/67) 100% (67/67) 100% (67/67) -lg Ganda 100% (54/54) 100% (54/54) 100% (54/54) -li Limburgan/Limburger/Limburgish 100% (62/62) 100% (62/62) 100% (62/62) -ln Lingala 100% (81/81) 100% (81/81) 100% (81/81) -lo Lao 100% (55/55) (0/55) 83% (46/55) -lt Lithuanian 100% (70/70) 100% (70/70) 100% (70/70) -lv Latvian 100% (78/78) 100% (78/78) 100% (78/78) -mai Maithili (Devanagari script) (0/68) (0/68) (0/68) -mg Malagasy 100% (56/56) 100% (56/56) 100% (56/56) -mh Marshallese 100% (62/62) 100% (62/62) 100% (62/62) -mi Maori 100% (64/64) 100% (64/64) 100% (64/64) -mk Macedonian 100% (42/42) 100% (42/42) 100% (42/42) -ml Malayalam (0/68) (0/68) (0/68) -mn-cn Mongolian in China (0/130) (0/130) (0/130) -mn-mn Mongolian in Mongolia 100% (70/70) 100% (70/70) 100% (70/70) -mni Maniputi (0/78) (0/78) (0/78) -mo Moldavian 100% (128/128) 100% (128/128) 100% (128/128) -mr Marathi (Devanagari script) (0/68) (0/68) (0/68) -ms Malay 100% (52/52) 100% (52/52) 100% (52/52) -mt Maltese 100% (72/72) 100% (72/72) 100% (72/72) -my Burmese (Myanmar) (0/48) (0/48) (0/48) -na Nauru 100% (60/60) 100% (60/60) 100% (60/60) -nb Norwegian Bokmal 100% (70/70) 100% (70/70) 100% (70/70) -nds Low Saxon 100% (59/59) 100% (59/59) 100% (59/59) -ne Nepali (0/72) (0/72) (0/72) -ng Ndonga 100% (52/52) 100% (52/52) 100% (52/52) -nl Dutch 100% (82/82) 100% (82/82) 100% (82/82) -nn Norwegian Nynorsk 100% (76/76) 100% (76/76) 100% (76/76) -no Norwegian (Bokmal) 100% (70/70) 100% (70/70) 100% (70/70) -nqo N'Ko 91% (54/59) (0/59) (0/59) -nr Ndebele, South 100% (52/52) 100% (52/52) 100% (52/52) -nso Northern Sotho 100% (58/58) 100% (58/58) 100% (58/58) -nv Navajo/Navaho 100% (72/72) 100% (72/72) 100% (72/72) -ny Chichewa 100% (54/54) 100% (54/54) 100% (54/54) -oc Occitan 100% (70/70) 100% (70/70) 100% (70/70) -om Oromo or Galla 100% (52/52) 100% (52/52) 100% (52/52) -or Oriya (0/68) (0/68) (0/68) -os Ossetic 100% (66/66) 100% (66/66) 100% (66/66) -ota Ottoman Turkish 100% (37/37) (0/37) 97% (36/37) -pa Panjabi/Punjabi (0/63) (0/63) (0/63) -pa-pk Panjabi/Punjabi in Pakistan 92% (25/27) (0/27) 85% (23/27) -pap-an Papiamento in Netherlands Antilles 100% (72/72) 100% (72/72) 100% (72/72) -pap-aw Papiamento in Aruba 100% (54/54) 100% (54/54) 100% (54/54) -pes Western Farsi 100% (40/40) (0/40) 100% (40/40) -pl Polish 100% (70/70) 100% (70/70) 100% (70/70) -prs Dari/Eastern Farsi 100% (40/40) (0/40) 100% (40/40) -ps-af Pashto in Afghanistan 97% (48/49) (0/49) 77% (38/49) -ps-pk Pashto in Pakistan 95% (47/49) (0/49) 75% (37/49) -pt Portuguese 100% (82/82) 100% (82/82) 100% (82/82) -qu Quechua 100% (55/55) 100% (55/55) 100% (55/55) -quz Cusco Quechua 100% (55/55) 100% (55/55) 100% (55/55) -rm Rhaeto-Romance (Romansch) 100% (66/66) 100% (66/66) 100% (66/66) -rn Rundi 100% (52/52) 100% (52/52) 100% (52/52) -ro Romanian 100% (62/62) 100% (62/62) 100% (62/62) -ru Russian 100% (66/66) 100% (66/66) 100% (66/66) -rw Kinyarwanda 100% (52/52) 100% (52/52) 100% (52/52) -sa Sanskrit (Devanagari script) (0/68) (0/68) (0/68) -sah Yakut 100% (76/76) 100% (76/76) 100% (76/76) -sat Santali (Devanagari script) (0/70) (0/70) (0/70) -sc Sardinian 100% (62/62) 100% (62/62) 100% (62/62) -sco Scots 100% (56/56) 100% (56/56) 100% (56/56) -sd Sindhi 100% (54/54) (0/54) 79% (43/54) -se North Sami 100% (66/66) 100% (66/66) 100% (66/66) -sel Selkup (Ostyak-Samoyed) 100% (66/66) 100% (66/66) 100% (66/66) -sg Sango 100% (72/72) 100% (72/72) 100% (72/72) -sh Serbo-Croatian 100% (156/156) 100% (156/156) 98% (154/156) -shs Secwepemctsin 100% (48/48) 100% (48/48) 100% (48/48) -si Sinhala/Sinhalese (0/73) (0/73) (0/73) -sid Sidamo (0/281) (0/281) (0/281) -sk Slovak 100% (86/86) 100% (86/86) 100% (86/86) -sl Slovenian 100% (62/62) 100% (62/62) 100% (62/62) -sm Samoan 100% (53/53) 100% (53/53) 100% (53/53) -sma South Sami 100% (60/60) 100% (60/60) 100% (60/60) -smj Lule Sami 100% (60/60) 100% (60/60) 100% (60/60) -smn Inari Sami 100% (68/68) 100% (68/68) 100% (68/68) -sms Skolt Sami 100% (80/80) 100% (80/80) 97% (78/80) -sn Shona 100% (52/52) 100% (52/52) 100% (52/52) -so Somali 100% (52/52) 100% (52/52) 100% (52/52) -sq Albanian 100% (56/56) 100% (56/56) 100% (56/56) -sr Serbian 100% (60/60) 100% (60/60) 100% (60/60) -ss Swati 100% (52/52) 100% (52/52) 100% (52/52) -st Sotho, Southern 100% (52/52) 100% (52/52) 100% (52/52) -su Sundanese 100% (54/54) 100% (54/54) 100% (54/54) -sv Swedish 100% (68/68) 100% (68/68) 100% (68/68) -sw Swahili 100% (52/52) 100% (52/52) 100% (52/52) -syr Syriac (0/45) (0/45) (0/45) -ta Tamil (0/48) (0/48) (0/48) -te Telugu (0/70) (0/70) (0/70) -tg Tajik 100% (78/78) 100% (78/78) 97% (76/78) -th Thai 1% (1/74) 1% (1/74) 1% (1/74) -ti-er Eritrean Tigrinya (0/255) (0/255) (0/255) -ti-et Ethiopian Tigrinya (0/281) (0/281) (0/281) -tig Tigre (0/221) (0/221) (0/221) -tk Turkmen 100% (68/68) 100% (68/68) 100% (68/68) -tl Tagalog 100% (84/84) 100% (84/84) 100% (84/84) -tn Tswana 100% (58/58) 100% (58/58) 100% (58/58) -to Tonga 100% (53/53) 100% (53/53) 100% (53/53) -tr Turkish 100% (70/70) 100% (70/70) 100% (70/70) -ts Tsonga 100% (52/52) 100% (52/52) 100% (52/52) -tt Tatar 100% (76/76) 100% (76/76) 100% (76/76) -tw Twi 100% (73/73) 100% (73/73) 100% (73/73) -ty Tahitian 100% (65/65) 100% (65/65) 100% (65/65) -tyv Tuvinian 100% (70/70) 100% (70/70) 100% (70/70) -ug Uyghur 100% (33/33) (0/33) 78% (26/33) -uk Ukrainian 100% (72/72) 100% (72/72) 100% (72/72) -ur Urdu 92% (25/27) (0/27) 85% (23/27) -uz Uzbek 100% (52/52) 100% (52/52) 100% (52/52) -ve Venda 100% (62/62) 100% (62/62) 100% (62/62) -vi Vietnamese 100% (194/194) 100% (194/194) 76% (148/194) -vo Volapuk 100% (54/54) 100% (54/54) 100% (54/54) -vot Votic 100% (62/62) 100% (62/62) 100% (62/62) -wa Walloon 100% (70/70) 100% (70/70) 100% (70/70) -wal Wolaitta/Wolaytta (0/281) (0/281) (0/281) -wen Sorbian languages (lower and upper) 100% (76/76) 100% (76/76) 100% (76/76) -wo Wolof 100% (66/66) 100% (66/66) 100% (66/66) -xh Xhosa 100% (52/52) 100% (52/52) 100% (52/52) -yap Yapese 100% (58/58) 100% (58/58) 100% (58/58) -yi Yiddish 100% (27/27) (0/27) (0/27) -yo Yoruba 100% (119/119) 100% (119/119) 100% (119/119) -za Zhuang/Chuang 100% (52/52) 100% (52/52) 100% (52/52) -zh-cn Chinese (simplified) 0% (2/6765) 0% (2/6765) 0% (2/6765) -zh-hk Chinese Hong Kong Supplementary Character Set (0/1083) (0/1083) (0/1083) -zh-mo Chinese in Macau (0/1083) (0/1083) (0/1083) -zh-sg Chinese in Singapore 0% (2/6765) 0% (2/6765) 0% (2/6765) -zh-tw Chinese (traditional) (0/13063) (0/13063) (0/13063) -zu Zulu 100% (52/52) 100% (52/52) 100% (52/52) diff --git a/servo/components/gfx/tests/support/dejavu-fonts-ttf-2.37/status.txt b/servo/components/gfx/tests/support/dejavu-fonts-ttf-2.37/status.txt deleted file mode 100644 index 8b78cf38be5a..000000000000 --- a/servo/components/gfx/tests/support/dejavu-fonts-ttf-2.37/status.txt +++ /dev/null @@ -1,7143 +0,0 @@ -This is the status file for DejaVu fonts -($Id$) - -original = present in original Bitstream Vera 1.10 - = added in DejaVu fonts - -U+0020 space original -U+0021 exclam original -U+0022 quotedbl original -U+0023 numbersign original -U+0024 dollar original -U+0025 percent original -U+0026 ampersand original -U+0027 quotesingle original -U+0028 parenleft original -U+0029 parenright original -U+002a asterisk original -U+002b plus original -U+002c comma original -U+002d hyphen original -U+002e period original -U+002f slash original -U+0030 zero original -U+0031 one original -U+0032 two original -U+0033 three original -U+0034 four original -U+0035 five original -U+0036 six original -U+0037 seven original -U+0038 eight original -U+0039 nine original -U+003a colon original -U+003b semicolon original -U+003c less original -U+003d equal original -U+003e greater original -U+003f question original -U+0040 at original -U+0041 A original -U+0042 B original -U+0043 C original -U+0044 D original -U+0045 E original -U+0046 F original -U+0047 G original -U+0048 H original -U+0049 I original -U+004a J original -U+004b K original -U+004c L original -U+004d M original -U+004e N original -U+004f O original -U+0050 P original -U+0051 Q original -U+0052 R original -U+0053 S original -U+0054 T original -U+0055 U original -U+0056 V original -U+0057 W original -U+0058 X original -U+0059 Y original -U+005a Z original -U+005b bracketleft original -U+005c backslash original -U+005d bracketright original -U+005e asciicircum original -U+005f underscore original -U+0060 grave original -U+0061 a original -U+0062 b original -U+0063 c original -U+0064 d original -U+0065 e original -U+0066 f original -U+0067 g original -U+0068 h original -U+0069 i original -U+006a j original -U+006b k original -U+006c l original -U+006d m original -U+006e n original -U+006f o original -U+0070 p original -U+0071 q original -U+0072 r original -U+0073 s original -U+0074 t original -U+0075 u original -U+0076 v original -U+0077 w original -U+0078 x original -U+0079 y original -U+007a z original -U+007b braceleft original -U+007c bar original -U+007d braceright original -U+007e asciitilde original -U+00a0 nonbreakingspace original -U+00a1 exclamdown original -U+00a2 cent original -U+00a3 sterling original -U+00a4 currency original -U+00a5 yen original -U+00a6 brokenbar original -U+00a7 section original -U+00a8 dieresis original -U+00a9 copyright original -U+00aa ordfeminine original -U+00ab guillemotleft original -U+00ac logicalnot original -U+00ad sfthyphen original -U+00ae registered original -U+00af macron original -U+00b0 degree original -U+00b1 plusminus original -U+00b2 twosuperior original -U+00b3 threesuperior original -U+00b4 acute original -U+00b5 mu original -U+00b6 paragraph original -U+00b7 periodcentered original -U+00b8 cedilla original -U+00b9 onesuperior original -U+00ba ordmasculine original -U+00bb guillemotright original -U+00bc onequarter original -U+00bd onehalf original -U+00be threequarters original -U+00bf questiondown original -U+00c0 Agrave original -U+00c1 Aacute original -U+00c2 Acircumflex original -U+00c3 Atilde original -U+00c4 Adieresis original -U+00c5 Aring original -U+00c6 AE original -U+00c7 Ccedilla original -U+00c8 Egrave original -U+00c9 Eacute original -U+00ca Ecircumflex original -U+00cb Edieresis original -U+00cc Igrave original -U+00cd Iacute original -U+00ce Icircumflex original -U+00cf Idieresis original -U+00d0 Eth original -U+00d1 Ntilde original -U+00d2 Ograve original -U+00d3 Oacute original -U+00d4 Ocircumflex original -U+00d5 Otilde original -U+00d6 Odieresis original -U+00d7 multiply original -U+00d8 Oslash original -U+00d9 Ugrave original -U+00da Uacute original -U+00db Ucircumflex original -U+00dc Udieresis original -U+00dd Yacute original -U+00de Thorn original -U+00df germandbls original -U+00e0 agrave original -U+00e1 aacute original -U+00e2 acircumflex original -U+00e3 atilde original -U+00e4 adieresis original -U+00e5 aring original -U+00e6 ae original -U+00e7 ccedilla original -U+00e8 egrave original -U+00e9 eacute original -U+00ea ecircumflex original -U+00eb edieresis original -U+00ec igrave original -U+00ed iacute original -U+00ee icircumflex original -U+00ef idieresis original -U+00f0 eth original -U+00f1 ntilde original -U+00f2 ograve original -U+00f3 oacute original -U+00f4 ocircumflex original -U+00f5 otilde original -U+00f6 odieresis original -U+00f7 divide original -U+00f8 oslash original -U+00f9 ugrave original -U+00fa uacute original -U+00fb ucircumflex original -U+00fc udieresis original -U+00fd yacute original -U+00fe thorn original -U+00ff ydieresis original -U+0100 Amacron 1.5 -U+0101 amacron 1.5 -U+0102 Abreve 1.5 -U+0103 abreve 1.5 -U+0104 Aogonek 1.4 -U+0105 aogonek 1.4 -U+0106 Cacute original -U+0107 cacute original -U+0108 Ccircumflex 1.5 -U+0109 ccircumflex 1.5 -U+010a Cdotaccent 1.5 -U+010b cdotaccent 1.5 -U+010c Ccaron original -U+010d ccaron original -U+010e Dcaron 1.0 -U+010f dcaron 1.0 -U+0110 Dcroat 1.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Oblique) 1.5 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Serif, Serif Bold) 1.6 (Serif Bold Italic, Serif Italic) 1.7 (Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic) 2.4 (Sans ExtraLight) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) -U+0111 dcroat original -U+0112 Emacron 1.5 -U+0113 emacron 1.5 -U+0114 Ebreve 1.5 -U+0115 ebreve 1.5 -U+0116 Edotaccent 1.5 -U+0117 edotaccent 1.5 -U+0118 Eogonek 1.4 -U+0119 eogonek 1.4 -U+011a Ecaron 1.0 -U+011b ecaron 1.0 -U+011c Gcircumflex 1.5 -U+011d gcircumflex 1.5 -U+011e Gbreve original -U+011f gbreve original -U+0120 Gdotaccent 1.5 -U+0121 gdotaccent 1.5 -U+0122 Gcommaaccent 1.11 -U+0123 gcommaaccent 1.11 -U+0124 Hcircumflex 1.5 -U+0125 hcircumflex 1.5 -U+0126 Hbar 1.12 -U+0127 hbar 1.12 -U+0128 Itilde 1.5 -U+0129 itilde 1.5 -U+012a Imacron 1.5 -U+012b imacron 1.5 -U+012c Ibreve 1.5 -U+012d ibreve 1.5 -U+012e Iogonek 1.11 -U+012f iogonek 1.11 -U+0130 Idotaccent original -U+0131 dotlessi original -U+0132 IJ 1.11 -U+0133 ij 1.11 -U+0134 Jcircumflex 1.5 -U+0135 jcircumflex 1.5 -U+0136 Kcommaaccent 1.11 -U+0137 kcommaaccent 1.11 -U+0138 kgreenlandic 1.12 -U+0139 Lacute 1.1 -U+013a lacute 1.1 -U+013b Lcommaaccent 1.11 -U+013c lcommaaccent 1.11 -U+013d Lcaron 1.1 -U+013e lcaron 1.1 -U+013f Ldot 1.2 -U+0140 ldot 1.2 -U+0141 Lslash original -U+0142 lslash original -U+0143 Nacute 1.4 -U+0144 nacute 1.4 -U+0145 Ncommaaccent 1.11 -U+0146 ncommaaccent 1.11 -U+0147 Ncaron 1.0 -U+0148 ncaron 1.0 -U+0149 napostrophe 1.12 -U+014a Eng 1.12 -U+014b eng 1.12 -U+014c Omacron 1.5 -U+014d omacron 1.5 -U+014e Obreve 1.5 -U+014f obreve 1.5 -U+0150 Ohungarumlaut 1.5 -U+0151 ohungarumlaut 1.5 -U+0152 OE original -U+0153 oe original -U+0154 Racute 1.1 -U+0155 racute 1.1 -U+0156 Rcommaaccent 1.11 -U+0157 rcommaaccent 1.11 -U+0158 Rcaron 1.0 -U+0159 rcaron 1.0 -U+015a Sacute 1.4 -U+015b sacute 1.4 -U+015c Scircumflex 1.5 -U+015d scircumflex 1.5 -U+015e Scedilla original -U+015f scedilla original -U+0160 Scaron original -U+0161 scaron original -U+0162 Tcommaaccent 1.5 -U+0163 tcommaaccent 1.5 -U+0164 Tcaron 1.0 -U+0165 tcaron 1.0 -U+0166 Tbar 1.12 -U+0167 tbar 1.12 -U+0168 Utilde 1.5 -U+0169 utilde 1.5 -U+016a Umacron 1.5 -U+016b umacron 1.5 -U+016c Ubreve 1.5 -U+016d ubreve 1.5 -U+016e Uring 1.0 -U+016f uring 1.0 -U+0170 Uhungarumlaut 1.5 -U+0171 uhungarumlaut 1.5 -U+0172 Uogonek 1.11 -U+0173 uogonek 1.11 -U+0174 Wcircumflex 1.2 -U+0175 wcircumflex 1.2 -U+0176 Ycircumflex 1.2 -U+0177 ycircumflex 1.2 -U+0178 Ydieresis original -U+0179 Zacute 1.4 -U+017a zacute 1.4 -U+017b Zdotaccent 1.4 -U+017c zdotaccent 1.4 -U+017d Zcaron original -U+017e zcaron original -U+017f longs 1.12 -U+0180 uni0180 2.1 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.4 (Sans ExtraLight) 2.12 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.22 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.23 (Serif Italic Condensed) -U+0181 uni0181 2.2 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.3 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.4 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+0182 uni0182 2.2 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.3 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.4 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+0183 uni0183 2.2 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.3 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.4 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+0184 uni0184 2.3 -U+0185 uni0185 2.3 -U+0186 uni0186 1.15 -U+0187 uni0187 2.2 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.3 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.4 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+0188 uni0188 2.2 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.3 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.4 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+0189 uni0189 2.1 -U+018a uni018A 2.2 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.3 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.4 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+018b uni018B 2.2 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.3 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.4 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+018c uni018C 2.2 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.3 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.4 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+018d uni018D 2.2 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.3 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.5 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+018e uni018E 2.1 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.3 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.4 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+018f uni018F 2.2 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.3 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.4 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+0190 uni0190 1.15 -U+0191 uni0191 2.2 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.3 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.4 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+0192 florin original -U+0193 uni0193 2.2 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.3 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.4 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+0194 uni0194 1.14 -U+0195 uni0195 2.2 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.3 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.6 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+0196 uni0196 2.2 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.3 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.4 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+0197 uni0197 2.2 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.3 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.4 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+0198 uni0198 2.2 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.3 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.4 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+0199 uni0199 2.2 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.3 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.4 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+019a uni019A 2.2 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.3 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.4 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+019b uni019B 2.2 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.3 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.35 (Sans ExtraLight) -U+019c uni019C 2.3 -U+019d uni019D 2.2 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.3 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.4 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+019e uni019E 2.2 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.3 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.4 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+019f uni019F 2.3 -U+01a0 Ohorn 2.3 -U+01a1 ohorn 2.3 -U+01a2 uni01A2 2.3 -U+01a3 uni01A3 2.3 -U+01a4 uni01A4 2.2 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.3 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.4 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+01a5 uni01A5 2.2 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.3 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.4 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+01a6 uni01A6 2.3 -U+01a7 uni01A7 2.2 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.3 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.4 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+01a8 uni01A8 2.2 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.3 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.4 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+01a9 uni01A9 2.2 -U+01aa uni01AA 2.3 -U+01ab uni01AB 2.2 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.3 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.4 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+01ac uni01AC 2.2 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.3 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.4 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+01ad uni01AD 2.2 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.3 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.4 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+01ae uni01AE 2.2 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.3 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.4 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+01af Uhorn 2.3 -U+01b0 uhorn 2.3 -U+01b1 uni01B1 2.2 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.3 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.4 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+01b2 uni01B2 2.3 -U+01b3 uni01B3 2.3 -U+01b4 uni01B4 2.3 -U+01b5 uni01B5 2.2 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.3 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.4 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+01b6 uni01B6 2.2 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.3 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.4 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+01b7 uni01B7 2.3 -U+01b8 uni01B8 2.3 -U+01b9 uni01B9 2.3 -U+01ba uni01BA 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.26 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.33 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) -U+01bb uni01BB 2.2 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.3 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+01bc uni01BC 2.3 -U+01bd uni01BD 2.3 -U+01be uni01BE 2.3 -U+01bf uni01BF 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.26 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.32 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) -U+01c0 uni01C0 2.2 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.3 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.4 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+01c1 uni01C1 2.2 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.3 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.4 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+01c2 uni01C2 2.2 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.3 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.4 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+01c3 uni01C3 2.2 -U+01c4 uni01C4 1.9 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.4 (Sans ExtraLight, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+01c5 uni01C5 1.9 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.4 (Sans ExtraLight, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+01c6 uni01C6 1.9 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.4 (Sans ExtraLight, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+01c7 uni01C7 1.9 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.4 (Sans ExtraLight, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+01c8 uni01C8 1.9 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.4 (Sans ExtraLight, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+01c9 uni01C9 1.9 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.4 (Sans ExtraLight, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+01ca uni01CA 1.9 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.4 (Sans ExtraLight, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+01cb uni01CB 1.9 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.4 (Sans ExtraLight, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+01cc uni01CC 1.9 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.4 (Sans ExtraLight, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+01cd uni01CD 1.15 -U+01ce uni01CE 1.15 -U+01cf uni01CF 1.15 -U+01d0 uni01D0 1.15 -U+01d1 uni01D1 1.15 -U+01d2 uni01D2 1.15 -U+01d3 uni01D3 1.15 -U+01d4 uni01D4 1.15 -U+01d5 uni01D5 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.22 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.23 (Serif Italic Condensed) -U+01d6 uni01D6 1.13 -U+01d7 uni01D7 2.3 -U+01d8 uni01D8 2.3 -U+01d9 uni01D9 2.3 -U+01da uni01DA 2.3 -U+01db uni01DB 2.3 -U+01dc uni01DC 2.3 -U+01dd uni01DD 2.2 -U+01de uni01DE 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.22 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique) 2.23 (Serif Italic Condensed) -U+01df uni01DF 1.13 -U+01e0 uni01E0 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.22 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.23 (Serif Italic Condensed) -U+01e1 uni01E1 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.22 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.23 (Serif Italic Condensed) -U+01e2 uni01E2 1.5 -U+01e3 uni01E3 1.5 -U+01e4 uni01E4 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.7 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.26 (Sans ExtraLight) -U+01e5 uni01E5 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.7 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.26 (Sans ExtraLight) -U+01e6 Gcaron 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.13 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.23 (Serif Italic Condensed) -U+01e7 gcaron 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.13 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.23 (Serif Italic Condensed) -U+01e8 uni01E8 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.13 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.23 (Serif Italic Condensed) -U+01e9 uni01E9 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.13 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.23 (Serif Italic Condensed) -U+01ea uni01EA 1.9 -U+01eb uni01EB 1.9 -U+01ec uni01EC 1.9 -U+01ed uni01ED 1.9 -U+01ee uni01EE 2.4 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.13 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.23 (Serif Italic Condensed) 2.35 (Sans ExtraLight) -U+01ef uni01EF 2.4 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.13 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.23 (Serif Italic Condensed) 2.35 (Sans ExtraLight) -U+01f0 uni01F0 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.13 (Sans Mono) 2.22 (Sans Mono Bold) 2.23 (Serif Italic Condensed) -U+01f1 uni01F1 2.2 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.4 (Sans ExtraLight, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+01f2 uni01F2 2.2 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.4 (Sans ExtraLight, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+01f3 uni01F3 2.2 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.4 (Sans ExtraLight, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+01f4 uni01F4 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.13 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.23 (Serif Italic Condensed) -U+01f5 uni01F5 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.13 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.23 (Serif Italic Condensed) -U+01f6 uni01F6 2.3 -U+01f7 uni01F7 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.32 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) -U+01f8 uni01F8 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.7 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.23 (Serif Italic Condensed) -U+01f9 uni01F9 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.7 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.23 (Serif Italic Condensed) -U+01fa Aringacute 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) 2.7 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+01fb aringacute 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) 2.7 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+01fc AEacute 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.13 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.23 (Serif Italic Condensed) -U+01fd aeacute 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.13 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.23 (Serif Italic Condensed) -U+01fe Oslashacute 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.13 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.23 (Serif Italic Condensed) -U+01ff oslashacute 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.13 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.23 (Serif Italic Condensed) -U+0200 uni0200 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.14 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.23 (Serif Italic Condensed) -U+0201 uni0201 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.14 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.23 (Serif Italic Condensed) -U+0202 uni0202 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.14 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.23 (Serif Italic Condensed) -U+0203 uni0203 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.14 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.23 (Serif Italic Condensed) -U+0204 uni0204 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.14 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.23 (Serif Italic Condensed) -U+0205 uni0205 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.14 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.23 (Serif Italic Condensed) -U+0206 uni0206 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.14 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.23 (Serif Italic Condensed) -U+0207 uni0207 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.14 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.23 (Serif Italic Condensed) -U+0208 uni0208 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.14 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.23 (Serif Italic Condensed) -U+0209 uni0209 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.14 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.23 (Serif Italic Condensed) -U+020a uni020A 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.14 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.23 (Serif Italic Condensed) -U+020b uni020B 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.14 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.23 (Serif Italic Condensed) -U+020c uni020C 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.14 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.23 (Serif Italic Condensed) -U+020d uni020D 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.14 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.23 (Serif Italic Condensed) -U+020e uni020E 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.14 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.23 (Serif Italic Condensed) -U+020f uni020F 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.14 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.23 (Serif Italic Condensed) -U+0210 uni0210 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.14 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.23 (Serif Italic Condensed) -U+0211 uni0211 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.14 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.23 (Serif Italic Condensed) -U+0212 uni0212 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.14 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.23 (Serif Italic Condensed) -U+0213 uni0213 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.14 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.23 (Serif Italic Condensed) -U+0214 uni0214 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.14 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.23 (Serif Italic Condensed) -U+0215 uni0215 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.14 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.23 (Serif Italic Condensed) -U+0216 uni0216 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.14 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.23 (Serif Italic Condensed) -U+0217 uni0217 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.14 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.23 (Serif Italic Condensed) -U+0218 Scommaaccent 1.5 -U+0219 scommaaccent 1.5 -U+021a uni021A 1.5 -U+021b uni021B 1.5 -U+021c uni021C 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.27 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Italic, Serif Italic Condensed) 2.28 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.31 (Serif Condensed Italic) -U+021d uni021D 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.27 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Italic, Serif Italic Condensed) 2.28 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.31 (Serif Condensed Italic) -U+021e uni021E 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.13 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.23 (Serif Italic Condensed) -U+021f uni021F 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.13 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.23 (Serif Italic Condensed) -U+0220 uni0220 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.16 (Serif, Serif Bold, Serif Bold Italic, Serif Italic) 2.17 (Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic) 2.18 (Sans Mono, Sans Mono Bold) 2.23 (Serif Italic Condensed) -U+0221 uni0221 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+0222 uni0222 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.32 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) -U+0223 uni0223 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.32 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) -U+0224 uni0224 2.3 -U+0225 uni0225 2.3 -U+0226 uni0226 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.14 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.23 (Serif Italic Condensed) -U+0227 uni0227 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.14 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.23 (Serif Italic Condensed) -U+0228 uni0228 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.14 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.23 (Serif Italic Condensed) -U+0229 uni0229 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.14 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.23 (Serif Italic Condensed) -U+022a uni022A 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.22 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.23 (Serif Italic Condensed) -U+022b uni022B 1.13 -U+022c uni022C 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.22 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.23 (Serif Italic Condensed) -U+022d uni022D 1.13 -U+022e uni022E 1.10 -U+022f uni022F 1.10 -U+0230 uni0230 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.5 (Sans ExtraLight) 2.22 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.23 (Serif Italic Condensed) -U+0231 uni0231 1.13 -U+0232 uni0232 1.5 -U+0233 uni0233 1.5 -U+0234 uni0234 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+0235 uni0235 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+0236 uni0236 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+0237 dotlessj 1.5 -U+0238 uni0238 2.2 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.3 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.10 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+0239 uni0239 2.2 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.3 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.10 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+023a uni023A 2.3 -U+023b uni023B 2.3 -U+023c uni023C 2.3 -U+023d uni023D 2.3 -U+023e uni023E 2.3 -U+023f uni023F 2.3 -U+0240 uni0240 2.3 -U+0241 uni0241 2.3 -U+0242 uni0242 2.10 (Sans, Sans Bold, Sans Bold Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Italic) 2.11 (Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic) 2.23 (Serif Italic Condensed) -U+0243 uni0243 2.9 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.32 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.33 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) -U+0244 uni0244 2.9 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.27 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.32 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) -U+0245 uni0245 2.9 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.10 (Sans ExtraLight, Serif, Serif Bold, Serif Bold Italic, Serif Italic) 2.11 (Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic) 2.13 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.23 (Serif Italic Condensed) -U+0246 uni0246 2.9 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.32 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) -U+0247 uni0247 2.9 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.32 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) -U+0248 uni0248 2.9 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.26 (Sans ExtraLight) 2.32 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) -U+0249 uni0249 2.9 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.26 (Sans ExtraLight) 2.32 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) -U+024a uni024A 2.10 (Sans, Sans Bold, Sans Bold Oblique, Sans Oblique) 2.11 (Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique) 2.32 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) -U+024b uni024B 2.10 (Sans, Sans Bold, Sans Bold Oblique, Sans Oblique) 2.11 (Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique) 2.26 (Sans ExtraLight) 2.32 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) -U+024c uni024C 2.9 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.26 (Sans ExtraLight) 2.27 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.32 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) -U+024d uni024D 2.9 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.26 (Sans ExtraLight) 2.27 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.32 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) -U+024e uni024E 2.10 (Sans, Sans Bold, Sans Bold Oblique, Sans Oblique) 2.11 (Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique) 2.32 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) -U+024f uni024F 2.10 (Sans, Sans Bold, Sans Bold Oblique, Sans Oblique) 2.11 (Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique) 2.32 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) -U+0250 uni0250 1.14 -U+0251 uni0251 1.14 -U+0252 uni0252 1.14 -U+0253 uni0253 1.14 -U+0254 uni0254 1.14 -U+0255 uni0255 1.14 -U+0256 uni0256 1.14 -U+0257 uni0257 1.14 -U+0258 uni0258 1.14 -U+0259 uni0259 1.14 -U+025a uni025A 1.14 -U+025b uni025B 1.14 -U+025c uni025C 1.14 -U+025d uni025D 1.14 -U+025e uni025E 1.14 -U+025f uni025F 1.14 -U+0260 uni0260 1.14 -U+0261 uni0261 1.14 -U+0262 uni0262 1.14 -U+0263 uni0263 1.14 -U+0264 uni0264 1.14 -U+0265 uni0265 1.14 -U+0266 uni0266 1.14 -U+0267 uni0267 1.14 -U+0268 uni0268 1.14 -U+0269 uni0269 1.14 -U+026a uni026A 1.14 -U+026b uni026B 1.14 -U+026c uni026C 1.14 -U+026d uni026D 1.14 -U+026e uni026E 1.14 -U+026f uni026F 1.14 -U+0270 uni0270 1.14 -U+0271 uni0271 1.14 -U+0272 uni0272 1.14 -U+0273 uni0273 1.14 -U+0274 uni0274 1.14 -U+0275 uni0275 1.14 -U+0276 uni0276 1.14 -U+0277 uni0277 1.14 -U+0278 uni0278 1.14 -U+0279 uni0279 1.14 -U+027a uni027A 1.14 -U+027b uni027B 1.14 -U+027c uni027C 1.14 -U+027d uni027D 1.14 -U+027e uni027E 1.14 -U+027f uni027F 1.14 -U+0280 uni0280 1.14 -U+0281 uni0281 1.14 -U+0282 uni0282 1.14 -U+0283 uni0283 1.14 -U+0284 uni0284 1.14 -U+0285 uni0285 1.14 -U+0286 uni0286 1.14 -U+0287 uni0287 1.14 -U+0288 uni0288 1.14 -U+0289 uni0289 1.14 -U+028a uni028A 1.14 -U+028b uni028B 1.14 -U+028c uni028C 1.14 -U+028d uni028D 1.14 -U+028e uni028E 1.14 -U+028f uni028F 1.14 -U+0290 uni0290 1.14 -U+0291 uni0291 1.14 -U+0292 uni0292 1.14 -U+0293 uni0293 1.14 -U+0294 uni0294 1.14 -U+0295 uni0295 1.14 -U+0296 uni0296 1.14 -U+0297 uni0297 1.14 -U+0298 uni0298 1.14 -U+0299 uni0299 1.14 -U+029a uni029A 1.14 -U+029b uni029B 1.14 -U+029c uni029C 1.14 -U+029d uni029D 1.14 -U+029e uni029E 1.14 -U+029f uni029F 1.14 -U+02a0 uni02A0 1.14 -U+02a1 uni02A1 1.14 -U+02a2 uni02A2 1.14 -U+02a3 uni02A3 1.14 -U+02a4 uni02A4 1.14 -U+02a5 uni02A5 1.14 -U+02a6 uni02A6 1.14 -U+02a7 uni02A7 1.14 -U+02a8 uni02A8 1.14 -U+02a9 uni02A9 1.14 -U+02aa uni02AA 1.14 -U+02ab uni02AB 1.14 -U+02ac uni02AC 1.14 -U+02ad uni02AD 1.14 -U+02ae uni02AE 1.14 -U+02af uni02AF 1.14 -U+02b0 uni02B0 1.14 -U+02b1 uni02B1 1.14 -U+02b2 uni02B2 1.14 -U+02b3 uni02B3 1.14 -U+02b4 uni02B4 1.14 -U+02b5 uni02B5 1.14 -U+02b6 uni02B6 1.14 -U+02b7 uni02B7 1.14 -U+02b8 uni02B8 1.14 -U+02b9 uni02B9 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.13 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+02ba uni02BA 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.34 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) -U+02bb uni02BB 1.5 -U+02bc uni02BC 1.12 -U+02bd uni02BD 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.7 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.13 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.23 (Serif Italic Condensed) -U+02be uni02BE 2.2 -U+02bf uni02BF 2.2 -U+02c0 uni02C0 1.14 -U+02c1 uni02C1 1.14 -U+02c2 uni02C2 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.34 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) -U+02c3 uni02C3 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.34 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) -U+02c4 uni02C4 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.34 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) -U+02c5 uni02C5 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.34 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) -U+02c6 circumflex original -U+02c7 caron original -U+02c8 uni02C8 2.0 -U+02c9 uni02C9 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) 2.7 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.13 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.23 (Serif Italic Condensed) -U+02ca uni02CA 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) 2.34 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) -U+02cb uni02CB 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) 2.34 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) -U+02cc uni02CC 2.0 -U+02cd uni02CD 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) 2.7 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.32 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) -U+02ce uni02CE 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) 2.34 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) -U+02cf uni02CF 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) 2.34 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) -U+02d0 uni02D0 1.14 -U+02d1 uni02D1 1.14 -U+02d2 uni02D2 2.0 -U+02d3 uni02D3 2.2 -U+02d4 uni02D4 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+02d5 uni02D5 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+02d6 uni02D6 2.0 -U+02d7 uni02D7 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.28 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.34 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) -U+02d8 breve original -U+02d9 dotaccent original -U+02da ring original -U+02db ogonek original -U+02dc tilde original -U+02dd hungarumlaut original -U+02de uni02DE 2.0 -U+02df uni02DF 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+02e0 uni02E0 1.14 -U+02e1 uni02E1 1.14 -U+02e2 uni02E2 1.14 -U+02e3 uni02E3 1.14 -U+02e4 uni02E4 1.14 -U+02e5 uni02E5 2.0 -U+02e6 uni02E6 2.0 -U+02e7 uni02E7 2.0 -U+02e8 uni02E8 2.0 -U+02e9 uni02E9 2.0 -U+02ec uni02EC 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.34 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) -U+02ed uni02ED 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+02ee uni02EE 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.7 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.28 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) -U+02ef uni02EF 2.34 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) -U+02f0 uni02F0 2.34 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) -U+02f3 uni02F3 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) 2.14 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.34 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) -U+02f7 uni02F7 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) 2.34 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) -U+0300 gravecomb 1.15 -U+0301 acutecomb 1.15 -U+0302 uni0302 1.15 -U+0303 tildecomb 1.15 -U+0304 uni0304 1.15 -U+0305 uni0305 2.0 -U+0306 uni0306 1.15 -U+0307 uni0307 1.15 -U+0308 uni0308 1.15 -U+0309 hookabovecomb 2.1 -U+030a uni030A 1.15 -U+030b uni030B 1.15 -U+030c uni030C 1.15 -U+030d uni030D 2.0 -U+030e uni030E 2.0 -U+030f uni030F 2.0 -U+0310 uni0310 2.0 -U+0311 uni0311 2.0 -U+0312 uni0312 1.11 -U+0313 uni0313 2.1 -U+0314 uni0314 2.1 -U+0315 uni0315 2.0 -U+0316 uni0316 2.0 -U+0317 uni0317 2.0 -U+0318 uni0318 2.0 -U+0319 uni0319 2.0 -U+031a uni031A 2.1 -U+031b uni031B 2.1 -U+031c uni031C 2.0 -U+031d uni031D 2.0 -U+031e uni031E 2.0 -U+031f uni031F 2.0 -U+0320 uni0320 2.0 -U+0321 uni0321 1.15 -U+0322 uni0322 1.15 -U+0323 dotbelowcomb 2.1 -U+0324 uni0324 2.0 -U+0325 uni0325 2.0 -U+0326 uni0326 1.5 -U+0327 uni0327 2.1 -U+0328 uni0328 2.1 -U+0329 uni0329 2.0 -U+032a uni032A 2.0 -U+032b uni032B 2.1 -U+032c uni032C 2.0 -U+032d uni032D 2.0 -U+032e uni032E 2.0 -U+032f uni032F 2.0 -U+0330 uni0330 2.0 -U+0331 uni0331 2.0 -U+0332 uni0332 2.0 -U+0333 uni0333 2.1 -U+0334 uni0334 2.3 -U+0335 uni0335 2.3 -U+0336 uni0336 2.3 -U+0337 uni0337 2.3 -U+0338 uni0338 2.3 -U+0339 uni0339 2.0 -U+033a uni033A 2.0 -U+033b uni033B 2.0 -U+033c uni033C 2.1 -U+033d uni033D 2.0 -U+033e uni033E 2.1 -U+033f uni033F 2.1 -U+0340 uni0340 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+0341 uni0341 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+0342 uni0342 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+0343 uni0343 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.13 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+0344 uni0344 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+0345 uni0345 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+0346 uni0346 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+0347 uni0347 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+0348 uni0348 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+0349 uni0349 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+034a uni034A 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+034b uni034B 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+034c uni034C 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+034d uni034D 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.36 (Math TeX Gyre Regular) -U+034e uni034E 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+034f uni034F 2.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+0351 uni0351 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+0352 uni0352 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique) 2.28 (Sans Condensed Oblique, Sans Oblique) -U+0353 uni0353 2.5 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) 2.28 (Sans Bold Oblique, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+0357 uni0357 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+0358 uni0358 2.3 -U+035a uni035A 2.28 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+035c uni035C 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) -U+035d uni035D 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) -U+035e uni035E 2.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+035f uni035F 2.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+0360 uni0360 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.34 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) -U+0361 uni0361 2.0 -U+0362 uni0362 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+0370 uni0370 2.26 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) 2.27 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) -U+0371 uni0371 2.26 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) 2.27 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) -U+0372 uni0372 2.27 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) 2.33 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) -U+0373 uni0373 2.27 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) 2.33 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) -U+0374 uni0374 1.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 1.15 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.2 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.4 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+0375 uni0375 1.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 1.15 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.2 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.4 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+0376 uni0376 2.27 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) 2.33 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.36 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) -U+0377 uni0377 2.27 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) 2.33 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.36 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) -U+037a uni037A 1.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 1.15 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.2 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.4 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+037b uni037B 2.9 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.10 (Sans ExtraLight) 2.27 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) 2.36 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) -U+037c uni037C 2.10 (Sans, Sans Bold, Sans Bold Oblique, Sans ExtraLight, Sans Oblique) 2.11 (Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique) 2.27 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) 2.36 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) -U+037d uni037D 2.10 (Sans, Sans Bold, Sans Bold Oblique, Sans ExtraLight, Sans Oblique) 2.11 (Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique) 2.27 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) 2.36 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) -U+037e uni037E 1.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.2 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.4 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+037f uni037F 2.36 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) -U+0384 tonos 1.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.2 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.4 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+0385 dieresistonos 1.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 1.15 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.2 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.4 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+0386 Alphatonos 1.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.2 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.4 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+0387 anoteleia 1.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.2 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.4 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+0388 Epsilontonos 1.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.2 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.4 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+0389 Etatonos 1.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.2 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.4 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+038a Iotatonos 1.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.2 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.4 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+038c Omicrontonos 1.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.2 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.4 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+038e Upsilontonos 1.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.2 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.4 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+038f Omegatonos 1.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.2 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.5 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+0390 iotadieresistonos 1.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 1.15 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.2 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.4 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+0391 Alpha 1.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.1 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.4 (Sans ExtraLight) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) -U+0392 Beta 1.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.1 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.4 (Sans ExtraLight) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) -U+0393 Gamma 1.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.1 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.4 (Sans ExtraLight) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) -U+0394 uni0394 1.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.1 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.4 (Sans ExtraLight) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) -U+0395 Epsilon 1.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.1 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.4 (Sans ExtraLight) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) -U+0396 Zeta 1.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.1 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.4 (Sans ExtraLight) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) -U+0397 Eta 1.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.1 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.4 (Sans ExtraLight) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) -U+0398 Theta 1.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.1 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.5 (Sans ExtraLight) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) -U+0399 Iota 1.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.1 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.4 (Sans ExtraLight) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) -U+039a Kappa 1.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.1 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.4 (Sans ExtraLight) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) -U+039b Lambda 1.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.1 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.4 (Sans ExtraLight) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) -U+039c Mu 1.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.1 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.4 (Sans ExtraLight) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) -U+039d Nu 1.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.1 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.4 (Sans ExtraLight) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) -U+039e Xi 1.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.1 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.4 (Sans ExtraLight) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) -U+039f Omicron 1.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.1 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.4 (Sans ExtraLight) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) -U+03a0 Pi 1.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.1 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.4 (Sans ExtraLight) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) -U+03a1 Rho 1.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.1 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.4 (Sans ExtraLight) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) -U+03a3 Sigma 1.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.1 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.4 (Sans ExtraLight) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) -U+03a4 Tau 1.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.1 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.4 (Sans ExtraLight) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) -U+03a5 Upsilon 1.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.1 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.4 (Sans ExtraLight) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) -U+03a6 Phi 1.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.1 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.5 (Sans ExtraLight) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) -U+03a7 Chi 1.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.1 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.4 (Sans ExtraLight) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) -U+03a8 Psi 1.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.1 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.5 (Sans ExtraLight) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) -U+03a9 Omega original -U+03aa Iotadieresis 1.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.1 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.4 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+03ab Upsilondieresis 1.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.1 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.4 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+03ac alphatonos 1.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 1.15 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.2 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.5 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+03ad epsilontonos 1.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 1.15 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.2 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.5 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+03ae etatonos 1.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 1.15 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.2 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.4 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+03af iotatonos 1.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 1.15 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.2 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.5 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+03b0 upsilondieresistonos 1.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 1.15 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.2 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.5 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+03b1 alpha 1.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 1.15 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.2 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.5 (Sans ExtraLight) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) -U+03b2 beta 1.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 1.15 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.2 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.5 (Sans ExtraLight) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) -U+03b3 gamma 1.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 1.15 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.2 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.5 (Sans ExtraLight) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) -U+03b4 delta 1.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 1.15 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.2 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.5 (Sans ExtraLight) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) -U+03b5 epsilon 1.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 1.15 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.2 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.4 (Sans ExtraLight) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) -U+03b6 zeta 1.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 1.15 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.2 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.5 (Sans ExtraLight) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) -U+03b7 eta 1.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 1.15 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.2 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.4 (Sans ExtraLight) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) -U+03b8 theta 1.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 1.15 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.2 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.5 (Sans ExtraLight) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) -U+03b9 iota 1.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 1.15 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.2 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.4 (Sans ExtraLight) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) -U+03ba kappa 1.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 1.15 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.2 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.4 (Sans ExtraLight) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) -U+03bb lambda 1.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 1.15 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.2 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.4 (Sans ExtraLight) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) -U+03bc uni03BC 1.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 1.15 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.2 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.4 (Sans ExtraLight) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) -U+03bd nu 1.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 1.15 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.2 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.5 (Sans ExtraLight) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) -U+03be xi 1.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 1.15 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.2 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.5 (Sans ExtraLight) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) -U+03bf omicron 1.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 1.15 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.2 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.4 (Sans ExtraLight) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) -U+03c0 pi original -U+03c1 rho 1.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 1.15 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.2 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.5 (Sans ExtraLight) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) -U+03c2 sigma1 1.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 1.15 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.2 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.5 (Sans ExtraLight) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) -U+03c3 sigma 1.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 1.15 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.2 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.5 (Sans ExtraLight) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) -U+03c4 tau 1.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 1.15 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.2 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.5 (Sans ExtraLight) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) -U+03c5 upsilon 1.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 1.15 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.2 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.5 (Sans ExtraLight) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) -U+03c6 phi 1.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 1.15 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.2 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.5 (Sans ExtraLight) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) -U+03c7 chi 1.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 1.15 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.2 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.5 (Sans ExtraLight) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) -U+03c8 psi 1.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 1.15 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.2 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.5 (Sans ExtraLight) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) -U+03c9 omega 1.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 1.15 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.2 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.5 (Sans ExtraLight) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) -U+03ca iotadieresis 1.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 1.15 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.2 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.4 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+03cb upsilondieresis 1.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 1.15 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.2 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.5 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+03cc omicrontonos 1.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 1.15 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.2 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.4 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+03cd upsilontonos 1.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 1.15 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.2 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.5 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+03ce omegatonos 1.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 1.15 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.2 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.5 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+03cf uni03CF 2.27 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) 2.33 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) -U+03d0 uni03D0 1.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.0 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.3 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.23 (Serif Italic Condensed) -U+03d1 theta1 1.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.0 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.3 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) -U+03d2 Upsilon1 1.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.0 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.3 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.23 (Serif Italic Condensed) -U+03d3 uni03D3 1.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.0 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.3 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.23 (Serif Italic Condensed) -U+03d4 uni03D4 1.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.0 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.3 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.23 (Serif Italic Condensed) -U+03d5 phi1 1.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.0 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.3 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.18 (Sans ExtraLight) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) -U+03d6 omega1 1.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.0 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.3 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.23 (Serif Italic Condensed) 2.26 (Sans ExtraLight) 2.36 (Math TeX Gyre Regular) -U+03d7 uni03D7 1.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.0 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.3 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.23 (Serif Italic Condensed) -U+03d8 uni03D8 1.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.0 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.3 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.23 (Serif Italic Condensed) 2.26 (Sans ExtraLight) -U+03d9 uni03D9 1.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.0 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.3 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.23 (Serif Italic Condensed) 2.26 (Sans ExtraLight) -U+03da uni03DA 1.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.0 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.3 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.23 (Serif Italic Condensed) -U+03db uni03DB 1.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.0 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.3 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.23 (Serif Italic Condensed) -U+03dc uni03DC 1.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.0 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.3 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.4 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+03dd uni03DD 1.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.0 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.3 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.23 (Serif Italic Condensed) -U+03de uni03DE 1.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.0 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.3 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.23 (Serif Italic Condensed) -U+03df uni03DF 1.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.0 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.3 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.23 (Serif Italic Condensed) -U+03e0 uni03E0 1.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.0 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.3 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.23 (Serif Italic Condensed) -U+03e1 uni03E1 1.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.0 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.3 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.23 (Serif Italic Condensed) -U+03e2 uni03E2 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+03e3 uni03E3 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+03e4 uni03E4 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+03e5 uni03E5 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+03e6 uni03E6 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+03e7 uni03E7 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+03e8 uni03E8 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+03e9 uni03E9 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+03ea uni03EA 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+03eb uni03EB 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+03ec uni03EC 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+03ed uni03ED 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+03ee uni03EE 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+03ef uni03EF 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+03f0 uni03F0 1.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.0 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.3 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) -U+03f1 uni03F1 1.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.0 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.3 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.23 (Serif Italic Condensed) 2.26 (Sans ExtraLight) 2.36 (Math TeX Gyre Regular) -U+03f2 uni03F2 1.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.0 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.3 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.4 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+03f3 uni03F3 1.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.0 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.3 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.4 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+03f4 uni03F4 1.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.0 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.3 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.4 (Sans ExtraLight) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) -U+03f5 uni03F5 1.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.0 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.3 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.4 (Sans ExtraLight) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) -U+03f6 uni03F6 1.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.0 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.3 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.4 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+03f7 uni03F7 1.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.0 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.3 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.4 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+03f8 uni03F8 1.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.0 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.3 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.4 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+03f9 uni03F9 1.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.0 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.3 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.4 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+03fa uni03FA 1.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.0 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.3 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.23 (Serif Italic Condensed) -U+03fb uni03FB 1.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.0 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.3 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.23 (Serif Italic Condensed) -U+03fc uni03FC 1.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.0 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.3 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.23 (Serif Italic Condensed) 2.26 (Sans ExtraLight) -U+03fd uni03FD 1.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.0 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.3 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.4 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+03fe uni03FE 1.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.0 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.3 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.4 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+03ff uni03FF 1.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.0 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.3 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.4 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+0400 uni0400 1.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Oblique) 1.5 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Serif, Serif Bold) 1.6 (Serif Bold Italic, Serif Italic) 1.7 (Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic) 2.4 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+0401 uni0401 1.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Oblique) 1.5 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Serif, Serif Bold) 1.6 (Serif Bold Italic, Serif Italic) 1.7 (Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic) 2.4 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+0402 uni0402 1.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Oblique) 1.5 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Serif, Serif Bold) 1.6 (Serif Bold Italic, Serif Italic) 1.7 (Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic) 2.5 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+0403 uni0403 1.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Oblique) 1.5 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Serif, Serif Bold) 1.6 (Serif Bold Italic, Serif Italic) 1.7 (Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic) 2.4 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+0404 uni0404 1.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Oblique) 1.5 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Serif, Serif Bold) 1.6 (Serif Bold Italic, Serif Italic) 1.7 (Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic) 2.4 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+0405 uni0405 1.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Oblique) 1.5 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Serif, Serif Bold) 1.6 (Serif Bold Italic, Serif Italic) 1.7 (Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic) 2.4 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+0406 uni0406 1.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Oblique) 1.5 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Serif, Serif Bold) 1.6 (Serif Bold Italic, Serif Italic) 1.7 (Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic) 2.4 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+0407 uni0407 1.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Oblique) 1.5 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Serif, Serif Bold) 1.6 (Serif Bold Italic, Serif Italic) 1.7 (Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic) 2.4 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+0408 uni0408 1.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Oblique) 1.5 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Serif, Serif Bold) 1.6 (Serif Bold Italic, Serif Italic) 1.7 (Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic) 2.4 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+0409 uni0409 1.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Oblique) 1.5 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Serif, Serif Bold) 1.6 (Serif Bold Italic, Serif Italic) 1.7 (Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic) 2.5 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+040a uni040A 1.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Oblique) 1.5 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Serif, Serif Bold) 1.6 (Serif Bold Italic, Serif Italic) 1.7 (Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic) 2.5 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+040b uni040B 1.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Oblique) 1.5 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Serif, Serif Bold) 1.6 (Serif Bold Italic, Serif Italic) 1.7 (Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic) 2.5 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+040c uni040C 1.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Oblique) 1.5 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Serif, Serif Bold) 1.6 (Serif Bold Italic, Serif Italic) 1.7 (Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic) 2.4 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+040d uni040D 1.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Oblique) 1.5 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Serif, Serif Bold) 1.6 (Serif Bold Italic, Serif Italic) 1.7 (Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic) 2.4 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+040e uni040E 1.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Oblique) 1.5 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Serif, Serif Bold) 1.6 (Serif Bold Italic, Serif Italic) 1.7 (Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic) 2.5 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+040f uni040F 1.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Oblique) 1.5 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Serif, Serif Bold) 1.6 (Serif Bold Italic, Serif Italic) 1.7 (Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic) 2.5 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+0410 uni0410 1.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Oblique) 1.5 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Serif, Serif Bold) 1.6 (Serif Bold Italic, Serif Italic) 1.7 (Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic) 2.4 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+0411 uni0411 1.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Oblique) 1.5 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Serif, Serif Bold) 1.6 (Serif Bold Italic, Serif Italic) 1.7 (Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic) 2.4 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+0412 uni0412 1.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Oblique) 1.5 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Serif, Serif Bold) 1.6 (Serif Bold Italic, Serif Italic) 1.7 (Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic) 2.4 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+0413 uni0413 1.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Oblique) 1.5 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Serif, Serif Bold) 1.6 (Serif Bold Italic, Serif Italic) 1.7 (Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic) 2.4 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+0414 uni0414 1.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Oblique) 1.5 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Serif, Serif Bold) 1.6 (Serif Bold Italic, Serif Italic) 1.7 (Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic) 2.5 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+0415 uni0415 1.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Oblique) 1.5 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Serif, Serif Bold) 1.6 (Serif Bold Italic, Serif Italic) 1.7 (Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic) 2.4 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+0416 uni0416 1.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Oblique) 1.5 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Serif, Serif Bold) 1.6 (Serif Bold Italic, Serif Italic) 1.7 (Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic) 2.4 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+0417 uni0417 1.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Oblique) 1.5 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Serif, Serif Bold) 1.6 (Serif Bold Italic, Serif Italic) 1.7 (Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic) 2.4 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+0418 uni0418 1.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Oblique) 1.5 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Serif, Serif Bold) 1.6 (Serif Bold Italic, Serif Italic) 1.7 (Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic) 2.4 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+0419 uni0419 1.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Oblique) 1.5 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Serif, Serif Bold) 1.6 (Serif Bold Italic, Serif Italic) 1.7 (Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic) 2.4 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+041a uni041A 1.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Oblique) 1.5 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Serif, Serif Bold) 1.6 (Serif Bold Italic, Serif Italic) 1.7 (Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic) 2.4 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+041b uni041B 1.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Oblique) 1.5 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Serif, Serif Bold) 1.6 (Serif Bold Italic, Serif Italic) 1.7 (Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic) 2.5 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+041c uni041C 1.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Oblique) 1.5 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Serif, Serif Bold) 1.6 (Serif Bold Italic, Serif Italic) 1.7 (Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic) 2.4 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+041d uni041D 1.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Oblique) 1.5 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Serif, Serif Bold) 1.6 (Serif Bold Italic, Serif Italic) 1.7 (Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic) 2.4 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+041e uni041E 1.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Oblique) 1.5 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Serif, Serif Bold) 1.6 (Serif Bold Italic, Serif Italic) 1.7 (Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic) 2.4 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+041f uni041F 1.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Oblique) 1.5 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Serif, Serif Bold) 1.6 (Serif Bold Italic, Serif Italic) 1.7 (Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic) 2.4 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+0420 uni0420 1.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Oblique) 1.5 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Serif, Serif Bold) 1.6 (Serif Bold Italic, Serif Italic) 1.7 (Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic) 2.4 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+0421 uni0421 1.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Oblique) 1.5 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Serif, Serif Bold) 1.6 (Serif Bold Italic, Serif Italic) 1.7 (Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic) 2.4 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+0422 uni0422 1.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Oblique) 1.5 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Serif, Serif Bold) 1.6 (Serif Bold Italic, Serif Italic) 1.7 (Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic) 2.4 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+0423 uni0423 1.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Oblique) 1.5 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Serif, Serif Bold) 1.6 (Serif Bold Italic, Serif Italic) 1.7 (Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic) 2.5 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+0424 uni0424 1.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Oblique) 1.5 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Serif, Serif Bold) 1.6 (Serif Bold Italic, Serif Italic) 1.7 (Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic) 2.5 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+0425 uni0425 1.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Oblique) 1.5 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Serif, Serif Bold) 1.6 (Serif Bold Italic, Serif Italic) 1.7 (Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic) 2.4 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+0426 uni0426 1.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Oblique) 1.5 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Serif, Serif Bold) 1.6 (Serif Bold Italic, Serif Italic) 1.7 (Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic) 2.5 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+0427 uni0427 1.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Oblique) 1.5 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Serif, Serif Bold) 1.6 (Serif Bold Italic, Serif Italic) 1.7 (Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic) 2.5 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+0428 uni0428 1.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Oblique) 1.5 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Serif, Serif Bold) 1.6 (Serif Bold Italic, Serif Italic) 1.7 (Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic) 2.5 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+0429 uni0429 1.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Oblique) 1.5 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Serif, Serif Bold) 1.6 (Serif Bold Italic, Serif Italic) 1.7 (Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic) 2.5 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+042a uni042A 1.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Oblique) 1.5 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Serif, Serif Bold) 1.6 (Serif Bold Italic, Serif Italic) 1.7 (Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic) 2.4 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+042b uni042B 1.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Oblique) 1.5 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Serif, Serif Bold) 1.6 (Serif Bold Italic, Serif Italic) 1.7 (Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic) 2.4 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+042c uni042C 1.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Oblique) 1.5 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Serif, Serif Bold) 1.6 (Serif Bold Italic, Serif Italic) 1.7 (Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic) 2.4 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+042d uni042D 1.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Oblique) 1.5 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Serif, Serif Bold) 1.6 (Serif Bold Italic, Serif Italic) 1.7 (Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic) 2.4 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+042e uni042E 1.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Oblique) 1.5 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Serif, Serif Bold) 1.6 (Serif Bold Italic, Serif Italic) 1.7 (Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic) 2.5 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+042f uni042F 1.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Oblique) 1.5 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Serif, Serif Bold) 1.6 (Serif Bold Italic, Serif Italic) 1.7 (Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic) 2.4 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+0430 uni0430 1.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Oblique) 1.5 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Serif, Serif Bold) 1.6 (Serif Bold Italic, Serif Italic) 1.7 (Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic) 2.4 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+0431 uni0431 1.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Oblique) 1.5 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Serif, Serif Bold) 1.6 (Serif Bold Italic, Serif Italic) 1.7 (Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic) 2.5 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+0432 uni0432 1.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Oblique) 1.5 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Serif, Serif Bold) 1.6 (Serif Bold Italic, Serif Italic) 1.7 (Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic) 2.4 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+0433 uni0433 1.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Oblique) 1.5 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Serif, Serif Bold) 1.6 (Serif Bold Italic, Serif Italic) 1.7 (Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic) 2.4 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+0434 uni0434 1.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Oblique) 1.5 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Serif, Serif Bold) 1.6 (Serif Bold Italic, Serif Italic) 1.7 (Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic) 2.5 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+0435 uni0435 1.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Oblique) 1.5 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Serif, Serif Bold) 1.6 (Serif Bold Italic, Serif Italic) 1.7 (Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic) 2.4 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+0436 uni0436 1.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Oblique) 1.5 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Serif, Serif Bold) 1.6 (Serif Bold Italic, Serif Italic) 1.7 (Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic) 2.4 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+0437 uni0437 1.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Oblique) 1.5 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Serif, Serif Bold) 1.6 (Serif Bold Italic, Serif Italic) 1.7 (Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic) 2.4 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+0438 uni0438 1.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Oblique) 1.5 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Serif, Serif Bold) 1.6 (Serif Bold Italic, Serif Italic) 1.7 (Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic) 2.4 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+0439 uni0439 1.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Oblique) 1.5 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Serif, Serif Bold) 1.6 (Serif Bold Italic, Serif Italic) 1.7 (Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic) 2.4 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+043a uni043A 1.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Oblique) 1.5 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Serif, Serif Bold) 1.6 (Serif Bold Italic, Serif Italic) 1.7 (Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic) 2.4 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+043b uni043B 1.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Oblique) 1.5 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Serif, Serif Bold) 1.6 (Serif Bold Italic, Serif Italic) 1.7 (Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic) 2.5 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+043c uni043C 1.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Oblique) 1.5 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Serif, Serif Bold) 1.6 (Serif Bold Italic, Serif Italic) 1.7 (Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic) 2.5 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+043d uni043D 1.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Oblique) 1.5 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Serif, Serif Bold) 1.6 (Serif Bold Italic, Serif Italic) 1.7 (Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic) 2.4 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+043e uni043E 1.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Oblique) 1.5 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Serif, Serif Bold) 1.6 (Serif Bold Italic, Serif Italic) 1.7 (Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic) 2.4 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+043f uni043F 1.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Oblique) 1.5 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Serif, Serif Bold) 1.6 (Serif Bold Italic, Serif Italic) 1.7 (Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic) 2.4 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+0440 uni0440 1.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Oblique) 1.5 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Serif, Serif Bold) 1.6 (Serif Bold Italic, Serif Italic) 1.7 (Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic) 2.4 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+0441 uni0441 1.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Oblique) 1.5 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Serif, Serif Bold) 1.6 (Serif Bold Italic, Serif Italic) 1.7 (Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic) 2.4 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+0442 uni0442 1.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Oblique) 1.5 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Serif, Serif Bold) 1.6 (Serif Bold Italic, Serif Italic) 1.7 (Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic) 2.4 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+0443 uni0443 1.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Oblique) 1.5 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Serif, Serif Bold) 1.6 (Serif Bold Italic, Serif Italic) 1.7 (Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic) 2.4 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+0444 uni0444 1.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Oblique) 1.5 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Serif, Serif Bold) 1.6 (Serif Bold Italic, Serif Italic) 1.7 (Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic) 2.5 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+0445 uni0445 1.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Oblique) 1.5 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Serif, Serif Bold) 1.6 (Serif Bold Italic, Serif Italic) 1.7 (Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic) 2.4 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+0446 uni0446 1.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Oblique) 1.5 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Serif, Serif Bold) 1.6 (Serif Bold Italic, Serif Italic) 1.7 (Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic) 2.5 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+0447 uni0447 1.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Oblique) 1.5 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Serif, Serif Bold) 1.6 (Serif Bold Italic, Serif Italic) 1.7 (Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic) 2.5 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+0448 uni0448 1.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Oblique) 1.5 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Serif, Serif Bold) 1.6 (Serif Bold Italic, Serif Italic) 1.7 (Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic) 2.5 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+0449 uni0449 1.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Oblique) 1.5 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Serif, Serif Bold) 1.6 (Serif Bold Italic, Serif Italic) 1.7 (Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic) 2.5 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+044a uni044A 1.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Oblique) 1.5 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Serif, Serif Bold) 1.6 (Serif Bold Italic, Serif Italic) 1.7 (Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic) 2.5 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+044b uni044B 1.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Oblique) 1.5 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Serif, Serif Bold) 1.6 (Serif Bold Italic, Serif Italic) 1.7 (Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic) 2.5 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+044c uni044C 1.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Oblique) 1.5 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Serif, Serif Bold) 1.6 (Serif Bold Italic, Serif Italic) 1.7 (Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic) 2.5 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+044d uni044D 1.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Oblique) 1.5 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Serif, Serif Bold) 1.6 (Serif Bold Italic, Serif Italic) 1.7 (Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic) 2.4 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+044e uni044E 1.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Oblique) 1.5 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Serif, Serif Bold) 1.6 (Serif Bold Italic, Serif Italic) 1.7 (Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic) 2.5 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+044f uni044F 1.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Oblique) 1.5 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Serif, Serif Bold) 1.6 (Serif Bold Italic, Serif Italic) 1.7 (Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic) 2.4 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+0450 uni0450 1.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Oblique) 1.5 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Serif, Serif Bold) 1.6 (Serif Bold Italic, Serif Italic) 1.7 (Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic) 2.4 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+0451 uni0451 1.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Oblique) 1.5 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Serif, Serif Bold) 1.6 (Serif Bold Italic, Serif Italic) 1.7 (Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic) 2.4 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+0452 uni0452 1.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Oblique) 1.5 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Serif, Serif Bold) 1.6 (Serif Bold Italic, Serif Italic) 1.7 (Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic) 2.5 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+0453 uni0453 1.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Oblique) 1.5 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Serif, Serif Bold) 1.6 (Serif Bold Italic, Serif Italic) 1.7 (Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic) 2.4 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+0454 uni0454 1.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Oblique) 1.5 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Serif, Serif Bold) 1.6 (Serif Bold Italic, Serif Italic) 1.7 (Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic) 2.4 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+0455 uni0455 1.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Oblique) 1.5 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Serif, Serif Bold) 1.6 (Serif Bold Italic, Serif Italic) 1.7 (Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic) 2.4 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+0456 uni0456 1.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Oblique) 1.5 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Serif, Serif Bold) 1.6 (Serif Bold Italic, Serif Italic) 1.7 (Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic) 2.4 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+0457 uni0457 1.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Oblique) 1.5 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Serif, Serif Bold) 1.6 (Serif Bold Italic, Serif Italic) 1.7 (Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic) 2.4 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+0458 uni0458 1.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Oblique) 1.5 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Serif, Serif Bold) 1.6 (Serif Bold Italic, Serif Italic) 1.7 (Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic) 2.4 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+0459 uni0459 1.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Oblique) 1.5 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Serif, Serif Bold) 1.6 (Serif Bold Italic, Serif Italic) 1.7 (Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic) 2.5 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+045a uni045A 1.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Oblique) 1.5 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Serif, Serif Bold) 1.6 (Serif Bold Italic, Serif Italic) 1.7 (Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic) 2.5 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+045b uni045B 1.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Oblique) 1.5 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Serif, Serif Bold) 1.6 (Serif Bold Italic, Serif Italic) 1.7 (Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic) 2.5 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+045c uni045C 1.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Oblique) 1.5 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Serif, Serif Bold) 1.6 (Serif Bold Italic, Serif Italic) 1.7 (Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic) 2.4 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+045d uni045D 1.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Oblique) 1.5 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Serif, Serif Bold) 1.6 (Serif Bold Italic, Serif Italic) 1.7 (Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic) 2.4 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+045e uni045E 1.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Oblique) 1.5 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Serif, Serif Bold) 1.6 (Serif Bold Italic, Serif Italic) 1.7 (Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic) 2.4 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+045f uni045F 1.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Oblique) 1.5 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Serif, Serif Bold) 1.6 (Serif Bold Italic, Serif Italic) 1.7 (Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic) 2.5 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+0460 uni0460 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+0461 uni0461 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.10 (Sans ExtraLight) -U+0462 uni0462 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.7 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.20 (Sans ExtraLight) 2.23 (Serif Italic Condensed) 2.30 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) -U+0463 uni0463 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.20 (Sans ExtraLight) 2.23 (Serif Italic Condensed) 2.30 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) -U+0464 uni0464 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.5 (Sans ExtraLight) 2.18 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+0465 uni0465 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.5 (Sans ExtraLight) 2.18 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+0466 uni0466 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+0467 uni0467 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+0468 uni0468 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+0469 uni0469 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+046a uni046A 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.21 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+046b uni046B 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.21 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+046c uni046C 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.34 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) -U+046d uni046D 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.34 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) -U+046e uni046E 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+046f uni046F 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+0470 uni0470 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.10 (Sans ExtraLight) 2.27 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) -U+0471 uni0471 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.10 (Sans ExtraLight) 2.27 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) -U+0472 uni0472 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.10 (Sans ExtraLight) 2.23 (Serif Italic Condensed) 2.26 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) -U+0473 uni0473 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.26 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) -U+0474 uni0474 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.12 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+0475 uni0475 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.12 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+0476 uni0476 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.34 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) -U+0477 uni0477 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.34 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) -U+0478 uni0478 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+0479 uni0479 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+047a uni047A 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+047b uni047B 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+047c uni047C 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+047d uni047D 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+047e uni047E 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+047f uni047F 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+0480 uni0480 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+0481 uni0481 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+0482 uni0482 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+0483 uni0483 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+0484 uni0484 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+0485 uni0485 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+0486 uni0486 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+0487 uni0487 2.9 (Sans, Sans Condensed) 2.27 (Sans Bold, Sans Bold Oblique, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+0488 uni0488 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+0489 uni0489 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+048a uni048A 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+048b uni048B 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+048c uni048C 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.4 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+048d uni048D 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.4 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+048e uni048E 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+048f uni048F 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+0490 uni0490 1.15 -U+0491 uni0491 1.15 -U+0492 uni0492 1.14 -U+0493 uni0493 1.14 -U+0494 uni0494 2.2 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.4 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.5 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.23 (Serif Italic Condensed) -U+0495 uni0495 2.2 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.4 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.5 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.23 (Serif Italic Condensed) -U+0496 uni0496 2.2 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.15 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.26 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) -U+0497 uni0497 2.2 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.15 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.26 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) -U+0498 uni0498 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.4 (Sans ExtraLight) 2.5 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+0499 uni0499 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.4 (Sans ExtraLight) 2.5 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+049a uni049A 1.14 -U+049b uni049B 1.14 -U+049c uni049C 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+049d uni049D 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+049e uni049E 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+049f uni049F 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+04a0 uni04A0 2.2 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.4 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.26 (Sans ExtraLight) -U+04a1 uni04A1 2.2 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.4 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.26 (Sans ExtraLight) -U+04a2 uni04A2 2.2 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.4 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+04a3 uni04A3 2.2 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.4 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+04a4 uni04A4 2.2 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.4 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.10 (Sans ExtraLight) 2.23 (Serif Italic Condensed) 2.31 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) -U+04a5 uni04A5 2.2 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.4 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.10 (Sans ExtraLight) 2.23 (Serif Italic Condensed) 2.31 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) -U+04a6 uni04A6 2.2 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.4 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+04a7 uni04A7 2.2 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.4 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+04a8 uni04A8 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+04a9 uni04A9 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+04aa uni04AA 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.4 (Sans ExtraLight) 2.5 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+04ab uni04AB 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.4 (Sans ExtraLight) 2.5 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+04ac uni04AC 2.2 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.4 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+04ad uni04AD 2.2 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.4 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+04ae uni04AE 2.2 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.4 (Sans ExtraLight, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+04af uni04AF 2.2 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.4 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.5 (Sans ExtraLight, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+04b0 uni04B0 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.26 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) -U+04b1 uni04B1 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.26 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) -U+04b2 uni04B2 1.14 -U+04b3 uni04B3 1.14 -U+04b4 uni04B4 2.2 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.4 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.10 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+04b5 uni04B5 2.2 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.4 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.10 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+04b6 uni04B6 2.2 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.4 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+04b7 uni04B7 2.2 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.4 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+04b8 uni04B8 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+04b9 uni04B9 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+04ba uni04BA 2.2 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.4 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.5 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+04bb uni04BB 2.2 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.4 (Sans ExtraLight, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+04bc uni04BC 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+04bd uni04BD 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+04be uni04BE 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+04bf uni04BF 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+04c0 uni04C0 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.4 (Sans ExtraLight, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+04c1 uni04C1 2.2 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.4 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.5 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+04c2 uni04C2 2.2 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.4 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.5 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+04c3 uni04C3 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.5 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.23 (Serif Italic Condensed) -U+04c4 uni04C4 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.5 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.23 (Serif Italic Condensed) -U+04c5 uni04C5 2.2 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+04c6 uni04C6 2.2 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+04c7 uni04C7 2.2 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.4 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.5 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.23 (Serif Italic Condensed) 2.26 (Sans ExtraLight) -U+04c8 uni04C8 2.2 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.4 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.5 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.23 (Serif Italic Condensed) 2.26 (Sans ExtraLight) -U+04c9 uni04C9 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+04ca uni04CA 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+04cb uni04CB 2.2 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.4 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+04cc uni04CC 2.2 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.4 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+04cd uni04CD 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+04ce uni04CE 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+04cf uni04CF 2.9 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+04d0 uni04D0 2.2 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.3 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.4 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+04d1 uni04D1 2.2 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.3 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.4 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+04d2 uni04D2 2.2 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.3 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.4 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+04d3 uni04D3 2.2 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.3 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.4 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+04d4 uni04D4 2.2 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.3 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.4 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+04d5 uni04D5 2.2 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.3 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.4 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+04d6 uni04D6 2.2 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.3 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.4 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+04d7 uni04D7 2.2 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.3 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.4 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+04d8 uni04D8 2.2 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.4 (Sans ExtraLight, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+04d9 uni04D9 2.2 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.4 (Sans ExtraLight, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+04da uni04DA 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.4 (Sans ExtraLight, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+04db uni04DB 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.4 (Sans ExtraLight, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+04dc uni04DC 2.2 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.4 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.5 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+04dd uni04DD 2.2 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.4 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.5 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+04de uni04DE 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.4 (Sans ExtraLight, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+04df uni04DF 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.4 (Sans ExtraLight, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+04e0 uni04E0 2.3 -U+04e1 uni04E1 2.3 -U+04e2 uni04E2 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.4 (Sans ExtraLight, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+04e3 uni04E3 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.4 (Sans ExtraLight, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+04e4 uni04E4 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.4 (Sans ExtraLight, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+04e5 uni04E5 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.4 (Sans ExtraLight, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+04e6 uni04E6 2.2 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.3 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.4 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+04e7 uni04E7 2.2 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.3 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.4 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+04e8 uni04E8 2.2 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.4 (Sans ExtraLight, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.23 (Serif Italic Condensed) -U+04e9 uni04E9 2.2 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.4 (Sans ExtraLight, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.23 (Serif Italic Condensed) -U+04ea uni04EA 2.2 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.4 (Sans ExtraLight, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.23 (Serif Italic Condensed) -U+04eb uni04EB 2.2 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.4 (Sans ExtraLight, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.23 (Serif Italic Condensed) -U+04ec uni04EC 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.4 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.5 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+04ed uni04ED 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.4 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.5 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+04ee uni04EE 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.4 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.5 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+04ef uni04EF 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.4 (Sans ExtraLight, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+04f0 uni04F0 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.4 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.5 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+04f1 uni04F1 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.4 (Sans ExtraLight, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+04f2 uni04F2 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.4 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.5 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+04f3 uni04F3 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.4 (Sans ExtraLight, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+04f4 uni04F4 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.4 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.5 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+04f5 uni04F5 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.4 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.5 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+04f6 uni04F6 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.4 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+04f7 uni04F7 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.4 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+04f8 uni04F8 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.4 (Sans ExtraLight, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+04f9 uni04F9 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.4 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.5 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+04fa uni04FA 2.13 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+04fb uni04FB 2.13 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+04fc uni04FC 2.13 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+04fd uni04FD 2.13 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+04fe uni04FE 2.12 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.26 (Sans ExtraLight) -U+04ff uni04FF 2.12 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.26 (Sans ExtraLight) -U+0500 uni0500 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.26 (Sans ExtraLight) -U+0501 uni0501 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.26 (Sans ExtraLight) -U+0502 uni0502 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+0503 uni0503 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+0504 uni0504 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+0505 uni0505 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+0506 uni0506 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+0507 uni0507 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+0508 uni0508 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+0509 uni0509 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+050a uni050A 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+050b uni050B 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+050c uni050C 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+050d uni050D 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+050e uni050E 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+050f uni050F 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+0510 uni0510 2.9 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.26 (Sans ExtraLight, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.27 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) -U+0511 uni0511 2.9 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.26 (Sans ExtraLight, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.27 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) -U+0512 uni0512 2.12 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.26 (Sans ExtraLight) 2.27 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) -U+0513 uni0513 2.12 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.26 (Sans ExtraLight) 2.27 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) -U+0514 uni0514 2.27 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) -U+0515 uni0515 2.27 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) -U+0516 uni0516 2.27 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.35 (Sans ExtraLight) -U+0517 uni0517 2.27 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.35 (Sans ExtraLight) -U+0518 uni0518 2.27 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.35 (Sans ExtraLight) -U+0519 uni0519 2.27 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.35 (Sans ExtraLight) -U+051a uni051A 2.26 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique) 2.27 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) -U+051b uni051B 2.26 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique) 2.27 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) -U+051c uni051C 2.26 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique) 2.27 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) -U+051d uni051D 2.26 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique) 2.27 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) -U+051e uni051E 2.33 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+051f uni051F 2.33 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+0520 uni0520 2.26 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+0521 uni0521 2.26 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+0522 uni0522 2.26 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+0523 uni0523 2.26 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+0524 uni0524 2.29 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+0525 uni0525 2.29 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+0531 uni0531 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.33 (Sans ExtraLight, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) -U+0532 uni0532 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.33 (Sans ExtraLight, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) -U+0533 uni0533 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.33 (Sans ExtraLight, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) -U+0534 uni0534 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.33 (Sans ExtraLight, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) -U+0535 uni0535 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.33 (Sans ExtraLight, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) -U+0536 uni0536 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.33 (Sans ExtraLight, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) -U+0537 uni0537 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.33 (Sans ExtraLight, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) -U+0538 uni0538 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.33 (Sans ExtraLight, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) -U+0539 uni0539 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.33 (Sans ExtraLight, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) -U+053a uni053A 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.33 (Sans ExtraLight, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) -U+053b uni053B 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.33 (Sans ExtraLight, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) -U+053c uni053C 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.33 (Sans ExtraLight, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) -U+053d uni053D 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.33 (Sans ExtraLight, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) -U+053e uni053E 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.33 (Sans ExtraLight, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) -U+053f uni053F 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.33 (Sans ExtraLight, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) -U+0540 uni0540 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.33 (Sans ExtraLight, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) -U+0541 uni0541 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.33 (Sans ExtraLight, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) -U+0542 uni0542 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.33 (Sans ExtraLight, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) -U+0543 uni0543 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.33 (Sans ExtraLight, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) -U+0544 uni0544 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.33 (Sans ExtraLight, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) -U+0545 uni0545 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.33 (Sans ExtraLight, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) -U+0546 uni0546 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.33 (Sans ExtraLight, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) -U+0547 uni0547 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.33 (Sans ExtraLight, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) -U+0548 uni0548 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.5 (Sans ExtraLight) 2.33 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) -U+0549 uni0549 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.33 (Sans ExtraLight, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) -U+054a uni054A 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.33 (Sans ExtraLight, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) -U+054b uni054B 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.33 (Sans ExtraLight, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) -U+054c uni054C 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.33 (Sans ExtraLight, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) -U+054d uni054D 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.4 (Sans ExtraLight) 2.33 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) -U+054e uni054E 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.33 (Sans ExtraLight, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) -U+054f uni054F 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.4 (Sans ExtraLight) 2.33 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) -U+0550 uni0550 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.26 (Sans ExtraLight) 2.33 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) -U+0551 uni0551 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.33 (Sans ExtraLight, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) -U+0552 uni0552 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.33 (Sans ExtraLight, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) -U+0553 uni0553 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.5 (Sans ExtraLight) 2.33 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) -U+0554 uni0554 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.33 (Sans ExtraLight, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) -U+0555 uni0555 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.4 (Sans ExtraLight) 2.33 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) -U+0556 uni0556 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.33 (Sans ExtraLight, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) -U+0559 uni0559 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.33 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) -U+055a uni055A 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.4 (Sans ExtraLight) 2.33 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) -U+055b uni055B 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.33 (Sans ExtraLight, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) -U+055c uni055C 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.33 (Sans ExtraLight, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) -U+055d uni055D 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.4 (Sans ExtraLight) 2.33 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) -U+055e uni055E 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.33 (Sans ExtraLight, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) -U+055f uni055F 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.33 (Sans ExtraLight, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) -U+0561 uni0561 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.5 (Sans ExtraLight) 2.33 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) -U+0562 uni0562 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.26 (Sans ExtraLight) 2.33 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) -U+0563 uni0563 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.26 (Sans ExtraLight) 2.33 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) -U+0564 uni0564 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.26 (Sans ExtraLight) 2.33 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) -U+0565 uni0565 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.26 (Sans ExtraLight) 2.33 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) -U+0566 uni0566 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.26 (Sans ExtraLight) 2.33 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) -U+0567 uni0567 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.33 (Sans ExtraLight, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) -U+0568 uni0568 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.26 (Sans ExtraLight) 2.33 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) -U+0569 uni0569 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.33 (Sans ExtraLight, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) -U+056a uni056A 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.33 (Sans ExtraLight, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) -U+056b uni056B 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.5 (Sans ExtraLight) 2.33 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) -U+056c uni056C 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.26 (Sans ExtraLight) 2.33 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) -U+056d uni056D 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.10 (Sans ExtraLight) 2.33 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) -U+056e uni056E 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.33 (Sans ExtraLight, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) -U+056f uni056F 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.10 (Sans ExtraLight) 2.33 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) -U+0570 uni0570 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.4 (Sans ExtraLight) 2.33 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) -U+0571 uni0571 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.33 (Sans ExtraLight, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) -U+0572 uni0572 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.26 (Sans ExtraLight) 2.33 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) -U+0573 uni0573 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.33 (Sans ExtraLight, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) -U+0574 uni0574 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.33 (Sans ExtraLight, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) -U+0575 uni0575 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.4 (Sans ExtraLight) 2.33 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) -U+0576 uni0576 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.33 (Sans ExtraLight, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) -U+0577 uni0577 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.33 (Sans ExtraLight, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) -U+0578 uni0578 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.4 (Sans ExtraLight) 2.33 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) -U+0579 uni0579 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.33 (Sans ExtraLight, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) -U+057a uni057A 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.5 (Sans ExtraLight) 2.33 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) -U+057b uni057B 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.33 (Sans ExtraLight, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) -U+057c uni057C 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.26 (Sans ExtraLight) 2.33 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) -U+057d uni057D 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.4 (Sans ExtraLight) 2.33 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) -U+057e uni057E 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.26 (Sans ExtraLight) 2.33 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) -U+057f uni057F 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.10 (Sans ExtraLight) 2.33 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) -U+0580 uni0580 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.4 (Sans ExtraLight) 2.33 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) -U+0581 uni0581 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.4 (Sans ExtraLight) 2.33 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) -U+0582 uni0582 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.26 (Sans ExtraLight) 2.33 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) -U+0583 uni0583 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.10 (Sans ExtraLight) 2.33 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) -U+0584 uni0584 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.33 (Sans ExtraLight, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) -U+0585 uni0585 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.4 (Sans ExtraLight) 2.33 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) -U+0586 uni0586 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.33 (Sans ExtraLight, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) -U+0587 uni0587 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.26 (Sans ExtraLight) 2.33 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) -U+0589 uni0589 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.4 (Sans ExtraLight) 2.33 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) -U+058a uni058A 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.33 (Sans ExtraLight, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) -U+05b0 uni05B0 2.9 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+05b1 uni05B1 2.9 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+05b2 uni05B2 2.9 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+05b3 uni05B3 2.9 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+05b4 uni05B4 2.9 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+05b5 uni05B5 2.9 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+05b6 uni05B6 2.9 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+05b7 uni05B7 2.9 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+05b8 uni05B8 2.9 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+05b9 uni05B9 2.9 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+05ba uni05BA 2.16 (Sans, Sans Bold, Sans Bold Oblique, Sans Oblique) 2.17 (Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique) -U+05bb uni05BB 2.9 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+05bc uni05BC 2.9 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+05bd uni05BD 2.9 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+05be uni05BE 2.9 (Sans Condensed Oblique, Sans Oblique) 2.16 (Sans, Sans Bold, Sans Bold Oblique) 2.17 (Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique) -U+05bf uni05BF 2.9 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+05c0 uni05C0 2.9 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+05c1 uni05C1 2.9 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+05c2 uni05C2 2.9 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+05c3 uni05C3 2.9 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+05c6 uni05C6 2.9 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+05c7 uni05C7 2.9 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+05d0 uni05D0 2.9 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+05d1 uni05D1 2.9 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+05d2 uni05D2 2.9 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+05d3 uni05D3 2.9 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+05d4 uni05D4 2.9 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+05d5 uni05D5 2.9 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+05d6 uni05D6 2.9 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+05d7 uni05D7 2.9 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+05d8 uni05D8 2.9 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+05d9 uni05D9 2.9 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+05da uni05DA 2.9 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+05db uni05DB 2.9 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+05dc uni05DC 2.9 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+05dd uni05DD 2.9 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+05de uni05DE 2.9 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+05df uni05DF 2.9 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+05e0 uni05E0 2.9 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+05e1 uni05E1 2.9 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+05e2 uni05E2 2.9 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+05e3 uni05E3 2.9 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+05e4 uni05E4 2.9 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+05e5 uni05E5 2.9 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+05e6 uni05E6 2.9 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+05e7 uni05E7 2.9 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+05e8 uni05E8 2.9 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+05e9 uni05E9 2.9 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+05ea uni05EA 2.9 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+05f0 uni05F0 2.9 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+05f1 uni05F1 2.9 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+05f2 uni05F2 2.9 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+05f3 uni05F3 2.16 (Sans, Sans Bold, Sans Bold Oblique, Sans Oblique) 2.17 (Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique) -U+05f4 uni05F4 2.16 (Sans, Sans Bold, Sans Bold Oblique, Sans Oblique) 2.17 (Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique) -U+0606 uni0606 2.26 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold, Sans Mono, Sans Mono Bold) -U+0607 uni0607 2.26 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold, Sans Mono, Sans Mono Bold) -U+0609 uni0609 2.26 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold, Sans Mono, Sans Mono Bold) -U+060a uni060A 2.26 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold, Sans Mono, Sans Mono Bold) -U+060c uni060C 2.4 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) 2.16 (Sans Mono, Sans Mono Bold) -U+0615 uni0615 2.4 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) 2.16 (Sans Mono, Sans Mono Bold) -U+061b uni061B 2.4 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) 2.16 (Sans Mono, Sans Mono Bold) -U+061f uni061F 2.4 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) 2.16 (Sans Mono, Sans Mono Bold) -U+0621 uni0621 2.4 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) 2.16 (Sans Mono, Sans Mono Bold) -U+0622 uni0622 2.4 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) 2.16 (Sans Mono, Sans Mono Bold) -U+0623 uni0623 2.4 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) 2.16 (Sans Mono, Sans Mono Bold) -U+0624 uni0624 2.4 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) 2.16 (Sans Mono, Sans Mono Bold) -U+0625 uni0625 2.4 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) 2.16 (Sans Mono, Sans Mono Bold) -U+0626 uni0626 2.4 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) 2.16 (Sans Mono, Sans Mono Bold) -U+0627 uni0627 2.4 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) 2.16 (Sans Mono, Sans Mono Bold) -U+0628 uni0628 2.4 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) 2.16 (Sans Mono, Sans Mono Bold) -U+0629 uni0629 2.4 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) 2.16 (Sans Mono, Sans Mono Bold) -U+062a uni062A 2.4 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) 2.16 (Sans Mono, Sans Mono Bold) -U+062b uni062B 2.4 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) 2.16 (Sans Mono, Sans Mono Bold) -U+062c uni062C 2.4 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) 2.16 (Sans Mono, Sans Mono Bold) -U+062d uni062D 2.4 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) 2.16 (Sans Mono, Sans Mono Bold) -U+062e uni062E 2.4 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) 2.16 (Sans Mono, Sans Mono Bold) -U+062f uni062F 2.4 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) 2.16 (Sans Mono, Sans Mono Bold) -U+0630 uni0630 2.4 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) 2.16 (Sans Mono, Sans Mono Bold) -U+0631 uni0631 2.4 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) 2.16 (Sans Mono, Sans Mono Bold) -U+0632 uni0632 2.4 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) 2.16 (Sans Mono, Sans Mono Bold) -U+0633 uni0633 2.4 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) 2.16 (Sans Mono, Sans Mono Bold) -U+0634 uni0634 2.4 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) 2.16 (Sans Mono, Sans Mono Bold) -U+0635 uni0635 2.4 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) 2.16 (Sans Mono, Sans Mono Bold) -U+0636 uni0636 2.4 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) 2.16 (Sans Mono, Sans Mono Bold) -U+0637 uni0637 2.4 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) 2.16 (Sans Mono, Sans Mono Bold) -U+0638 uni0638 2.4 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) 2.16 (Sans Mono, Sans Mono Bold) -U+0639 uni0639 2.4 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) 2.16 (Sans Mono, Sans Mono Bold) -U+063a uni063A 2.4 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) 2.16 (Sans Mono, Sans Mono Bold) -U+0640 uni0640 2.4 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) 2.16 (Sans Mono, Sans Mono Bold) -U+0641 uni0641 2.4 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) 2.16 (Sans Mono, Sans Mono Bold) -U+0642 uni0642 2.4 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) 2.16 (Sans Mono, Sans Mono Bold) -U+0643 uni0643 2.4 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) 2.16 (Sans Mono, Sans Mono Bold) -U+0644 uni0644 2.4 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) 2.16 (Sans Mono, Sans Mono Bold) -U+0645 uni0645 2.4 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) 2.16 (Sans Mono, Sans Mono Bold) -U+0646 uni0646 2.4 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) 2.16 (Sans Mono, Sans Mono Bold) -U+0647 uni0647 2.4 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) 2.16 (Sans Mono, Sans Mono Bold) -U+0648 uni0648 2.4 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) 2.16 (Sans Mono, Sans Mono Bold) -U+0649 uni0649 2.4 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) 2.16 (Sans Mono, Sans Mono Bold) -U+064a uni064A 2.4 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) 2.16 (Sans Mono, Sans Mono Bold) -U+064b uni064B 2.4 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) 2.16 (Sans Mono, Sans Mono Bold) -U+064c uni064C 2.4 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) 2.16 (Sans Mono, Sans Mono Bold) -U+064d uni064D 2.4 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) 2.16 (Sans Mono, Sans Mono Bold) -U+064e uni064E 2.4 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) 2.16 (Sans Mono, Sans Mono Bold) -U+064f uni064F 2.4 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) 2.16 (Sans Mono, Sans Mono Bold) -U+0650 uni0650 2.4 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) 2.16 (Sans Mono, Sans Mono Bold) -U+0651 uni0651 2.4 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) 2.16 (Sans Mono, Sans Mono Bold) -U+0652 uni0652 2.4 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) 2.16 (Sans Mono, Sans Mono Bold) -U+0653 uni0653 2.4 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) 2.16 (Sans Mono, Sans Mono Bold) -U+0654 uni0654 2.4 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) 2.16 (Sans Mono, Sans Mono Bold) -U+0655 uni0655 2.4 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) 2.16 (Sans Mono, Sans Mono Bold) -U+0657 uni0657 2.31 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) -U+065a uni065A 2.7 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) 2.16 (Sans Mono, Sans Mono Bold) -U+0660 uni0660 2.4 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) 2.16 (Sans Mono, Sans Mono Bold) -U+0661 uni0661 2.4 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) 2.16 (Sans Mono, Sans Mono Bold) -U+0662 uni0662 2.4 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) 2.16 (Sans Mono, Sans Mono Bold) -U+0663 uni0663 2.4 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) 2.16 (Sans Mono, Sans Mono Bold) -U+0664 uni0664 2.4 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) 2.16 (Sans Mono, Sans Mono Bold) -U+0665 uni0665 2.4 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) 2.16 (Sans Mono, Sans Mono Bold) -U+0666 uni0666 2.4 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) 2.16 (Sans Mono, Sans Mono Bold) -U+0667 uni0667 2.4 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) 2.16 (Sans Mono, Sans Mono Bold) -U+0668 uni0668 2.4 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) 2.16 (Sans Mono, Sans Mono Bold) -U+0669 uni0669 2.4 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) 2.16 (Sans Mono, Sans Mono Bold) -U+066a uni066A 2.4 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) 2.16 (Sans Mono, Sans Mono Bold) -U+066b uni066B 2.4 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) 2.16 (Sans Mono, Sans Mono Bold) -U+066c uni066C 2.4 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) 2.16 (Sans Mono, Sans Mono Bold) -U+066d uni066D 2.4 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) 2.16 (Sans Mono, Sans Mono Bold) -U+066e uni066E 2.4 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) 2.16 (Sans Mono, Sans Mono Bold) -U+066f uni066F 2.4 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) 2.16 (Sans Mono, Sans Mono Bold) -U+0670 uni0670 2.31 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) -U+0674 uni0674 2.4 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold, Sans ExtraLight) 2.16 (Sans Mono, Sans Mono Bold) -U+0679 uni0679 2.4 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) 2.16 (Sans Mono, Sans Mono Bold) -U+067a uni067A 2.4 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) 2.16 (Sans Mono, Sans Mono Bold) -U+067b uni067B 2.4 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) 2.16 (Sans Mono, Sans Mono Bold) -U+067c uni067C 2.4 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) 2.16 (Sans Mono, Sans Mono Bold) -U+067d uni067D 2.4 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) 2.16 (Sans Mono, Sans Mono Bold) -U+067e uni067E 2.4 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) 2.16 (Sans Mono, Sans Mono Bold) -U+067f uni067F 2.4 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) 2.16 (Sans Mono, Sans Mono Bold) -U+0680 uni0680 2.4 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) 2.16 (Sans Mono, Sans Mono Bold) -U+0681 uni0681 2.4 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) 2.16 (Sans Mono, Sans Mono Bold) -U+0682 uni0682 2.4 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) 2.16 (Sans Mono, Sans Mono Bold) -U+0683 uni0683 2.4 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) 2.16 (Sans Mono, Sans Mono Bold) -U+0684 uni0684 2.4 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) 2.16 (Sans Mono, Sans Mono Bold) -U+0685 uni0685 2.4 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) 2.16 (Sans Mono, Sans Mono Bold) -U+0686 uni0686 2.4 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) 2.16 (Sans Mono, Sans Mono Bold) -U+0687 uni0687 2.4 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) 2.16 (Sans Mono, Sans Mono Bold) -U+0688 uni0688 2.31 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) -U+0689 uni0689 2.31 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) -U+068a uni068A 2.31 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) -U+068b uni068B 2.31 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) -U+068c uni068C 2.31 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) -U+068d uni068D 2.31 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) -U+068e uni068E 2.31 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) -U+068f uni068F 2.31 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) -U+0690 uni0690 2.31 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) -U+0691 uni0691 2.4 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) 2.16 (Sans Mono, Sans Mono Bold) -U+0692 uni0692 2.7 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) 2.16 (Sans Mono, Sans Mono Bold) -U+0693 uni0693 2.31 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) -U+0694 uni0694 2.31 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) -U+0695 uni0695 2.7 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) -U+0696 uni0696 2.31 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) -U+0697 uni0697 2.31 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) -U+0698 uni0698 2.4 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) 2.16 (Sans Mono, Sans Mono Bold) -U+0699 uni0699 2.31 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) -U+069a uni069A 2.31 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) -U+069b uni069B 2.31 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) -U+069c uni069C 2.31 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) -U+069d uni069D 2.31 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) -U+069e uni069E 2.31 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) -U+069f uni069F 2.31 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) -U+06a0 uni06A0 2.31 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) -U+06a1 uni06A1 2.4 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) 2.16 (Sans Mono, Sans Mono Bold) -U+06a2 uni06A2 2.31 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) -U+06a3 uni06A3 2.31 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) -U+06a4 uni06A4 2.4 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) 2.16 (Sans Mono, Sans Mono Bold) -U+06a5 uni06A5 2.31 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) -U+06a6 uni06A6 2.4 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) -U+06a7 uni06A7 2.31 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) -U+06a8 uni06A8 2.31 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) -U+06a9 uni06A9 2.4 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) 2.16 (Sans Mono, Sans Mono Bold) -U+06aa uni06AA 2.31 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) -U+06ab uni06AB 2.31 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) -U+06ac uni06AC 2.31 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) -U+06ad uni06AD 2.31 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) -U+06ae uni06AE 2.31 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) -U+06af uni06AF 2.4 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) 2.16 (Sans Mono, Sans Mono Bold) -U+06b0 uni06B0 2.31 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) -U+06b1 uni06B1 2.31 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) -U+06b2 uni06B2 2.31 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) -U+06b3 uni06B3 2.31 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) -U+06b4 uni06B4 2.31 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) -U+06b5 uni06B5 2.7 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) 2.16 (Sans Mono, Sans Mono Bold) -U+06b6 uni06B6 2.31 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) -U+06b7 uni06B7 2.31 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) -U+06b8 uni06B8 2.31 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) -U+06b9 uni06B9 2.31 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) -U+06ba uni06BA 2.4 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) 2.16 (Sans Mono, Sans Mono Bold) -U+06bb uni06BB 2.31 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) -U+06bc uni06BC 2.31 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) -U+06bd uni06BD 2.31 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) -U+06be uni06BE 2.16 (Sans Mono, Sans Mono Bold) 2.31 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) -U+06bf uni06BF 2.4 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) -U+06c6 uni06C6 2.7 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) 2.16 (Sans Mono, Sans Mono Bold) -U+06c7 uni06C7 2.35 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) -U+06c8 uni06C8 2.35 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) -U+06cb uni06CB 2.35 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) -U+06cc uni06CC 2.4 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) 2.16 (Sans Mono, Sans Mono Bold) -U+06ce uni06CE 2.7 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) 2.16 (Sans Mono, Sans Mono Bold) -U+06d0 uni06D0 2.35 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) -U+06d5 uni06D5 2.10 (Sans, Sans Bold) 2.11 (Sans Condensed, Sans Condensed Bold) 2.16 (Sans Mono, Sans Mono Bold) -U+06f0 uni06F0 2.4 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) 2.16 (Sans Mono, Sans Mono Bold) -U+06f1 uni06F1 2.4 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) 2.16 (Sans Mono, Sans Mono Bold) -U+06f2 uni06F2 2.4 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) 2.16 (Sans Mono, Sans Mono Bold) -U+06f3 uni06F3 2.4 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) 2.16 (Sans Mono, Sans Mono Bold) -U+06f4 uni06F4 2.4 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) 2.16 (Sans Mono, Sans Mono Bold) -U+06f5 uni06F5 2.4 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) 2.16 (Sans Mono, Sans Mono Bold) -U+06f6 uni06F6 2.4 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) 2.16 (Sans Mono, Sans Mono Bold) -U+06f7 uni06F7 2.4 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) 2.16 (Sans Mono, Sans Mono Bold) -U+06f8 uni06F8 2.4 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) 2.16 (Sans Mono, Sans Mono Bold) -U+06f9 uni06F9 2.4 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) 2.16 (Sans Mono, Sans Mono Bold) -U+07c0 uni07C0 2.18 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) -U+07c1 uni07C1 2.18 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) -U+07c2 uni07C2 2.18 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) -U+07c3 uni07C3 2.18 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) -U+07c4 uni07C4 2.18 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) -U+07c5 uni07C5 2.18 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) -U+07c6 uni07C6 2.18 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) -U+07c7 uni07C7 2.18 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) -U+07c8 uni07C8 2.18 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) -U+07c9 uni07C9 2.18 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) -U+07ca uni07CA 2.18 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) -U+07cb uni07CB 2.18 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) -U+07cc uni07CC 2.18 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) -U+07cd uni07CD 2.18 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) -U+07ce uni07CE 2.18 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) -U+07cf uni07CF 2.18 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) -U+07d0 uni07D0 2.18 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) -U+07d1 uni07D1 2.18 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) -U+07d2 uni07D2 2.18 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) -U+07d3 uni07D3 2.18 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) -U+07d4 uni07D4 2.18 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) -U+07d5 uni07D5 2.18 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) -U+07d6 uni07D6 2.18 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) -U+07d7 uni07D7 2.18 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) -U+07d8 uni07D8 2.18 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) -U+07d9 uni07D9 2.18 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) -U+07da uni07DA 2.18 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) -U+07db uni07DB 2.18 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) -U+07dc uni07DC 2.18 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) -U+07dd uni07DD 2.18 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) -U+07de uni07DE 2.18 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) -U+07df uni07DF 2.18 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) -U+07e0 uni07E0 2.18 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) -U+07e1 uni07E1 2.18 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) -U+07e2 uni07E2 2.18 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) -U+07e3 uni07E3 2.18 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) -U+07e4 uni07E4 2.18 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) -U+07e5 uni07E5 2.18 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) -U+07e6 uni07E6 2.18 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) -U+07e7 uni07E7 2.18 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) -U+07eb uni07EB 2.18 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) -U+07ec uni07EC 2.18 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) -U+07ed uni07ED 2.18 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) -U+07ee uni07EE 2.18 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) -U+07ef uni07EF 2.18 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) -U+07f0 uni07F0 2.18 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) -U+07f1 uni07F1 2.18 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) -U+07f2 uni07F2 2.18 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) -U+07f3 uni07F3 2.18 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) -U+07f4 uni07F4 2.18 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) -U+07f5 uni07F5 2.18 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) -U+07f8 uni07F8 2.18 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) -U+07f9 uni07F9 2.18 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) -U+07fa uni07FA 2.18 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) -U+0e3f uni0E3F 2.10 (Sans, Sans Bold, Sans Bold Oblique, Sans Oblique) 2.11 (Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique) 2.35 (Sans ExtraLight, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.36 (Math TeX Gyre Regular) -U+0e81 uni0E81 2.10 (Sans, Sans Bold, Sans Bold Oblique, Sans Oblique) 2.11 (Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique) 2.14 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) -U+0e82 uni0E82 2.10 (Sans, Sans Bold, Sans Bold Oblique, Sans Oblique) 2.11 (Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique) 2.14 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) -U+0e84 uni0E84 2.10 (Sans, Sans Bold, Sans Bold Oblique, Sans Oblique) 2.11 (Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique) 2.14 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) -U+0e87 uni0E87 2.10 (Sans, Sans Bold, Sans Bold Oblique, Sans Oblique) 2.11 (Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique) 2.14 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) -U+0e88 uni0E88 2.10 (Sans, Sans Bold, Sans Bold Oblique, Sans Oblique) 2.11 (Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique) 2.14 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) -U+0e8a uni0E8A 2.10 (Sans, Sans Bold, Sans Bold Oblique, Sans Oblique) 2.11 (Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique) 2.14 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) -U+0e8d uni0E8D 2.10 (Sans, Sans Bold, Sans Bold Oblique, Sans Oblique) 2.11 (Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique) 2.14 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) -U+0e94 uni0E94 2.10 (Sans, Sans Bold, Sans Bold Oblique, Sans Oblique) 2.11 (Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique) 2.14 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) -U+0e95 uni0E95 2.10 (Sans, Sans Bold, Sans Bold Oblique, Sans Oblique) 2.11 (Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique) 2.14 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) -U+0e96 uni0E96 2.10 (Sans, Sans Bold, Sans Bold Oblique, Sans Oblique) 2.11 (Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique) 2.14 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) -U+0e97 uni0E97 2.10 (Sans, Sans Bold, Sans Bold Oblique, Sans Oblique) 2.11 (Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique) 2.14 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) -U+0e99 uni0E99 2.10 (Sans, Sans Bold, Sans Bold Oblique, Sans Oblique) 2.11 (Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique) 2.14 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) -U+0e9a uni0E9A 2.10 (Sans, Sans Bold, Sans Bold Oblique, Sans Oblique) 2.11 (Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique) 2.14 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) -U+0e9b uni0E9B 2.10 (Sans, Sans Bold, Sans Bold Oblique, Sans Oblique) 2.11 (Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique) 2.14 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) -U+0e9c uni0E9C 2.10 (Sans, Sans Bold, Sans Bold Oblique, Sans Oblique) 2.11 (Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique) 2.14 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) -U+0e9d uni0E9D 2.10 (Sans, Sans Bold, Sans Bold Oblique, Sans Oblique) 2.11 (Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique) 2.14 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) -U+0e9e uni0E9E 2.10 (Sans, Sans Bold, Sans Bold Oblique, Sans Oblique) 2.11 (Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique) 2.14 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) -U+0e9f uni0E9F 2.10 (Sans, Sans Bold, Sans Bold Oblique, Sans Oblique) 2.11 (Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique) 2.14 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) -U+0ea1 uni0EA1 2.10 (Sans, Sans Bold, Sans Bold Oblique, Sans Oblique) 2.11 (Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique) 2.14 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) -U+0ea2 uni0EA2 2.10 (Sans, Sans Bold, Sans Bold Oblique, Sans Oblique) 2.11 (Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique) 2.14 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) -U+0ea3 uni0EA3 2.10 (Sans, Sans Bold, Sans Bold Oblique, Sans Oblique) 2.11 (Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique) 2.14 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) -U+0ea5 uni0EA5 2.10 (Sans, Sans Bold, Sans Bold Oblique, Sans Oblique) 2.11 (Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique) 2.14 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) -U+0ea7 uni0EA7 2.10 (Sans, Sans Bold, Sans Bold Oblique, Sans Oblique) 2.11 (Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique) 2.14 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) -U+0eaa uni0EAA 2.10 (Sans, Sans Bold, Sans Bold Oblique, Sans Oblique) 2.11 (Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique) 2.14 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) -U+0eab uni0EAB 2.10 (Sans, Sans Bold, Sans Bold Oblique, Sans Oblique) 2.11 (Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique) 2.14 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) -U+0ead uni0EAD 2.10 (Sans, Sans Bold, Sans Bold Oblique, Sans Oblique) 2.11 (Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique) 2.14 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) -U+0eae uni0EAE 2.10 (Sans, Sans Bold, Sans Bold Oblique, Sans Oblique) 2.11 (Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique) 2.14 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) -U+0eaf uni0EAF 2.10 (Sans, Sans Bold, Sans Bold Oblique, Sans Oblique) 2.11 (Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique) 2.14 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) -U+0eb0 uni0EB0 2.10 (Sans, Sans Bold, Sans Bold Oblique, Sans Oblique) 2.11 (Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique) 2.18 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) -U+0eb1 uni0EB1 2.10 (Sans, Sans Bold, Sans Bold Oblique, Sans Oblique) 2.11 (Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique) 2.18 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) -U+0eb2 uni0EB2 2.10 (Sans, Sans Bold, Sans Bold Oblique, Sans Oblique) 2.11 (Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique) 2.18 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) -U+0eb3 uni0EB3 2.10 (Sans, Sans Bold, Sans Bold Oblique, Sans Oblique) 2.11 (Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique) 2.18 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) -U+0eb4 uni0EB4 2.10 (Sans, Sans Bold, Sans Bold Oblique, Sans Oblique) 2.11 (Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique) 2.18 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) -U+0eb5 uni0EB5 2.10 (Sans, Sans Bold, Sans Bold Oblique, Sans Oblique) 2.11 (Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique) 2.18 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) -U+0eb6 uni0EB6 2.10 (Sans, Sans Bold, Sans Bold Oblique, Sans Oblique) 2.11 (Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique) 2.18 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) -U+0eb7 uni0EB7 2.10 (Sans, Sans Bold, Sans Bold Oblique, Sans Oblique) 2.11 (Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique) 2.18 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) -U+0eb8 uni0EB8 2.10 (Sans, Sans Bold, Sans Bold Oblique, Sans Oblique) 2.11 (Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique) 2.18 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) -U+0eb9 uni0EB9 2.10 (Sans, Sans Bold, Sans Bold Oblique, Sans Oblique) 2.11 (Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique) 2.18 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) -U+0ebb uni0EBB 2.10 (Sans, Sans Bold, Sans Bold Oblique, Sans Oblique) 2.11 (Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique) 2.18 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) -U+0ebc uni0EBC 2.10 (Sans, Sans Bold, Sans Bold Oblique, Sans Oblique) 2.11 (Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique) 2.18 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) -U+0ebd uni0EBD 2.10 (Sans, Sans Bold, Sans Bold Oblique, Sans Oblique) 2.11 (Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique) -U+0ec0 uni0EC0 2.10 (Sans, Sans Bold, Sans Bold Oblique, Sans Oblique) 2.11 (Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique) -U+0ec1 uni0EC1 2.10 (Sans, Sans Bold, Sans Bold Oblique, Sans Oblique) 2.11 (Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique) -U+0ec2 uni0EC2 2.10 (Sans, Sans Bold, Sans Bold Oblique, Sans Oblique) 2.11 (Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique) -U+0ec3 uni0EC3 2.10 (Sans, Sans Bold, Sans Bold Oblique, Sans Oblique) 2.11 (Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique) -U+0ec4 uni0EC4 2.10 (Sans, Sans Bold, Sans Bold Oblique, Sans Oblique) 2.11 (Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique) -U+0ec6 uni0EC6 2.10 (Sans, Sans Bold, Sans Bold Oblique, Sans Oblique) 2.11 (Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique) -U+0ec8 uni0EC8 2.10 (Sans, Sans Bold, Sans Bold Oblique, Sans Oblique) 2.11 (Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique) 2.18 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) -U+0ec9 uni0EC9 2.10 (Sans, Sans Bold, Sans Bold Oblique, Sans Oblique) 2.11 (Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique) 2.18 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) -U+0eca uni0ECA 2.10 (Sans, Sans Bold, Sans Bold Oblique, Sans Oblique) 2.11 (Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique) 2.18 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) -U+0ecb uni0ECB 2.10 (Sans, Sans Bold, Sans Bold Oblique, Sans Oblique) 2.11 (Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique) 2.18 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) -U+0ecc uni0ECC 2.10 (Sans, Sans Bold, Sans Bold Oblique, Sans Oblique) 2.11 (Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique) 2.18 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) -U+0ecd uni0ECD 2.10 (Sans, Sans Bold, Sans Bold Oblique, Sans Oblique) 2.11 (Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique) 2.18 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) -U+0ed0 uni0ED0 2.16 (Sans, Sans Bold, Sans Bold Oblique, Sans Oblique) 2.17 (Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique) -U+0ed1 uni0ED1 2.16 (Sans, Sans Bold, Sans Bold Oblique, Sans Oblique) 2.17 (Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique) -U+0ed2 uni0ED2 2.16 (Sans, Sans Bold, Sans Bold Oblique, Sans Oblique) 2.17 (Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique) -U+0ed3 uni0ED3 2.16 (Sans, Sans Bold, Sans Bold Oblique, Sans Oblique) 2.17 (Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique) -U+0ed4 uni0ED4 2.16 (Sans, Sans Bold, Sans Bold Oblique, Sans Oblique) 2.17 (Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique) -U+0ed5 uni0ED5 2.16 (Sans, Sans Bold, Sans Bold Oblique, Sans Oblique) 2.17 (Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique) -U+0ed6 uni0ED6 2.16 (Sans, Sans Bold, Sans Bold Oblique, Sans Oblique) 2.17 (Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique) -U+0ed7 uni0ED7 2.16 (Sans, Sans Bold, Sans Bold Oblique, Sans Oblique) 2.17 (Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique) -U+0ed8 uni0ED8 2.18 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+0ed9 uni0ED9 2.16 (Sans, Sans Bold, Sans Bold Oblique, Sans Oblique) 2.17 (Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique) -U+0edc uni0EDC 2.10 (Sans, Sans Bold, Sans Bold Oblique, Sans Oblique) 2.11 (Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique) -U+0edd uni0EDD 2.10 (Sans, Sans Bold, Sans Bold Oblique, Sans Oblique) 2.11 (Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique) -U+10a0 uni10A0 2.18 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold, Serif, Serif Bold, Serif Condensed, Serif Condensed Bold) 2.20 (Sans Bold Oblique, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif Bold Italic, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+10a1 uni10A1 2.18 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold, Serif, Serif Bold, Serif Condensed, Serif Condensed Bold) 2.20 (Sans Bold Oblique, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif Bold Italic, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+10a2 uni10A2 2.18 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold, Serif, Serif Bold, Serif Condensed, Serif Condensed Bold) 2.20 (Sans Bold Oblique, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif Bold Italic, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+10a3 uni10A3 2.18 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold, Serif, Serif Bold, Serif Condensed, Serif Condensed Bold) 2.20 (Sans Bold Oblique, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif Bold Italic, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+10a4 uni10A4 2.18 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold, Serif, Serif Bold, Serif Condensed, Serif Condensed Bold) 2.20 (Sans Bold Oblique, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif Bold Italic, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+10a5 uni10A5 2.18 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold, Serif, Serif Bold, Serif Condensed, Serif Condensed Bold) 2.20 (Sans Bold Oblique, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif Bold Italic, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+10a6 uni10A6 2.18 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold, Serif, Serif Bold, Serif Condensed, Serif Condensed Bold) 2.20 (Sans Bold Oblique, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif Bold Italic, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+10a7 uni10A7 2.18 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold, Serif, Serif Bold, Serif Condensed, Serif Condensed Bold) 2.20 (Sans Bold Oblique, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif Bold Italic, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+10a8 uni10A8 2.18 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold, Serif, Serif Bold, Serif Condensed, Serif Condensed Bold) 2.20 (Sans Bold Oblique, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif Bold Italic, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+10a9 uni10A9 2.18 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold, Serif, Serif Bold, Serif Condensed, Serif Condensed Bold) 2.20 (Sans Bold Oblique, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif Bold Italic, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+10aa uni10AA 2.18 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold, Serif, Serif Bold, Serif Condensed, Serif Condensed Bold) 2.20 (Sans Bold Oblique, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif Bold Italic, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+10ab uni10AB 2.18 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold, Serif, Serif Bold, Serif Condensed, Serif Condensed Bold) 2.20 (Sans Bold Oblique, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif Bold Italic, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+10ac uni10AC 2.18 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold, Serif, Serif Bold, Serif Condensed, Serif Condensed Bold) 2.20 (Sans Bold Oblique, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif Bold Italic, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+10ad uni10AD 2.18 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold, Serif, Serif Bold, Serif Condensed, Serif Condensed Bold) 2.20 (Sans Bold Oblique, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif Bold Italic, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+10ae uni10AE 2.18 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold, Serif, Serif Bold, Serif Condensed, Serif Condensed Bold) 2.20 (Sans Bold Oblique, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif Bold Italic, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+10af uni10AF 2.18 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold, Serif, Serif Bold, Serif Condensed, Serif Condensed Bold) 2.20 (Sans Bold Oblique, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif Bold Italic, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+10b0 uni10B0 2.18 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold, Serif, Serif Bold, Serif Condensed, Serif Condensed Bold) 2.20 (Sans Bold Oblique, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif Bold Italic, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+10b1 uni10B1 2.18 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold, Serif, Serif Bold, Serif Condensed, Serif Condensed Bold) 2.20 (Sans Bold Oblique, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif Bold Italic, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+10b2 uni10B2 2.18 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold, Serif, Serif Bold, Serif Condensed, Serif Condensed Bold) 2.20 (Sans Bold Oblique, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif Bold Italic, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+10b3 uni10B3 2.18 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold, Serif, Serif Bold, Serif Condensed, Serif Condensed Bold) 2.20 (Sans Bold Oblique, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif Bold Italic, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+10b4 uni10B4 2.18 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold, Serif, Serif Bold, Serif Condensed, Serif Condensed Bold) 2.20 (Sans Bold Oblique, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif Bold Italic, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+10b5 uni10B5 2.18 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold, Serif, Serif Bold, Serif Condensed, Serif Condensed Bold) 2.20 (Sans Bold Oblique, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif Bold Italic, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+10b6 uni10B6 2.18 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold, Serif, Serif Bold, Serif Condensed, Serif Condensed Bold) 2.20 (Sans Bold Oblique, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif Bold Italic, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+10b7 uni10B7 2.18 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold, Serif, Serif Bold, Serif Condensed, Serif Condensed Bold) 2.20 (Sans Bold Oblique, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif Bold Italic, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+10b8 uni10B8 2.18 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold, Serif, Serif Bold, Serif Condensed, Serif Condensed Bold) 2.20 (Sans Bold Oblique, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif Bold Italic, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+10b9 uni10B9 2.18 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold, Serif, Serif Bold, Serif Condensed, Serif Condensed Bold) 2.20 (Sans Bold Oblique, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif Bold Italic, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+10ba uni10BA 2.18 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold, Serif, Serif Bold, Serif Condensed, Serif Condensed Bold) 2.20 (Sans Bold Oblique, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif Bold Italic, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+10bb uni10BB 2.18 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold, Serif, Serif Bold, Serif Condensed, Serif Condensed Bold) 2.20 (Sans Bold Oblique, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif Bold Italic, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+10bc uni10BC 2.18 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold, Serif, Serif Bold, Serif Condensed, Serif Condensed Bold) 2.20 (Sans Bold Oblique, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif Bold Italic, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+10bd uni10BD 2.18 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold, Serif, Serif Bold, Serif Condensed, Serif Condensed Bold) 2.20 (Sans Bold Oblique, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif Bold Italic, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+10be uni10BE 2.18 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold, Serif, Serif Bold, Serif Condensed, Serif Condensed Bold) 2.20 (Sans Bold Oblique, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif Bold Italic, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+10bf uni10BF 2.18 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold, Serif, Serif Bold, Serif Condensed, Serif Condensed Bold) 2.20 (Sans Bold Oblique, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif Bold Italic, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+10c0 uni10C0 2.18 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold, Serif, Serif Bold, Serif Condensed, Serif Condensed Bold) 2.20 (Sans Bold Oblique, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif Bold Italic, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+10c1 uni10C1 2.18 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold, Serif, Serif Bold, Serif Condensed, Serif Condensed Bold) 2.20 (Sans Bold Oblique, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif Bold Italic, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+10c2 uni10C2 2.18 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold, Serif, Serif Bold, Serif Condensed, Serif Condensed Bold) 2.20 (Sans Bold Oblique, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif Bold Italic, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+10c3 uni10C3 2.18 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold, Serif, Serif Bold, Serif Condensed, Serif Condensed Bold) 2.20 (Sans Bold Oblique, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif Bold Italic, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+10c4 uni10C4 2.18 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold, Serif, Serif Bold, Serif Condensed, Serif Condensed Bold) 2.20 (Sans Bold Oblique, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif Bold Italic, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+10c5 uni10C5 2.18 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold, Serif, Serif Bold, Serif Condensed, Serif Condensed Bold) 2.20 (Sans Bold Oblique, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif Bold Italic, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+10d0 uni10D0 2.18 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold, Sans Mono, Sans Mono Bold, Serif, Serif Bold, Serif Condensed, Serif Condensed Bold) 2.20 (Sans Bold Oblique, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique, Serif Bold Italic, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.32 (Sans ExtraLight) -U+10d1 uni10D1 2.18 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold, Sans Mono, Sans Mono Bold, Serif, Serif Bold, Serif Condensed, Serif Condensed Bold) 2.20 (Sans Bold Oblique, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique, Serif Bold Italic, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.32 (Sans ExtraLight) -U+10d2 uni10D2 2.18 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold, Sans Mono, Sans Mono Bold, Serif, Serif Bold, Serif Condensed, Serif Condensed Bold) 2.20 (Sans Bold Oblique, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique, Serif Bold Italic, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.32 (Sans ExtraLight) -U+10d3 uni10D3 2.18 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold, Sans Mono, Sans Mono Bold, Serif, Serif Bold, Serif Condensed, Serif Condensed Bold) 2.20 (Sans Bold Oblique, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique, Serif Bold Italic, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.32 (Sans ExtraLight) -U+10d4 uni10D4 2.18 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold, Sans Mono, Sans Mono Bold, Serif, Serif Bold, Serif Condensed, Serif Condensed Bold) 2.20 (Sans Bold Oblique, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique, Serif Bold Italic, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.32 (Sans ExtraLight) -U+10d5 uni10D5 2.18 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold, Sans Mono, Sans Mono Bold, Serif, Serif Bold, Serif Condensed, Serif Condensed Bold) 2.20 (Sans Bold Oblique, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique, Serif Bold Italic, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.32 (Sans ExtraLight) -U+10d6 uni10D6 2.18 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold, Sans Mono, Sans Mono Bold, Serif, Serif Bold, Serif Condensed, Serif Condensed Bold) 2.20 (Sans Bold Oblique, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique, Serif Bold Italic, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.32 (Sans ExtraLight) -U+10d7 uni10D7 2.18 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold, Sans Mono, Sans Mono Bold, Serif, Serif Bold, Serif Condensed, Serif Condensed Bold) 2.20 (Sans Bold Oblique, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique, Serif Bold Italic, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.32 (Sans ExtraLight) -U+10d8 uni10D8 2.18 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold, Sans Mono, Sans Mono Bold, Serif, Serif Bold, Serif Condensed, Serif Condensed Bold) 2.20 (Sans Bold Oblique, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique, Serif Bold Italic, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.32 (Sans ExtraLight) -U+10d9 uni10D9 2.18 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold, Sans Mono, Sans Mono Bold, Serif, Serif Bold, Serif Condensed, Serif Condensed Bold) 2.20 (Sans Bold Oblique, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique, Serif Bold Italic, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.32 (Sans ExtraLight) -U+10da uni10DA 2.18 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold, Sans Mono, Sans Mono Bold, Serif, Serif Bold, Serif Condensed, Serif Condensed Bold) 2.20 (Sans Bold Oblique, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique, Serif Bold Italic, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.32 (Sans ExtraLight) -U+10db uni10DB 2.18 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold, Sans Mono, Sans Mono Bold, Serif, Serif Bold, Serif Condensed, Serif Condensed Bold) 2.20 (Sans Bold Oblique, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique, Serif Bold Italic, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.32 (Sans ExtraLight) -U+10dc uni10DC 2.18 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold, Sans Mono, Sans Mono Bold, Serif, Serif Bold, Serif Condensed, Serif Condensed Bold) 2.20 (Sans Bold Oblique, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique, Serif Bold Italic, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.32 (Sans ExtraLight) -U+10dd uni10DD 2.18 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold, Sans Mono, Sans Mono Bold, Serif, Serif Bold, Serif Condensed, Serif Condensed Bold) 2.20 (Sans Bold Oblique, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique, Serif Bold Italic, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.32 (Sans ExtraLight) -U+10de uni10DE 2.18 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold, Sans Mono, Sans Mono Bold, Serif, Serif Bold, Serif Condensed, Serif Condensed Bold) 2.20 (Sans Bold Oblique, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique, Serif Bold Italic, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.32 (Sans ExtraLight) -U+10df uni10DF 2.18 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold, Sans Mono, Sans Mono Bold, Serif, Serif Bold, Serif Condensed, Serif Condensed Bold) 2.20 (Sans Bold Oblique, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique, Serif Bold Italic, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.32 (Sans ExtraLight) -U+10e0 uni10E0 2.18 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold, Sans Mono, Sans Mono Bold, Serif, Serif Bold, Serif Condensed, Serif Condensed Bold) 2.20 (Sans Bold Oblique, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique, Serif Bold Italic, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.32 (Sans ExtraLight) -U+10e1 uni10E1 2.18 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold, Sans Mono, Sans Mono Bold, Serif, Serif Bold, Serif Condensed, Serif Condensed Bold) 2.20 (Sans Bold Oblique, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique, Serif Bold Italic, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.32 (Sans ExtraLight) -U+10e2 uni10E2 2.18 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold, Sans Mono, Sans Mono Bold, Serif, Serif Bold, Serif Condensed, Serif Condensed Bold) 2.20 (Sans Bold Oblique, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique, Serif Bold Italic, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.32 (Sans ExtraLight) -U+10e3 uni10E3 2.18 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold, Sans Mono, Sans Mono Bold, Serif, Serif Bold, Serif Condensed, Serif Condensed Bold) 2.20 (Sans Bold Oblique, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique, Serif Bold Italic, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.32 (Sans ExtraLight) -U+10e4 uni10E4 2.18 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold, Sans Mono, Sans Mono Bold, Serif, Serif Bold, Serif Condensed, Serif Condensed Bold) 2.20 (Sans Bold Oblique, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique, Serif Bold Italic, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.32 (Sans ExtraLight) -U+10e5 uni10E5 2.18 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold, Sans Mono, Sans Mono Bold, Serif, Serif Bold, Serif Condensed, Serif Condensed Bold) 2.20 (Sans Bold Oblique, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique, Serif Bold Italic, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.32 (Sans ExtraLight) -U+10e6 uni10E6 2.18 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold, Sans Mono, Sans Mono Bold, Serif, Serif Bold, Serif Condensed, Serif Condensed Bold) 2.20 (Sans Bold Oblique, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique, Serif Bold Italic, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.32 (Sans ExtraLight) -U+10e7 uni10E7 2.18 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold, Sans Mono, Sans Mono Bold, Serif, Serif Bold, Serif Condensed, Serif Condensed Bold) 2.20 (Sans Bold Oblique, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique, Serif Bold Italic, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.32 (Sans ExtraLight) -U+10e8 uni10E8 2.18 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold, Sans Mono, Sans Mono Bold, Serif, Serif Bold, Serif Condensed, Serif Condensed Bold) 2.20 (Sans Bold Oblique, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique, Serif Bold Italic, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.32 (Sans ExtraLight) -U+10e9 uni10E9 2.18 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold, Sans Mono, Sans Mono Bold, Serif, Serif Bold, Serif Condensed, Serif Condensed Bold) 2.20 (Sans Bold Oblique, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique, Serif Bold Italic, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.32 (Sans ExtraLight) -U+10ea uni10EA 2.18 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold, Sans Mono, Sans Mono Bold, Serif, Serif Bold, Serif Condensed, Serif Condensed Bold) 2.20 (Sans Bold Oblique, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique, Serif Bold Italic, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.32 (Sans ExtraLight) -U+10eb uni10EB 2.18 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold, Sans Mono, Sans Mono Bold, Serif, Serif Bold, Serif Condensed, Serif Condensed Bold) 2.20 (Sans Bold Oblique, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique, Serif Bold Italic, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.32 (Sans ExtraLight) -U+10ec uni10EC 2.18 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold, Sans Mono, Sans Mono Bold, Serif, Serif Bold, Serif Condensed, Serif Condensed Bold) 2.20 (Sans Bold Oblique, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique, Serif Bold Italic, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.32 (Sans ExtraLight) -U+10ed uni10ED 2.18 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold, Sans Mono, Sans Mono Bold, Serif, Serif Bold, Serif Condensed, Serif Condensed Bold) 2.20 (Sans Bold Oblique, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique, Serif Bold Italic, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.32 (Sans ExtraLight) -U+10ee uni10EE 2.18 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold, Sans Mono, Sans Mono Bold, Serif, Serif Bold, Serif Condensed, Serif Condensed Bold) 2.20 (Sans Bold Oblique, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique, Serif Bold Italic, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.32 (Sans ExtraLight) -U+10ef uni10EF 2.18 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold, Sans Mono, Sans Mono Bold, Serif, Serif Bold, Serif Condensed, Serif Condensed Bold) 2.20 (Sans Bold Oblique, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique, Serif Bold Italic, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.32 (Sans ExtraLight) -U+10f0 uni10F0 2.18 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold, Sans Mono, Sans Mono Bold, Serif, Serif Bold, Serif Condensed, Serif Condensed Bold) 2.20 (Sans Bold Oblique, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique, Serif Bold Italic, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.32 (Sans ExtraLight) -U+10f1 uni10F1 2.18 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold, Sans Mono, Sans Mono Bold, Serif, Serif Bold, Serif Condensed, Serif Condensed Bold) 2.20 (Sans Bold Oblique, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique, Serif Bold Italic, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.32 (Sans ExtraLight) -U+10f2 uni10F2 2.18 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold, Sans Mono, Sans Mono Bold, Serif, Serif Bold, Serif Condensed, Serif Condensed Bold) 2.20 (Sans Bold Oblique, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique, Serif Bold Italic, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.32 (Sans ExtraLight) -U+10f3 uni10F3 2.18 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold, Sans Mono, Sans Mono Bold, Serif, Serif Bold, Serif Condensed, Serif Condensed Bold) 2.20 (Sans Bold Oblique, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique, Serif Bold Italic, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.32 (Sans ExtraLight) -U+10f4 uni10F4 2.18 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold, Sans Mono, Sans Mono Bold, Serif, Serif Bold, Serif Condensed, Serif Condensed Bold) 2.20 (Sans Bold Oblique, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique, Serif Bold Italic, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.32 (Sans ExtraLight) -U+10f5 uni10F5 2.18 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold, Sans Mono, Sans Mono Bold, Serif, Serif Bold, Serif Condensed, Serif Condensed Bold) 2.20 (Sans Bold Oblique, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique, Serif Bold Italic, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.32 (Sans ExtraLight) -U+10f6 uni10F6 2.18 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold, Sans Mono, Sans Mono Bold, Serif, Serif Bold, Serif Condensed, Serif Condensed Bold) 2.20 (Sans Bold Oblique, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique, Serif Bold Italic, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.32 (Sans ExtraLight) -U+10f7 uni10F7 2.18 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold, Sans Mono, Sans Mono Bold, Serif, Serif Bold, Serif Condensed, Serif Condensed Bold) 2.20 (Sans Bold Oblique, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique, Serif Bold Italic, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.32 (Sans ExtraLight) -U+10f8 uni10F8 2.18 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold, Sans Mono, Sans Mono Bold, Serif, Serif Bold, Serif Condensed, Serif Condensed Bold) 2.20 (Sans Bold Oblique, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique, Serif Bold Italic, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.32 (Sans ExtraLight) -U+10f9 uni10F9 2.18 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold, Sans Mono, Sans Mono Bold, Serif, Serif Bold, Serif Condensed, Serif Condensed Bold) 2.20 (Sans Bold Oblique, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique, Serif Bold Italic, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.32 (Sans ExtraLight) -U+10fa uni10FA 2.18 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold, Sans Mono, Sans Mono Bold, Serif, Serif Bold, Serif Condensed, Serif Condensed Bold) 2.20 (Sans Bold Oblique, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique, Serif Bold Italic, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.32 (Sans ExtraLight) -U+10fb uni10FB 2.18 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold, Sans Mono, Sans Mono Bold, Serif, Serif Bold, Serif Condensed, Serif Condensed Bold) 2.20 (Sans Bold Oblique, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique, Serif Bold Italic, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.32 (Sans ExtraLight) -U+10fc uni10FC 2.18 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold, Sans Mono, Sans Mono Bold, Serif, Serif Bold, Serif Condensed, Serif Condensed Bold) 2.20 (Sans Bold Oblique, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique, Serif Bold Italic, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.32 (Sans ExtraLight) -U+1401 uni1401 2.12 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1402 uni1402 2.13 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1403 uni1403 2.12 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1404 uni1404 2.12 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1405 uni1405 2.12 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1406 uni1406 2.12 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1407 uni1407 2.15 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1409 uni1409 2.15 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+140a uni140A 2.12 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+140b uni140B 2.12 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+140c uni140C 2.15 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+140d uni140D 2.15 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+140e uni140E 2.15 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+140f uni140F 2.15 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1410 uni1410 2.15 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1411 uni1411 2.15 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1412 uni1412 2.15 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1413 uni1413 2.15 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1414 uni1414 2.15 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1415 uni1415 2.15 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1416 uni1416 2.15 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1417 uni1417 2.15 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1418 uni1418 2.15 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1419 uni1419 2.15 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+141a uni141A 2.15 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+141b uni141B 2.15 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+141d uni141D 2.15 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+141e uni141E 2.15 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+141f uni141F 2.15 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1420 uni1420 2.15 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1421 uni1421 2.15 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1422 uni1422 2.15 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1423 uni1423 2.15 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1424 uni1424 2.15 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1425 uni1425 2.15 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1426 uni1426 2.12 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1427 uni1427 2.15 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1428 uni1428 2.15 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1429 uni1429 2.15 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+142a uni142A 2.15 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+142b uni142B 2.15 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+142c uni142C 2.15 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+142d uni142D 2.15 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+142e uni142E 2.15 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+142f uni142F 2.12 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1430 uni1430 2.13 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1431 uni1431 2.12 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1432 uni1432 2.12 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1433 uni1433 2.12 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1434 uni1434 2.12 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1435 uni1435 2.15 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1437 uni1437 2.15 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1438 uni1438 2.12 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1439 uni1439 2.12 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+143a uni143A 2.15 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+143b uni143B 2.15 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+143c uni143C 2.15 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+143d uni143D 2.15 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+143e uni143E 2.15 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+143f uni143F 2.15 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1440 uni1440 2.15 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1441 uni1441 2.15 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1442 uni1442 2.15 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1443 uni1443 2.15 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1444 uni1444 2.15 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1445 uni1445 2.15 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1446 uni1446 2.15 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1447 uni1447 2.15 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1448 uni1448 2.15 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1449 uni1449 2.12 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+144a uni144A 2.12 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+144c uni144C 2.12 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+144d uni144D 2.13 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+144e uni144E 2.12 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+144f uni144F 2.12 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1450 uni1450 2.12 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1451 uni1451 2.12 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1452 uni1452 2.15 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1454 uni1454 2.15 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1455 uni1455 2.12 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1456 uni1456 2.12 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1457 uni1457 2.15 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1458 uni1458 2.15 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1459 uni1459 2.15 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+145a uni145A 2.15 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+145b uni145B 2.15 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+145c uni145C 2.15 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+145d uni145D 2.15 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+145e uni145E 2.15 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+145f uni145F 2.15 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1460 uni1460 2.15 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1461 uni1461 2.15 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1462 uni1462 2.15 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1463 uni1463 2.15 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1464 uni1464 2.15 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1465 uni1465 2.15 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1466 uni1466 2.12 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1467 uni1467 2.15 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1468 uni1468 2.15 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1469 uni1469 2.15 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+146a uni146A 2.15 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+146b uni146B 2.12 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+146c uni146C 2.13 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+146d uni146D 2.12 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+146e uni146E 2.12 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+146f uni146F 2.12 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1470 uni1470 2.12 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1471 uni1471 2.15 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1472 uni1472 2.12 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1473 uni1473 2.12 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1474 uni1474 2.15 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1475 uni1475 2.15 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1476 uni1476 2.15 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1477 uni1477 2.15 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1478 uni1478 2.15 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1479 uni1479 2.15 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+147a uni147A 2.15 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+147b uni147B 2.15 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+147c uni147C 2.15 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+147d uni147D 2.15 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+147e uni147E 2.15 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+147f uni147F 2.15 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1480 uni1480 2.15 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1481 uni1481 2.15 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1482 uni1482 2.15 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1483 uni1483 2.12 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1484 uni1484 2.15 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1485 uni1485 2.15 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1486 uni1486 2.15 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1487 uni1487 2.15 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1488 uni1488 2.15 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1489 uni1489 2.12 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+148a uni148A 2.13 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+148b uni148B 2.12 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+148c uni148C 2.12 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+148d uni148D 2.12 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+148e uni148E 2.12 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+148f uni148F 2.15 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1490 uni1490 2.12 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1491 uni1491 2.12 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1492 uni1492 2.15 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1493 uni1493 2.15 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1494 uni1494 2.15 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1495 uni1495 2.15 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1496 uni1496 2.15 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1497 uni1497 2.15 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1498 uni1498 2.15 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1499 uni1499 2.15 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+149a uni149A 2.15 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+149b uni149B 2.15 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+149c uni149C 2.15 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+149d uni149D 2.15 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+149e uni149E 2.15 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+149f uni149F 2.15 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+14a0 uni14A0 2.15 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+14a1 uni14A1 2.12 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+14a2 uni14A2 2.15 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+14a3 uni14A3 2.12 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+14a4 uni14A4 2.13 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold, Sans Condensed Oblique, Sans Oblique) 2.15 (Sans Bold Oblique, Sans Condensed Bold Oblique) -U+14a5 uni14A5 2.12 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+14a6 uni14A6 2.12 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+14a7 uni14A7 2.12 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+14a8 uni14A8 2.12 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+14a9 uni14A9 2.15 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+14aa uni14AA 2.12 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+14ab uni14AB 2.12 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+14ac uni14AC 2.15 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+14ad uni14AD 2.15 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+14ae uni14AE 2.15 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+14af uni14AF 2.15 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+14b0 uni14B0 2.15 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+14b1 uni14B1 2.15 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+14b2 uni14B2 2.15 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+14b3 uni14B3 2.15 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+14b4 uni14B4 2.15 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+14b5 uni14B5 2.15 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+14b6 uni14B6 2.15 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+14b7 uni14B7 2.15 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+14b8 uni14B8 2.15 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+14b9 uni14B9 2.15 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+14ba uni14BA 2.15 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+14bb uni14BB 2.12 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+14bc uni14BC 2.15 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+14bd uni14BD 2.15 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+14c0 uni14C0 2.12 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+14c1 uni14C1 2.13 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+14c2 uni14C2 2.12 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+14c3 uni14C3 2.12 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+14c4 uni14C4 2.12 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+14c5 uni14C5 2.12 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+14c6 uni14C6 2.15 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+14c7 uni14C7 2.12 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+14c8 uni14C8 2.12 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+14c9 uni14C9 2.15 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+14ca uni14CA 2.15 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+14cb uni14CB 2.15 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+14cc uni14CC 2.15 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+14cd uni14CD 2.15 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+14ce uni14CE 2.15 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+14cf uni14CF 2.15 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+14d0 uni14D0 2.12 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+14d1 uni14D1 2.15 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+14d2 uni14D2 2.15 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+14d3 uni14D3 2.12 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+14d4 uni14D4 2.13 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+14d5 uni14D5 2.12 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+14d6 uni14D6 2.12 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+14d7 uni14D7 2.12 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+14d8 uni14D8 2.12 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+14d9 uni14D9 2.15 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+14da uni14DA 2.12 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+14db uni14DB 2.12 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+14dc uni14DC 2.15 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+14dd uni14DD 2.15 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+14de uni14DE 2.15 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+14df uni14DF 2.15 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+14e0 uni14E0 2.15 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+14e1 uni14E1 2.15 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+14e2 uni14E2 2.15 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+14e3 uni14E3 2.15 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+14e4 uni14E4 2.15 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+14e5 uni14E5 2.15 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+14e6 uni14E6 2.15 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+14e7 uni14E7 2.15 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+14e8 uni14E8 2.15 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+14e9 uni14E9 2.15 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+14ea uni14EA 2.12 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+14ec uni14EC 2.15 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+14ed uni14ED 2.12 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+14ee uni14EE 2.13 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+14ef uni14EF 2.12 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+14f0 uni14F0 2.12 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+14f1 uni14F1 2.12 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+14f2 uni14F2 2.12 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+14f3 uni14F3 2.15 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+14f4 uni14F4 2.12 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+14f5 uni14F5 2.12 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+14f6 uni14F6 2.15 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+14f7 uni14F7 2.15 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+14f8 uni14F8 2.15 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+14f9 uni14F9 2.15 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+14fa uni14FA 2.15 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+14fb uni14FB 2.15 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+14fc uni14FC 2.15 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+14fd uni14FD 2.15 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+14fe uni14FE 2.15 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+14ff uni14FF 2.15 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1500 uni1500 2.15 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1501 uni1501 2.15 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1502 uni1502 2.15 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1503 uni1503 2.15 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1504 uni1504 2.15 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1505 uni1505 2.12 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1506 uni1506 2.15 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1507 uni1507 2.15 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1510 uni1510 2.15 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1511 uni1511 2.15 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1512 uni1512 2.15 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1513 uni1513 2.15 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1514 uni1514 2.15 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1515 uni1515 2.15 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1516 uni1516 2.15 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1517 uni1517 2.15 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1518 uni1518 2.15 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1519 uni1519 2.15 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+151a uni151A 2.15 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+151b uni151B 2.15 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+151c uni151C 2.15 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+151d uni151D 2.15 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+151e uni151E 2.15 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+151f uni151F 2.15 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1520 uni1520 2.15 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1521 uni1521 2.15 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1522 uni1522 2.15 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1523 uni1523 2.15 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1524 uni1524 2.15 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1525 uni1525 2.15 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1526 uni1526 2.12 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1527 uni1527 2.13 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1528 uni1528 2.12 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1529 uni1529 2.12 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+152a uni152A 2.12 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+152b uni152B 2.12 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+152c uni152C 2.15 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+152d uni152D 2.12 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+152e uni152E 2.12 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+152f uni152F 2.15 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1530 uni1530 2.15 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1531 uni1531 2.15 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1532 uni1532 2.15 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1533 uni1533 2.15 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1534 uni1534 2.15 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1535 uni1535 2.15 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1536 uni1536 2.15 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1537 uni1537 2.15 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1538 uni1538 2.15 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1539 uni1539 2.15 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+153a uni153A 2.15 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+153b uni153B 2.15 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+153c uni153C 2.15 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+153d uni153D 2.15 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+153e uni153E 2.12 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1540 uni1540 2.15 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1541 uni1541 2.15 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1542 uni1542 2.12 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1543 uni1543 2.12 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1544 uni1544 2.12 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1545 uni1545 2.13 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1546 uni1546 2.12 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1547 uni1547 2.12 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1548 uni1548 2.12 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1549 uni1549 2.12 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+154a uni154A 2.12 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+154b uni154B 2.12 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+154c uni154C 2.12 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+154d uni154D 2.12 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+154e uni154E 2.15 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+154f uni154F 2.15 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1550 uni1550 2.12 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1552 uni1552 2.15 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1553 uni1553 2.12 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1554 uni1554 2.13 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1555 uni1555 2.12 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1556 uni1556 2.12 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1557 uni1557 2.12 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1558 uni1558 2.12 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1559 uni1559 2.12 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+155a uni155A 2.12 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+155b uni155B 2.15 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+155c uni155C 2.15 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+155d uni155D 2.12 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+155e uni155E 2.12 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+155f uni155F 2.12 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1560 uni1560 2.12 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1561 uni1561 2.12 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1562 uni1562 2.12 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1563 uni1563 2.12 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1564 uni1564 2.12 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1565 uni1565 2.12 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1566 uni1566 2.12 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1567 uni1567 2.12 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1568 uni1568 2.15 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1569 uni1569 2.15 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+156a uni156A 2.12 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1574 uni1574 2.15 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1575 uni1575 2.15 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1576 uni1576 2.15 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1577 uni1577 2.15 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1578 uni1578 2.15 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1579 uni1579 2.15 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+157a uni157A 2.15 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+157b uni157B 2.15 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+157c uni157C 2.12 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+157d uni157D 2.15 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+157e uni157E 2.13 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+157f uni157F 2.12 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1580 uni1580 2.12 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1581 uni1581 2.12 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1582 uni1582 2.12 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1583 uni1583 2.12 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1584 uni1584 2.12 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1585 uni1585 2.12 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+158a uni158A 2.12 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+158b uni158B 2.12 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+158c uni158C 2.12 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+158d uni158D 2.12 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+158e uni158E 2.13 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+158f uni158F 2.12 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1590 uni1590 2.12 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1591 uni1591 2.12 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1592 uni1592 2.12 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1593 uni1593 2.12 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1594 uni1594 2.12 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1595 uni1595 2.12 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1596 uni1596 2.12 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+15a0 uni15A0 2.12 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+15a1 uni15A1 2.12 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+15a2 uni15A2 2.12 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+15a3 uni15A3 2.12 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+15a4 uni15A4 2.12 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+15a5 uni15A5 2.12 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+15a6 uni15A6 2.12 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+15a7 uni15A7 2.15 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+15a8 uni15A8 2.15 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+15a9 uni15A9 2.15 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+15aa uni15AA 2.15 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+15ab uni15AB 2.15 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+15ac uni15AC 2.15 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+15ad uni15AD 2.15 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+15ae uni15AE 2.15 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+15af uni15AF 2.13 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+15de uni15DE 2.12 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+15e1 uni15E1 2.12 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1646 uni1646 2.15 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1647 uni1647 2.15 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+166e uni166E 2.12 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+166f uni166F 2.12 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1670 uni1670 2.12 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1671 uni1671 2.12 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1672 uni1672 2.12 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1673 uni1673 2.12 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1674 uni1674 2.12 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1675 uni1675 2.12 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1676 uni1676 2.12 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1680 uni1680 2.22 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) 2.28 (Sans ExtraLight) -U+1681 uni1681 2.22 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) 2.28 (Sans ExtraLight) -U+1682 uni1682 2.22 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) 2.28 (Sans ExtraLight) -U+1683 uni1683 2.22 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) 2.28 (Sans ExtraLight) -U+1684 uni1684 2.22 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) 2.28 (Sans ExtraLight) -U+1685 uni1685 2.22 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) 2.28 (Sans ExtraLight) -U+1686 uni1686 2.22 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) 2.28 (Sans ExtraLight) -U+1687 uni1687 2.22 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) 2.28 (Sans ExtraLight) -U+1688 uni1688 2.22 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) 2.28 (Sans ExtraLight) -U+1689 uni1689 2.22 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) 2.28 (Sans ExtraLight) -U+168a uni168A 2.22 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) 2.28 (Sans ExtraLight) -U+168b uni168B 2.22 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) 2.28 (Sans ExtraLight) -U+168c uni168C 2.22 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) 2.28 (Sans ExtraLight) -U+168d uni168D 2.22 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) 2.28 (Sans ExtraLight) -U+168e uni168E 2.22 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) 2.28 (Sans ExtraLight) -U+168f uni168F 2.22 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) 2.28 (Sans ExtraLight) -U+1690 uni1690 2.22 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) 2.28 (Sans ExtraLight) -U+1691 uni1691 2.22 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) 2.28 (Sans ExtraLight) -U+1692 uni1692 2.22 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) 2.28 (Sans ExtraLight) -U+1693 uni1693 2.22 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) 2.28 (Sans ExtraLight) -U+1694 uni1694 2.22 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) 2.28 (Sans ExtraLight) -U+1695 uni1695 2.22 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) 2.28 (Sans ExtraLight) -U+1696 uni1696 2.22 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) 2.28 (Sans ExtraLight) -U+1697 uni1697 2.22 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) 2.28 (Sans ExtraLight) -U+1698 uni1698 2.22 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) 2.28 (Sans ExtraLight) -U+1699 uni1699 2.22 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) 2.28 (Sans ExtraLight) -U+169a uni169A 2.22 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) 2.28 (Sans ExtraLight) -U+169b uni169B 2.22 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) 2.28 (Sans ExtraLight) -U+169c uni169C 2.22 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) 2.28 (Sans ExtraLight) -U+1d00 uni1D00 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.33 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) -U+1d01 uni1D01 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.33 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) -U+1d02 uni1D02 2.2 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.3 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.4 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+1d03 uni1D03 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.33 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) -U+1d04 uni1D04 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.10 (Sans ExtraLight) 2.33 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) -U+1d05 uni1D05 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.33 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) -U+1d06 uni1D06 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.33 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) -U+1d07 uni1D07 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.33 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) -U+1d08 uni1D08 2.2 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.3 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+1d09 uni1D09 2.2 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.3 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.4 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+1d0a uni1D0A 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.33 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) -U+1d0b uni1D0B 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.10 (Sans ExtraLight) 2.33 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) -U+1d0c uni1D0C 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.33 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) -U+1d0d uni1D0D 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.10 (Sans ExtraLight) 2.33 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) -U+1d0e uni1D0E 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.10 (Sans ExtraLight) 2.33 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) -U+1d0f uni1D0F 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.10 (Sans ExtraLight) 2.33 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) -U+1d10 uni1D10 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.10 (Sans ExtraLight) 2.33 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) -U+1d11 uni1D11 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.10 (Sans ExtraLight) 2.33 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) -U+1d12 uni1D12 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.10 (Sans ExtraLight) 2.33 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) -U+1d13 uni1D13 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.10 (Sans ExtraLight) 2.33 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) -U+1d14 uni1D14 2.2 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.3 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.4 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+1d15 uni1D15 2.33 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) -U+1d16 uni1D16 2.3 -U+1d17 uni1D17 2.3 -U+1d18 uni1D18 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.33 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) -U+1d19 uni1D19 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.26 (Sans ExtraLight) 2.33 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) -U+1d1a uni1D1A 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.26 (Sans ExtraLight) 2.33 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) -U+1d1b uni1D1B 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.33 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) -U+1d1c uni1D1C 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.33 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) -U+1d1d uni1D1D 2.3 -U+1d1e uni1D1E 2.3 -U+1d1f uni1D1F 2.2 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.3 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+1d20 uni1D20 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.10 (Sans ExtraLight) 2.33 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) -U+1d21 uni1D21 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.10 (Sans ExtraLight) 2.33 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) -U+1d22 uni1D22 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.10 (Sans ExtraLight) 2.33 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) -U+1d23 uni1D23 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.33 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) -U+1d24 uni1D24 2.33 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) -U+1d25 uni1D25 2.33 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) -U+1d26 uni1D26 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.10 (Sans ExtraLight) 2.33 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) -U+1d27 uni1D27 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.10 (Sans ExtraLight) 2.33 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) -U+1d28 uni1D28 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.10 (Sans ExtraLight) 2.33 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) -U+1d29 uni1D29 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.33 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) -U+1d2a uni1D2A 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.33 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) -U+1d2b uni1D2B 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.26 (Sans ExtraLight) 2.33 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) -U+1d2c uni1D2C 2.10 (Sans, Sans Bold, Sans Bold Oblique, Sans Oblique) 2.11 (Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique) 2.17 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Italic) 2.18 (Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic) 2.23 (Serif Italic Condensed) -U+1d2d uni1D2D 2.10 (Sans, Sans Bold, Sans Bold Oblique, Sans Oblique) 2.11 (Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique) 2.17 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Italic) 2.18 (Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic) 2.23 (Serif Italic Condensed) -U+1d2e uni1D2E 2.10 (Sans, Sans Bold, Sans Bold Oblique, Sans Oblique) 2.11 (Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique) 2.17 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Italic) 2.18 (Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic) 2.23 (Serif Italic Condensed) -U+1d2f uni1D2F 2.33 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) -U+1d30 uni1D30 2.10 (Sans, Sans Bold, Sans Bold Oblique, Sans Oblique) 2.11 (Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique) 2.17 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Italic) 2.18 (Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic) 2.23 (Serif Italic Condensed) -U+1d31 uni1D31 2.10 (Sans, Sans Bold, Sans Bold Oblique, Sans Oblique) 2.11 (Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique) 2.17 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Italic) 2.18 (Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic) 2.23 (Serif Italic Condensed) -U+1d32 uni1D32 2.10 (Sans, Sans Bold, Sans Bold Oblique, Sans Oblique) 2.11 (Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique) 2.17 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Italic) 2.18 (Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic) 2.23 (Serif Italic Condensed) -U+1d33 uni1D33 2.10 (Sans, Sans Bold, Sans Bold Oblique, Sans Oblique) 2.11 (Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique) 2.17 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Italic) 2.18 (Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic) 2.23 (Serif Italic Condensed) -U+1d34 uni1D34 2.10 (Sans, Sans Bold, Sans Bold Oblique, Sans Oblique) 2.11 (Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique) 2.17 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Italic) 2.18 (Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic) 2.23 (Serif Italic Condensed) -U+1d35 uni1D35 2.10 (Sans, Sans Bold, Sans Bold Oblique, Sans Oblique) 2.11 (Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique) 2.17 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Italic) 2.18 (Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic) 2.23 (Serif Italic Condensed) -U+1d36 uni1D36 2.10 (Sans, Sans Bold, Sans Bold Oblique, Sans Oblique) 2.11 (Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique) 2.17 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Italic) 2.18 (Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic) 2.23 (Serif Italic Condensed) -U+1d37 uni1D37 2.10 (Sans, Sans Bold, Sans Bold Oblique, Sans Oblique) 2.11 (Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique) 2.17 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Italic) 2.18 (Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic) 2.23 (Serif Italic Condensed) -U+1d38 uni1D38 2.10 (Sans, Sans Bold, Sans Bold Oblique, Sans Oblique) 2.11 (Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique) 2.17 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Italic) 2.18 (Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic) 2.23 (Serif Italic Condensed) -U+1d39 uni1D39 2.10 (Sans, Sans Bold, Sans Bold Oblique, Sans Oblique) 2.11 (Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique) 2.17 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Italic) 2.18 (Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic) 2.23 (Serif Italic Condensed) -U+1d3a uni1D3A 2.10 (Sans, Sans Bold, Sans Bold Oblique, Sans Oblique) 2.11 (Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique) 2.17 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Italic) 2.18 (Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic) 2.23 (Serif Italic Condensed) -U+1d3b uni1D3B 2.10 (Sans, Sans Bold, Sans Bold Oblique, Sans Oblique) 2.11 (Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique) 2.17 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Italic) 2.18 (Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic) 2.23 (Serif Italic Condensed) -U+1d3c uni1D3C 2.10 (Sans, Sans Bold, Sans Bold Oblique, Sans Oblique) 2.11 (Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique) 2.17 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Italic) 2.18 (Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic) 2.23 (Serif Italic Condensed) -U+1d3d uni1D3D 2.10 (Sans, Sans Bold, Sans Bold Oblique, Sans Oblique) 2.11 (Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique) 2.17 (Sans Mono Oblique) 2.33 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) -U+1d3e uni1D3E 2.10 (Sans, Sans Bold, Sans Bold Oblique, Sans Oblique) 2.11 (Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique) 2.17 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Italic) 2.18 (Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic) 2.23 (Serif Italic Condensed) -U+1d3f uni1D3F 2.10 (Sans, Sans Bold, Sans Bold Oblique, Sans Oblique) 2.11 (Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique) 2.17 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Italic) 2.18 (Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic) 2.23 (Serif Italic Condensed) -U+1d40 uni1D40 2.10 (Sans, Sans Bold, Sans Bold Oblique, Sans Oblique) 2.11 (Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique) 2.17 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Italic) 2.18 (Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic) 2.23 (Serif Italic Condensed) -U+1d41 uni1D41 2.10 (Sans, Sans Bold, Sans Bold Oblique, Sans Oblique) 2.11 (Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique) 2.17 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Italic) 2.18 (Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic) 2.23 (Serif Italic Condensed) -U+1d42 uni1D42 2.10 (Sans, Sans Bold, Sans Bold Oblique, Sans Oblique) 2.11 (Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique) 2.17 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Italic) 2.18 (Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic) 2.23 (Serif Italic Condensed) -U+1d43 uni1D43 2.3 -U+1d44 uni1D44 2.3 -U+1d45 uni1D45 2.3 -U+1d46 uni1D46 2.3 -U+1d47 uni1D47 2.3 -U+1d48 uni1D48 2.3 -U+1d49 uni1D49 2.3 -U+1d4a uni1D4A 2.3 -U+1d4b uni1D4B 2.3 -U+1d4c uni1D4C 2.3 -U+1d4d uni1D4D 2.3 -U+1d4e uni1D4E 2.3 -U+1d4f uni1D4F 2.3 -U+1d50 uni1D50 2.3 -U+1d51 uni1D51 2.3 -U+1d52 uni1D52 2.3 -U+1d53 uni1D53 2.3 -U+1d54 uni1D54 2.3 -U+1d55 uni1D55 2.3 -U+1d56 uni1D56 2.3 -U+1d57 uni1D57 2.3 -U+1d58 uni1D58 2.3 -U+1d59 uni1D59 2.3 -U+1d5a uni1D5A 2.3 -U+1d5b uni1D5B 2.3 -U+1d5c uni1D5C 2.33 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) -U+1d5d uni1D5D 2.10 (Sans, Sans Bold, Sans Bold Oblique, Sans Oblique) 2.11 (Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique) 2.33 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) -U+1d5e uni1D5E 2.10 (Sans, Sans Bold, Sans Bold Oblique, Sans Oblique) 2.11 (Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique) 2.33 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) -U+1d5f uni1D5F 2.10 (Sans, Sans Bold, Sans Bold Oblique, Sans Oblique) 2.11 (Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique) 2.33 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) -U+1d60 uni1D60 2.10 (Sans, Sans Bold, Sans Bold Oblique, Sans Oblique) 2.11 (Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique) 2.33 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) -U+1d61 uni1D61 2.10 (Sans, Sans Bold, Sans Bold Oblique, Sans Oblique) 2.11 (Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique) 2.33 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) -U+1d62 uni1D62 2.10 (Sans, Sans Bold, Sans Bold Oblique, Sans Oblique) 2.11 (Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique) 2.17 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Italic) 2.18 (Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic) 2.23 (Serif Italic Condensed) -U+1d63 uni1D63 2.10 (Sans, Sans Bold, Sans Bold Oblique, Sans Oblique) 2.11 (Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique) 2.17 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Italic) 2.18 (Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic) 2.23 (Serif Italic Condensed) -U+1d64 uni1D64 2.10 (Sans, Sans Bold, Sans Bold Oblique, Sans Oblique) 2.11 (Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique) 2.17 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Italic) 2.18 (Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic) 2.23 (Serif Italic Condensed) -U+1d65 uni1D65 2.10 (Sans, Sans Bold, Sans Bold Oblique, Sans Oblique) 2.11 (Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique) 2.17 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Italic) 2.18 (Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic) 2.23 (Serif Italic Condensed) -U+1d66 uni1D66 2.10 (Sans, Sans Bold, Sans Bold Oblique, Sans Oblique) 2.11 (Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique) 2.33 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) -U+1d67 uni1D67 2.10 (Sans, Sans Bold, Sans Bold Oblique, Sans Oblique) 2.11 (Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique) 2.33 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) -U+1d68 uni1D68 2.10 (Sans, Sans Bold, Sans Bold Oblique, Sans Oblique) 2.11 (Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique) 2.33 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) -U+1d69 uni1D69 2.10 (Sans, Sans Bold, Sans Bold Oblique, Sans Oblique) 2.11 (Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique) 2.33 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) -U+1d6a uni1D6A 2.10 (Sans, Sans Bold, Sans Bold Oblique, Sans Oblique) 2.11 (Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique) 2.33 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) -U+1d6b uni1D6B 2.33 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) -U+1d77 uni1D77 2.2 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.3 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.4 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+1d78 uni1D78 2.10 (Sans, Sans Bold, Sans Bold Oblique, Sans Oblique) 2.11 (Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique) 2.17 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Italic) 2.18 (Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic) 2.23 (Serif Italic Condensed) -U+1d7b uni1D7B 2.3 -U+1d7c uni1D7C 2.34 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) -U+1d7d uni1D7D 2.32 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.34 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) -U+1d7e uni1D7E 2.34 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) -U+1d7f uni1D7F 2.34 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) -U+1d85 uni1D85 2.3 -U+1d9b uni1D9B 2.3 -U+1d9c uni1D9C 2.3 -U+1d9d uni1D9D 2.3 -U+1d9e uni1D9E 2.3 -U+1d9f uni1D9F 2.3 -U+1da0 uni1DA0 2.3 -U+1da1 uni1DA1 2.3 -U+1da2 uni1DA2 2.3 -U+1da3 uni1DA3 2.3 -U+1da4 uni1DA4 2.3 -U+1da5 uni1DA5 2.3 -U+1da6 uni1DA6 2.3 -U+1da7 uni1DA7 2.3 -U+1da8 uni1DA8 2.3 -U+1da9 uni1DA9 2.3 -U+1daa uni1DAA 2.3 -U+1dab uni1DAB 2.3 -U+1dac uni1DAC 2.3 -U+1dad uni1DAD 2.3 -U+1dae uni1DAE 2.3 -U+1daf uni1DAF 2.3 -U+1db0 uni1DB0 2.3 -U+1db1 uni1DB1 2.3 -U+1db2 uni1DB2 2.3 -U+1db3 uni1DB3 2.3 -U+1db4 uni1DB4 2.3 -U+1db5 uni1DB5 2.3 -U+1db6 uni1DB6 2.3 -U+1db7 uni1DB7 2.3 -U+1db8 uni1DB8 2.10 (Sans, Sans Bold, Sans Bold Oblique, Sans Oblique) 2.11 (Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique) 2.33 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) -U+1db9 uni1DB9 2.3 -U+1dba uni1DBA 2.3 -U+1dbb uni1DBB 2.3 -U+1dbc uni1DBC 2.3 -U+1dbd uni1DBD 2.3 -U+1dbe uni1DBE 2.3 -U+1dbf uni1DBF 2.3 -U+1dc4 uni1DC4 2.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.30 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) -U+1dc5 uni1DC5 2.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.30 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) -U+1dc6 uni1DC6 2.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.30 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) -U+1dc7 uni1DC7 2.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.30 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) -U+1dc8 uni1DC8 2.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.30 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) -U+1dc9 uni1DC9 2.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.30 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) -U+1e00 uni1E00 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.14 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.23 (Serif Italic Condensed) -U+1e01 uni1E01 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.14 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.23 (Serif Italic Condensed) -U+1e02 uni1E02 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.14 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.23 (Serif Italic Condensed) -U+1e03 uni1E03 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.14 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.23 (Serif Italic Condensed) -U+1e04 uni1E04 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.14 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.23 (Serif Italic Condensed) -U+1e05 uni1E05 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.14 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.23 (Serif Italic Condensed) -U+1e06 uni1E06 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.14 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.23 (Serif Italic Condensed) -U+1e07 uni1E07 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.14 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.23 (Serif Italic Condensed) -U+1e08 uni1E08 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.22 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.23 (Serif Italic Condensed) -U+1e09 uni1E09 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.22 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.23 (Serif Italic Condensed) -U+1e0a uni1E0A 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.14 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.23 (Serif Italic Condensed) -U+1e0b uni1E0B 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.14 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.23 (Serif Italic Condensed) -U+1e0c uni1E0C 2.1 -U+1e0d uni1E0D 2.1 -U+1e0e uni1E0E 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.7 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.23 (Serif Italic Condensed) -U+1e0f uni1E0F 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.7 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.23 (Serif Italic Condensed) -U+1e10 uni1E10 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.22 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.23 (Serif Italic Condensed) -U+1e11 uni1E11 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.22 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.23 (Serif Italic Condensed) -U+1e12 uni1E12 1.13 -U+1e13 uni1E13 1.13 -U+1e14 uni1E14 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.5 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+1e15 uni1E15 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.5 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+1e16 uni1E16 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.5 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+1e17 uni1E17 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.5 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+1e18 uni1E18 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.14 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.23 (Serif Italic Condensed) -U+1e19 uni1E19 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.14 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.23 (Serif Italic Condensed) -U+1e1a uni1E1A 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.14 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.23 (Serif Italic Condensed) -U+1e1b uni1E1B 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.14 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.23 (Serif Italic Condensed) -U+1e1c uni1E1C 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) 2.14 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.16 (Serif, Serif Bold, Serif Bold Italic, Serif Italic) 2.17 (Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic) 2.23 (Serif Italic Condensed) -U+1e1d uni1E1D 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) 2.14 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.16 (Serif, Serif Bold, Serif Bold Italic, Serif Italic) 2.17 (Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic) 2.23 (Serif Italic Condensed) -U+1e1e uni1E1E 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.14 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.23 (Serif Italic Condensed) -U+1e1f uni1E1F 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.14 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.23 (Serif Italic Condensed) -U+1e20 uni1E20 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.14 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.23 (Serif Italic Condensed) -U+1e21 uni1E21 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.14 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.23 (Serif Italic Condensed) -U+1e22 uni1E22 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.14 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.23 (Serif Italic Condensed) -U+1e23 uni1E23 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.14 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.23 (Serif Italic Condensed) -U+1e24 uni1E24 2.1 -U+1e25 uni1E25 2.1 -U+1e26 uni1E26 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.26 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) -U+1e27 uni1E27 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.26 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) -U+1e28 uni1E28 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.14 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.23 (Serif Italic Condensed) -U+1e29 uni1E29 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.14 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.23 (Serif Italic Condensed) -U+1e2a uni1E2A 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.14 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.23 (Serif Italic Condensed) -U+1e2b uni1E2B 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.14 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.23 (Serif Italic Condensed) -U+1e2c uni1E2C 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.14 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.23 (Serif Italic Condensed) -U+1e2d uni1E2D 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.14 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.23 (Serif Italic Condensed) -U+1e2e uni1E2E 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.5 (Sans ExtraLight) 2.32 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) -U+1e2f uni1E2F 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.5 (Sans ExtraLight) 2.32 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) -U+1e30 uni1E30 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.7 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.23 (Serif Italic Condensed) -U+1e31 uni1E31 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.7 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.23 (Serif Italic Condensed) -U+1e32 uni1E32 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.7 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.23 (Serif Italic Condensed) -U+1e33 uni1E33 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.7 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.23 (Serif Italic Condensed) -U+1e34 uni1E34 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.7 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.23 (Serif Italic Condensed) -U+1e35 uni1E35 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.7 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.23 (Serif Italic Condensed) -U+1e36 uni1E36 2.1 -U+1e37 uni1E37 2.1 -U+1e38 uni1E38 2.1 -U+1e39 uni1E39 2.1 -U+1e3a uni1E3A 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.14 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.23 (Serif Italic Condensed) -U+1e3b uni1E3B 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.14 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.23 (Serif Italic Condensed) -U+1e3c uni1E3C 1.13 -U+1e3d uni1E3D 1.13 -U+1e3e uni1E3E 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.7 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.23 (Serif Italic Condensed) -U+1e3f uni1E3F 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.7 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.23 (Serif Italic Condensed) -U+1e40 uni1E40 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.14 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.23 (Serif Italic Condensed) -U+1e41 uni1E41 2.1 -U+1e42 uni1E42 2.1 -U+1e43 uni1E43 2.1 -U+1e44 uni1E44 1.13 -U+1e45 uni1E45 1.13 -U+1e46 uni1E46 2.1 -U+1e47 uni1E47 2.1 -U+1e48 uni1E48 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.14 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.23 (Serif Italic Condensed) -U+1e49 uni1E49 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.14 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.23 (Serif Italic Condensed) -U+1e4a uni1E4A 1.13 -U+1e4b uni1E4B 1.13 -U+1e4c uni1E4C 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.5 (Sans ExtraLight) 2.30 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) -U+1e4d uni1E4D 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.5 (Sans ExtraLight) 2.30 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) -U+1e4e uni1E4E 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.5 (Sans ExtraLight) 2.32 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) -U+1e4f uni1E4F 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.5 (Sans ExtraLight) 2.32 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) -U+1e50 uni1E50 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.5 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+1e51 uni1E51 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.5 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+1e52 uni1E52 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.5 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+1e53 uni1E53 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.5 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+1e54 uni1E54 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.26 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) -U+1e55 uni1E55 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.26 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) -U+1e56 uni1E56 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.14 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.23 (Serif Italic Condensed) -U+1e57 uni1E57 2.1 -U+1e58 uni1E58 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.14 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.23 (Serif Italic Condensed) -U+1e59 uni1E59 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.14 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.23 (Serif Italic Condensed) -U+1e5a uni1E5A 2.1 -U+1e5b uni1E5B 2.1 -U+1e5c uni1E5C 2.1 -U+1e5d uni1E5D 2.1 -U+1e5e uni1E5E 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.14 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.23 (Serif Italic Condensed) -U+1e5f uni1E5F 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.14 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.23 (Serif Italic Condensed) -U+1e60 uni1E60 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.14 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.23 (Serif Italic Condensed) -U+1e61 uni1E61 2.1 -U+1e62 uni1E62 2.1 -U+1e63 uni1E63 2.1 -U+1e64 uni1E64 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) 2.32 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) -U+1e65 uni1E65 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) 2.32 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) -U+1e66 uni1E66 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.5 (Sans ExtraLight) 2.32 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) -U+1e67 uni1E67 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.5 (Sans ExtraLight) 2.32 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) -U+1e68 uni1E68 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.14 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.23 (Serif Italic Condensed) -U+1e69 uni1E69 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.14 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.23 (Serif Italic Condensed) -U+1e6a uni1E6A 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.14 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.23 (Serif Italic Condensed) -U+1e6b uni1E6B 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.14 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.23 (Serif Italic Condensed) -U+1e6c uni1E6C 2.1 -U+1e6d uni1E6D 2.1 -U+1e6e uni1E6E 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.14 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.23 (Serif Italic Condensed) -U+1e6f uni1E6F 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.14 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.23 (Serif Italic Condensed) -U+1e70 uni1E70 1.13 -U+1e71 uni1E71 1.13 -U+1e72 uni1E72 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.14 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.23 (Serif Italic Condensed) -U+1e73 uni1E73 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.14 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.23 (Serif Italic Condensed) -U+1e74 uni1E74 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.14 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.23 (Serif Italic Condensed) -U+1e75 uni1E75 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.14 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.23 (Serif Italic Condensed) -U+1e76 uni1E76 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.14 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.23 (Serif Italic Condensed) -U+1e77 uni1E77 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.14 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.23 (Serif Italic Condensed) -U+1e78 uni1E78 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.5 (Sans ExtraLight) 2.23 (Serif Italic Condensed) 2.30 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) -U+1e79 uni1E79 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.5 (Sans ExtraLight) 2.23 (Serif Italic Condensed) 2.30 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) -U+1e7a uni1E7A 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.5 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+1e7b uni1E7B 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.5 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+1e7c uni1E7C 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.26 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) -U+1e7d uni1E7D 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.26 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) -U+1e7e uni1E7E 2.1 -U+1e7f uni1E7F 2.1 -U+1e80 Wgrave 1.2 -U+1e81 wgrave 1.2 -U+1e82 Wacute 1.2 -U+1e83 wacute 1.2 -U+1e84 Wdieresis 1.2 -U+1e85 wdieresis 1.2 -U+1e86 uni1E86 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.14 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.23 (Serif Italic Condensed) -U+1e87 uni1E87 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.14 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.23 (Serif Italic Condensed) -U+1e88 uni1E88 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.14 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.23 (Serif Italic Condensed) -U+1e89 uni1E89 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.14 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.23 (Serif Italic Condensed) -U+1e8a uni1E8A 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.14 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.23 (Serif Italic Condensed) -U+1e8b uni1E8B 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.14 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.23 (Serif Italic Condensed) -U+1e8c uni1E8C 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.26 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) -U+1e8d uni1E8D 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.26 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) -U+1e8e uni1E8E 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.7 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.23 (Serif Italic Condensed) -U+1e8f uni1E8F 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.7 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.23 (Serif Italic Condensed) -U+1e90 uni1E90 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.26 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) -U+1e91 uni1E91 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.26 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) -U+1e92 uni1E92 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.14 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.23 (Serif Italic Condensed) -U+1e93 uni1E93 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.14 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.23 (Serif Italic Condensed) -U+1e94 uni1E94 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.14 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.23 (Serif Italic Condensed) -U+1e95 uni1E95 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.14 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.23 (Serif Italic Condensed) -U+1e96 uni1E96 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.14 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.23 (Serif Italic Condensed) -U+1e97 uni1E97 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.26 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) -U+1e98 uni1E98 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.26 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) -U+1e99 uni1E99 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.26 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) -U+1e9a uni1E9A 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.10 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+1e9b uni1E9B 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.13 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.23 (Serif Italic Condensed) -U+1e9c uni1E9C 2.32 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) 2.33 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) -U+1e9d uni1E9D 2.32 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) 2.33 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) -U+1e9e uni1E9E 2.28 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) 2.32 (Sans ExtraLight) -U+1e9f uni1E9F 2.26 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique) 2.27 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) -U+1ea0 uni1EA0 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.14 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) -U+1ea1 uni1EA1 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.14 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) -U+1ea2 uni1EA2 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.5 (Sans ExtraLight) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) -U+1ea3 uni1EA3 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.5 (Sans ExtraLight) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) -U+1ea4 uni1EA4 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.5 (Sans ExtraLight) 2.32 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.36 (Math TeX Gyre Regular) -U+1ea5 uni1EA5 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.5 (Sans ExtraLight) 2.32 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.36 (Math TeX Gyre Regular) -U+1ea6 uni1EA6 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.5 (Sans ExtraLight) 2.32 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.36 (Math TeX Gyre Regular) -U+1ea7 uni1EA7 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.5 (Sans ExtraLight) 2.32 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.36 (Math TeX Gyre Regular) -U+1ea8 uni1EA8 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.5 (Sans ExtraLight) 2.32 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.36 (Math TeX Gyre Regular) -U+1ea9 uni1EA9 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.5 (Sans ExtraLight) 2.32 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.36 (Math TeX Gyre Regular) -U+1eaa uni1EAA 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.5 (Sans ExtraLight) 2.32 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.36 (Math TeX Gyre Regular) -U+1eab uni1EAB 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.5 (Sans ExtraLight) 2.32 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.36 (Math TeX Gyre Regular) -U+1eac uni1EAC 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.26 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.36 (Math TeX Gyre Regular) -U+1ead uni1EAD 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.26 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.36 (Math TeX Gyre Regular) -U+1eae uni1EAE 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.5 (Sans ExtraLight) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) -U+1eaf uni1EAF 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.5 (Sans ExtraLight) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) -U+1eb0 uni1EB0 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.5 (Sans ExtraLight) 2.22 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) -U+1eb1 uni1EB1 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.5 (Sans ExtraLight) 2.22 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) -U+1eb2 uni1EB2 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.5 (Sans ExtraLight) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) -U+1eb3 uni1EB3 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.5 (Sans ExtraLight) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) -U+1eb4 uni1EB4 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.5 (Sans ExtraLight) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) -U+1eb5 uni1EB5 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.5 (Sans ExtraLight) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) -U+1eb6 uni1EB6 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.26 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.36 (Math TeX Gyre Regular) -U+1eb7 uni1EB7 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.26 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.36 (Math TeX Gyre Regular) -U+1eb8 uni1EB8 2.2 -U+1eb9 uni1EB9 2.2 -U+1eba uni1EBA 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.5 (Sans ExtraLight) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) -U+1ebb uni1EBB 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.5 (Sans ExtraLight) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) -U+1ebc uni1EBC 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.7 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) -U+1ebd uni1EBD 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.7 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) -U+1ebe uni1EBE 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.5 (Sans ExtraLight) 2.32 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.36 (Math TeX Gyre Regular) -U+1ebf uni1EBF 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.5 (Sans ExtraLight) 2.32 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.36 (Math TeX Gyre Regular) -U+1ec0 uni1EC0 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.5 (Sans ExtraLight) 2.32 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.36 (Math TeX Gyre Regular) -U+1ec1 uni1EC1 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.5 (Sans ExtraLight) 2.32 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.36 (Math TeX Gyre Regular) -U+1ec2 uni1EC2 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.5 (Sans ExtraLight) 2.32 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.36 (Math TeX Gyre Regular) -U+1ec3 uni1EC3 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.5 (Sans ExtraLight) 2.32 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.36 (Math TeX Gyre Regular) -U+1ec4 uni1EC4 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.5 (Sans ExtraLight) 2.32 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.36 (Math TeX Gyre Regular) -U+1ec5 uni1EC5 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.5 (Sans ExtraLight) 2.32 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.36 (Math TeX Gyre Regular) -U+1ec6 uni1EC6 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.26 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.36 (Math TeX Gyre Regular) -U+1ec7 uni1EC7 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.26 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.36 (Math TeX Gyre Regular) -U+1ec8 uni1EC8 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.5 (Sans ExtraLight) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) -U+1ec9 uni1EC9 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.5 (Sans ExtraLight) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) -U+1eca uni1ECA 2.2 -U+1ecb uni1ECB 2.2 -U+1ecc uni1ECC 2.2 -U+1ecd uni1ECD 2.2 -U+1ece uni1ECE 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.5 (Sans ExtraLight) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) -U+1ecf uni1ECF 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.5 (Sans ExtraLight) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) -U+1ed0 uni1ED0 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.5 (Sans ExtraLight) 2.32 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.36 (Math TeX Gyre Regular) -U+1ed1 uni1ED1 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.5 (Sans ExtraLight) 2.32 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.36 (Math TeX Gyre Regular) -U+1ed2 uni1ED2 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.5 (Sans ExtraLight) 2.32 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.36 (Math TeX Gyre Regular) -U+1ed3 uni1ED3 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.5 (Sans ExtraLight) 2.32 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.36 (Math TeX Gyre Regular) -U+1ed4 uni1ED4 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.5 (Sans ExtraLight) 2.32 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.36 (Math TeX Gyre Regular) -U+1ed5 uni1ED5 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.5 (Sans ExtraLight) 2.32 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.36 (Math TeX Gyre Regular) -U+1ed6 uni1ED6 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.5 (Sans ExtraLight) 2.32 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.36 (Math TeX Gyre Regular) -U+1ed7 uni1ED7 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.5 (Sans ExtraLight) 2.32 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.36 (Math TeX Gyre Regular) -U+1ed8 uni1ED8 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.26 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.36 (Math TeX Gyre Regular) -U+1ed9 uni1ED9 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.26 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.36 (Math TeX Gyre Regular) -U+1eda uni1EDA 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) 2.26 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.32 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.36 (Math TeX Gyre Regular) -U+1edb uni1EDB 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) 2.26 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.32 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.36 (Math TeX Gyre Regular) -U+1edc uni1EDC 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) 2.26 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.32 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.36 (Math TeX Gyre Regular) -U+1edd uni1EDD 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) 2.26 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.32 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.36 (Math TeX Gyre Regular) -U+1ede uni1EDE 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.5 (Sans ExtraLight) 2.32 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.36 (Math TeX Gyre Regular) -U+1edf uni1EDF 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.5 (Sans ExtraLight) 2.32 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.36 (Math TeX Gyre Regular) -U+1ee0 uni1EE0 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) 2.26 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.32 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.36 (Math TeX Gyre Regular) -U+1ee1 uni1EE1 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) 2.26 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.32 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.36 (Math TeX Gyre Regular) -U+1ee2 uni1EE2 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) 2.26 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.32 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.36 (Math TeX Gyre Regular) -U+1ee3 uni1EE3 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) 2.26 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.32 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.36 (Math TeX Gyre Regular) -U+1ee4 uni1EE4 2.2 -U+1ee5 uni1EE5 2.2 -U+1ee6 uni1EE6 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.5 (Sans ExtraLight) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) -U+1ee7 uni1EE7 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.5 (Sans ExtraLight) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) -U+1ee8 uni1EE8 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) 2.26 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.32 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.36 (Math TeX Gyre Regular) -U+1ee9 uni1EE9 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) 2.26 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.32 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.36 (Math TeX Gyre Regular) -U+1eea uni1EEA 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) 2.26 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.32 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.36 (Math TeX Gyre Regular) -U+1eeb uni1EEB 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) 2.26 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.32 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.36 (Math TeX Gyre Regular) -U+1eec uni1EEC 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.5 (Sans ExtraLight) 2.32 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.36 (Math TeX Gyre Regular) -U+1eed uni1EED 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.5 (Sans ExtraLight) 2.32 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.36 (Math TeX Gyre Regular) -U+1eee uni1EEE 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) 2.26 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.32 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.36 (Math TeX Gyre Regular) -U+1eef uni1EEF 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) 2.26 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.32 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.36 (Math TeX Gyre Regular) -U+1ef0 uni1EF0 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) 2.26 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.32 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.36 (Math TeX Gyre Regular) -U+1ef1 uni1EF1 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) 2.26 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.32 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.36 (Math TeX Gyre Regular) -U+1ef2 Ygrave 1.2 -U+1ef3 ygrave 1.2 -U+1ef4 uni1EF4 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.14 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) -U+1ef5 uni1EF5 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.14 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) -U+1ef6 uni1EF6 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.5 (Sans ExtraLight) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) -U+1ef7 uni1EF7 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.5 (Sans ExtraLight) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) -U+1ef8 uni1EF8 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.7 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) -U+1ef9 uni1EF9 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.7 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) -U+1efa uni1EFA 2.32 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) 2.33 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) -U+1efb uni1EFB 2.32 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) 2.33 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) -U+1f00 uni1F00 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.4 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.5 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+1f01 uni1F01 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.4 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.5 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+1f02 uni1F02 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.4 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.5 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+1f03 uni1F03 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.4 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.5 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+1f04 uni1F04 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.4 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.5 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+1f05 uni1F05 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.4 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.5 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+1f06 uni1F06 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.4 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.5 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+1f07 uni1F07 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.4 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.5 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+1f08 uni1F08 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.4 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.5 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+1f09 uni1F09 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.4 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.5 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+1f0a uni1F0A 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.4 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.5 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+1f0b uni1F0B 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.4 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.5 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+1f0c uni1F0C 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.4 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.5 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+1f0d uni1F0D 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.4 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.5 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+1f0e uni1F0E 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.4 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.5 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+1f0f uni1F0F 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.4 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.5 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+1f10 uni1F10 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.4 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.5 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+1f11 uni1F11 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.4 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.5 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+1f12 uni1F12 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.4 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.5 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+1f13 uni1F13 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.4 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.5 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+1f14 uni1F14 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.4 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.5 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+1f15 uni1F15 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.4 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.5 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+1f18 uni1F18 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.4 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.5 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+1f19 uni1F19 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.4 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.5 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+1f1a uni1F1A 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.4 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.5 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+1f1b uni1F1B 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.4 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.5 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+1f1c uni1F1C 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.4 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.5 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+1f1d uni1F1D 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.4 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.5 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+1f20 uni1F20 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.4 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.5 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+1f21 uni1F21 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.4 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.5 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+1f22 uni1F22 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.4 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.5 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+1f23 uni1F23 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.4 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.5 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+1f24 uni1F24 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.4 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.5 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+1f25 uni1F25 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.4 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.5 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+1f26 uni1F26 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.4 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.5 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+1f27 uni1F27 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.4 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.5 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+1f28 uni1F28 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.4 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.5 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+1f29 uni1F29 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.4 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.5 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+1f2a uni1F2A 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.4 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.5 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+1f2b uni1F2B 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.4 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.5 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+1f2c uni1F2C 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.4 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.5 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+1f2d uni1F2D 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.4 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.5 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+1f2e uni1F2E 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.4 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.5 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+1f2f uni1F2F 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.4 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.5 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+1f30 uni1F30 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.4 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.5 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+1f31 uni1F31 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.4 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.5 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+1f32 uni1F32 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.4 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.5 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+1f33 uni1F33 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.4 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.5 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+1f34 uni1F34 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.4 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.5 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+1f35 uni1F35 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.4 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.5 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+1f36 uni1F36 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.4 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.5 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+1f37 uni1F37 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.4 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.5 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+1f38 uni1F38 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.4 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.5 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+1f39 uni1F39 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.4 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.5 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+1f3a uni1F3A 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.4 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.5 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+1f3b uni1F3B 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.4 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.5 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+1f3c uni1F3C 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.4 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.5 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+1f3d uni1F3D 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.4 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.5 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+1f3e uni1F3E 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.4 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.5 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+1f3f uni1F3F 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.4 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.5 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+1f40 uni1F40 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.4 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.5 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+1f41 uni1F41 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.4 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.5 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+1f42 uni1F42 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.4 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.5 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+1f43 uni1F43 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.4 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.5 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+1f44 uni1F44 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.4 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.5 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+1f45 uni1F45 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.4 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.5 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+1f48 uni1F48 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.4 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.5 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+1f49 uni1F49 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.4 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.5 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+1f4a uni1F4A 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.4 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.5 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+1f4b uni1F4B 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.4 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.5 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+1f4c uni1F4C 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.4 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.5 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+1f4d uni1F4D 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.4 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.5 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+1f50 uni1F50 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.4 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.5 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+1f51 uni1F51 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.4 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.5 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+1f52 uni1F52 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.4 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.5 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+1f53 uni1F53 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.4 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.5 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+1f54 uni1F54 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.4 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.5 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+1f55 uni1F55 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.4 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.5 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+1f56 uni1F56 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.4 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.5 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+1f57 uni1F57 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.4 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.5 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+1f59 uni1F59 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.4 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.5 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+1f5b uni1F5B 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.4 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.5 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+1f5d uni1F5D 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.4 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.5 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+1f5f uni1F5F 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.4 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.5 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+1f60 uni1F60 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.4 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.5 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+1f61 uni1F61 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.4 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.5 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+1f62 uni1F62 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.4 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.5 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+1f63 uni1F63 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.4 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.5 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+1f64 uni1F64 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.4 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.5 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+1f65 uni1F65 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.4 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.5 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+1f66 uni1F66 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.4 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.5 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+1f67 uni1F67 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.4 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.5 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+1f68 uni1F68 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.4 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.5 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+1f69 uni1F69 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.4 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.5 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+1f6a uni1F6A 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.4 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.5 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+1f6b uni1F6B 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.4 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.5 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+1f6c uni1F6C 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.4 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.5 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+1f6d uni1F6D 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.4 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.5 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+1f6e uni1F6E 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.4 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.5 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+1f6f uni1F6F 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.4 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.5 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+1f70 uni1F70 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.4 (Sans ExtraLight, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.23 (Serif Italic Condensed) -U+1f71 uni1F71 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.4 (Sans ExtraLight, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.23 (Serif Italic Condensed) -U+1f72 uni1F72 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.4 (Sans ExtraLight, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.23 (Serif Italic Condensed) -U+1f73 uni1F73 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.4 (Sans ExtraLight, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.23 (Serif Italic Condensed) -U+1f74 uni1F74 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.4 (Sans ExtraLight, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.23 (Serif Italic Condensed) -U+1f75 uni1F75 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.4 (Sans ExtraLight, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.23 (Serif Italic Condensed) -U+1f76 uni1F76 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.4 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.5 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+1f77 uni1F77 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.4 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.5 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+1f78 uni1F78 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.4 (Sans ExtraLight, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.23 (Serif Italic Condensed) -U+1f79 uni1F79 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.4 (Sans ExtraLight, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.23 (Serif Italic Condensed) -U+1f7a uni1F7A 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.4 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.5 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+1f7b uni1F7B 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.4 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.5 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+1f7c uni1F7C 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.4 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.5 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+1f7d uni1F7D 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.4 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.5 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+1f80 uni1F80 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.4 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.5 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+1f81 uni1F81 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.4 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.5 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+1f82 uni1F82 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.4 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.5 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+1f83 uni1F83 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.4 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.5 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+1f84 uni1F84 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.4 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.5 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+1f85 uni1F85 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.4 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.5 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+1f86 uni1F86 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.4 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.5 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+1f87 uni1F87 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.4 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.5 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+1f88 uni1F88 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.4 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.5 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+1f89 uni1F89 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.4 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.5 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+1f8a uni1F8A 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.4 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.5 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+1f8b uni1F8B 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.4 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.5 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+1f8c uni1F8C 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.4 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.5 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+1f8d uni1F8D 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.4 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.5 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+1f8e uni1F8E 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.4 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.5 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+1f8f uni1F8F 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.4 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.5 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+1f90 uni1F90 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.4 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.5 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+1f91 uni1F91 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.4 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.5 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+1f92 uni1F92 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.4 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.5 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+1f93 uni1F93 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.4 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.5 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+1f94 uni1F94 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.4 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.5 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+1f95 uni1F95 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.4 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.5 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+1f96 uni1F96 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.4 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.5 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+1f97 uni1F97 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.4 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.5 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+1f98 uni1F98 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.4 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.5 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+1f99 uni1F99 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.4 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.5 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+1f9a uni1F9A 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.4 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.5 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+1f9b uni1F9B 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.4 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.5 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+1f9c uni1F9C 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.4 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.5 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+1f9d uni1F9D 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.4 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.5 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+1f9e uni1F9E 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.4 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.5 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+1f9f uni1F9F 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.4 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.5 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+1fa0 uni1FA0 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.4 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.5 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+1fa1 uni1FA1 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.4 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.5 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+1fa2 uni1FA2 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.4 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.5 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+1fa3 uni1FA3 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.4 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.5 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+1fa4 uni1FA4 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.4 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.5 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+1fa5 uni1FA5 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.4 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.5 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+1fa6 uni1FA6 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.4 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.5 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+1fa7 uni1FA7 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.4 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.5 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+1fa8 uni1FA8 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.4 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.5 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+1fa9 uni1FA9 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.4 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.5 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+1faa uni1FAA 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.4 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.5 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+1fab uni1FAB 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.4 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.5 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+1fac uni1FAC 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.4 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.5 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+1fad uni1FAD 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.4 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.5 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+1fae uni1FAE 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.4 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.5 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+1faf uni1FAF 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.4 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.5 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+1fb0 uni1FB0 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.4 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.5 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+1fb1 uni1FB1 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.4 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.5 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+1fb2 uni1FB2 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.4 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.5 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+1fb3 uni1FB3 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.4 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.5 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+1fb4 uni1FB4 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.4 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.5 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+1fb6 uni1FB6 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.4 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.5 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+1fb7 uni1FB7 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.4 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.5 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+1fb8 uni1FB8 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.4 (Sans ExtraLight, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.23 (Serif Italic Condensed) -U+1fb9 uni1FB9 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.4 (Sans ExtraLight, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.23 (Serif Italic Condensed) -U+1fba uni1FBA 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.4 (Sans ExtraLight, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.23 (Serif Italic Condensed) -U+1fbb uni1FBB 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.4 (Sans ExtraLight, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.23 (Serif Italic Condensed) -U+1fbc uni1FBC 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.4 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.5 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+1fbd uni1FBD 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.4 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.5 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+1fbe uni1FBE 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.4 (Sans ExtraLight, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.23 (Serif Italic Condensed) -U+1fbf uni1FBF 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.4 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.5 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+1fc0 uni1FC0 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.4 (Sans ExtraLight, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.23 (Serif Italic Condensed) -U+1fc1 uni1FC1 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.4 (Sans ExtraLight, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.23 (Serif Italic Condensed) -U+1fc2 uni1FC2 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.4 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.5 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+1fc3 uni1FC3 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.4 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.5 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+1fc4 uni1FC4 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.4 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.5 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+1fc6 uni1FC6 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.4 (Sans ExtraLight, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.23 (Serif Italic Condensed) -U+1fc7 uni1FC7 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.4 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.5 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+1fc8 uni1FC8 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.4 (Sans ExtraLight, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.23 (Serif Italic Condensed) -U+1fc9 uni1FC9 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.4 (Sans ExtraLight, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.23 (Serif Italic Condensed) -U+1fca uni1FCA 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.4 (Sans ExtraLight, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.23 (Serif Italic Condensed) -U+1fcb uni1FCB 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.4 (Sans ExtraLight, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.23 (Serif Italic Condensed) -U+1fcc uni1FCC 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.4 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.10 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+1fcd uni1FCD 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.4 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.5 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+1fce uni1FCE 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.4 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.5 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+1fcf uni1FCF 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.4 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.5 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+1fd0 uni1FD0 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.4 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.5 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+1fd1 uni1FD1 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.4 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.5 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+1fd2 uni1FD2 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.4 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.5 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+1fd3 uni1FD3 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.4 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.5 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+1fd6 uni1FD6 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.4 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.5 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+1fd7 uni1FD7 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.4 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.5 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+1fd8 uni1FD8 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.4 (Sans ExtraLight, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.23 (Serif Italic Condensed) -U+1fd9 uni1FD9 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.4 (Sans ExtraLight, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.23 (Serif Italic Condensed) -U+1fda uni1FDA 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.4 (Sans ExtraLight, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.23 (Serif Italic Condensed) -U+1fdb uni1FDB 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.4 (Sans ExtraLight, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.23 (Serif Italic Condensed) -U+1fdd uni1FDD 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.4 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.5 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+1fde uni1FDE 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.4 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.5 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+1fdf uni1FDF 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.4 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.5 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+1fe0 uni1FE0 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.4 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.5 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+1fe1 uni1FE1 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.4 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.5 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+1fe2 uni1FE2 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.4 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.5 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+1fe3 uni1FE3 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.4 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.5 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+1fe4 uni1FE4 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.4 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.5 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+1fe5 uni1FE5 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.4 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.5 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+1fe6 uni1FE6 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.4 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.5 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+1fe7 uni1FE7 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.4 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.5 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+1fe8 uni1FE8 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.4 (Sans ExtraLight, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.23 (Serif Italic Condensed) -U+1fe9 uni1FE9 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.4 (Sans ExtraLight, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.23 (Serif Italic Condensed) -U+1fea uni1FEA 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.4 (Sans ExtraLight, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.23 (Serif Italic Condensed) -U+1feb uni1FEB 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.4 (Sans ExtraLight, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.23 (Serif Italic Condensed) -U+1fec uni1FEC 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.4 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.5 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+1fed uni1FED 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.4 (Sans ExtraLight, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.23 (Serif Italic Condensed) -U+1fee uni1FEE 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.4 (Sans ExtraLight, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.23 (Serif Italic Condensed) -U+1fef uni1FEF 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.4 (Sans ExtraLight, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.23 (Serif Italic Condensed) -U+1ff2 uni1FF2 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.4 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.5 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+1ff3 uni1FF3 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.4 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.5 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+1ff4 uni1FF4 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.4 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.5 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+1ff6 uni1FF6 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.4 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.5 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+1ff7 uni1FF7 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.4 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.5 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+1ff8 uni1FF8 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.4 (Sans ExtraLight, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.23 (Serif Italic Condensed) -U+1ff9 uni1FF9 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.4 (Sans ExtraLight, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.23 (Serif Italic Condensed) -U+1ffa uni1FFA 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.4 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.5 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+1ffb uni1FFB 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.4 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.10 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+1ffc uni1FFC 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.4 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.5 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+1ffd uni1FFD 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.4 (Sans ExtraLight, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.23 (Serif Italic Condensed) -U+1ffe uni1FFE 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.4 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.5 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+2000 uni2000 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.5 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) -U+2001 uni2001 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.5 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) -U+2002 uni2002 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.5 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) -U+2003 uni2003 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.5 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) -U+2004 uni2004 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.5 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) -U+2005 uni2005 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.5 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) -U+2006 uni2006 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.5 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) -U+2007 uni2007 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.5 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) -U+2008 uni2008 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.5 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) -U+2009 uni2009 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.5 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) -U+200a uni200A 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.5 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) -U+200b uni200B 2.7 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Italic) 2.8 (Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) -U+200c uni200C 2.7 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Italic) 2.8 (Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) -U+200d uni200D 2.7 (Sans, Sans Bold, Sans Bold Oblique, Sans ExtraLight, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Italic) 2.8 (Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) -U+200e uni200E 2.7 (Sans, Sans Bold, Sans Bold Oblique, Sans ExtraLight, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Italic) 2.8 (Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic) 2.23 (Serif Italic Condensed) -U+200f uni200F 2.7 (Sans, Sans Bold, Sans Bold Oblique, Sans ExtraLight, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Italic) 2.8 (Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic) 2.23 (Serif Italic Condensed) -U+2010 uni2010 1.5 -U+2011 uni2011 1.5 -U+2012 figuredash 1.5 -U+2013 endash original -U+2014 emdash original -U+2015 uni2015 1.5 -U+2016 uni2016 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) 2.26 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) 2.34 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.36 (Math TeX Gyre Regular) -U+2017 underscoredbl 2.3 -U+2018 quoteleft original -U+2019 quoteright original -U+201a quotesinglbase original -U+201b quotereversed 2.3 -U+201c quotedblleft original -U+201d quotedblright original -U+201e quotedblbase original -U+201f uni201F 2.1 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.3 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.4 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+2020 dagger original -U+2021 daggerdbl original -U+2022 bullet original -U+2023 uni2023 2.2 -U+2024 onedotenleader 2.1 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.4 (Sans ExtraLight) 2.9 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+2025 twodotenleader 2.1 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.4 (Sans ExtraLight) 2.9 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+2026 ellipsis original -U+2027 uni2027 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+2028 uni2028 2.32 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) -U+2029 uni2029 2.32 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) -U+202a uni202A 2.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+202b uni202B 2.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+202c uni202C 2.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+202d uni202D 2.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+202e uni202E 2.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+202f uni202F 2.11 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.13 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) -U+2030 perthousand original -U+2031 uni2031 2.1 -U+2032 minute 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.26 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Italic, Serif Italic Condensed) 2.28 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.31 (Serif Condensed Italic) 2.36 (Math TeX Gyre Regular) -U+2033 second 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.26 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Italic, Serif Italic Condensed) 2.28 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.31 (Serif Condensed Italic) 2.36 (Math TeX Gyre Regular) -U+2034 uni2034 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.26 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Italic, Serif Italic Condensed) 2.28 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.31 (Serif Condensed Italic) 2.36 (Math TeX Gyre Regular) -U+2035 uni2035 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.26 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Italic, Serif Italic Condensed) 2.28 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.31 (Serif Condensed Italic) 2.36 (Math TeX Gyre Regular) -U+2036 uni2036 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.26 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Italic, Serif Italic Condensed) 2.28 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.31 (Serif Condensed Italic) 2.36 (Math TeX Gyre Regular) -U+2037 uni2037 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.26 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Italic, Serif Italic Condensed) 2.28 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.31 (Serif Condensed Italic) 2.36 (Math TeX Gyre Regular) -U+2038 uni2038 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.26 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) -U+2039 guilsinglleft original -U+203a guilsinglright original -U+203b uni203B 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) 2.36 (Math TeX Gyre Regular) -U+203c exclamdbl 2.0 -U+203d uni203D 2.1 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.4 (Sans ExtraLight) 2.11 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.14 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) -U+203e uni203E 2.3 -U+203f uni203F 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) 2.35 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) -U+2040 uni2040 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) -U+2041 uni2041 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+2042 uni2042 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) 2.26 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) -U+2043 uni2043 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) -U+2044 fraction 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) 2.27 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) 2.36 (Math TeX Gyre Regular) -U+2045 uni2045 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) 2.13 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.26 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) -U+2046 uni2046 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) 2.13 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.26 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) -U+2047 uni2047 2.0 -U+2048 uni2048 2.0 -U+2049 uni2049 2.0 -U+204a uni204A 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+204b uni204B 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) 2.26 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) 2.33 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) -U+204c uni204C 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) 2.26 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) -U+204d uni204D 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) 2.26 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) -U+204e uni204E 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) 2.26 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) -U+204f uni204F 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) 2.26 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) -U+2050 uni2050 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) -U+2051 uni2051 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) 2.26 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) -U+2052 uni2052 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) 2.26 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) 2.36 (Math TeX Gyre Regular) -U+2053 uni2053 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) 2.26 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) -U+2054 uni2054 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) -U+2055 uni2055 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+2056 uni2056 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+2057 uni2057 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.26 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) 2.36 (Math TeX Gyre Regular) -U+2058 uni2058 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+2059 uni2059 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+205a uni205A 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+205b uni205B 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+205c uni205C 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+205d uni205D 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+205e uni205E 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+205f uni205F 2.14 -U+2060 uni2060 2.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) -U+2061 uni2061 2.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) -U+2062 uni2062 2.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) -U+2063 uni2063 2.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) -U+2064 uni2064 2.26 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) 2.36 (Math TeX Gyre Regular) -U+206a uni206A 2.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+206b uni206B 2.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+206c uni206C 2.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+206d uni206D 2.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+206e uni206E 2.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+206f uni206F 2.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+2070 uni2070 2.2 -U+2071 uni2071 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) 2.17 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Italic) 2.18 (Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic) 2.23 (Serif Italic Condensed) -U+2074 uni2074 2.2 -U+2075 uni2075 2.2 -U+2076 uni2076 2.2 -U+2077 uni2077 2.2 -U+2078 uni2078 2.2 -U+2079 uni2079 2.2 -U+207a uni207A 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.17 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Italic) 2.18 (Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic) 2.23 (Serif Italic Condensed) -U+207b uni207B 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.17 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Italic) 2.18 (Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic) 2.23 (Serif Italic Condensed) -U+207c uni207C 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.17 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Italic) 2.18 (Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic) 2.23 (Serif Italic Condensed) -U+207d uni207D 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.17 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Italic) 2.18 (Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic) 2.23 (Serif Italic Condensed) -U+207e uni207E 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.17 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Italic) 2.18 (Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic) 2.23 (Serif Italic Condensed) -U+207f uni207F 1.14 -U+2080 uni2080 2.4 -U+2081 uni2081 2.4 -U+2082 uni2082 2.4 -U+2083 uni2083 2.4 -U+2084 uni2084 2.4 -U+2085 uni2085 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+2086 uni2086 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+2087 uni2087 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+2088 uni2088 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+2089 uni2089 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+208a uni208A 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.17 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Italic) 2.18 (Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic) 2.23 (Serif Italic Condensed) -U+208b uni208B 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.17 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Italic) 2.18 (Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic) 2.23 (Serif Italic Condensed) -U+208c uni208C 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.17 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Italic) 2.18 (Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic) 2.23 (Serif Italic Condensed) -U+208d uni208D 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.17 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Italic) 2.18 (Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic) 2.23 (Serif Italic Condensed) -U+208e uni208E 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.17 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Italic) 2.18 (Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic) 2.23 (Serif Italic Condensed) -U+2090 uni2090 2.10 (Sans, Sans Bold, Sans Bold Oblique, Sans Oblique) 2.11 (Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique) 2.17 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Italic) 2.18 (Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic) 2.23 (Serif Italic Condensed) -U+2091 uni2091 2.10 (Sans, Sans Bold, Sans Bold Oblique, Sans Oblique) 2.11 (Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique) 2.17 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Italic) 2.18 (Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic) 2.23 (Serif Italic Condensed) -U+2092 uni2092 2.10 (Sans, Sans Bold, Sans Bold Oblique, Sans Oblique) 2.11 (Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique) 2.17 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Italic) 2.18 (Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic) 2.23 (Serif Italic Condensed) -U+2093 uni2093 2.10 (Sans, Sans Bold, Sans Bold Oblique, Sans Oblique) 2.11 (Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique) 2.17 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Italic) 2.18 (Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic) 2.23 (Serif Italic Condensed) -U+2094 uni2094 2.10 (Sans, Sans Bold, Sans Bold Oblique, Sans Oblique) 2.11 (Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique) 2.17 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Italic) 2.18 (Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic) 2.23 (Serif Italic Condensed) -U+2095 uni2095 2.33 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) -U+2096 uni2096 2.33 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) -U+2097 uni2097 2.33 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) -U+2098 uni2098 2.33 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) -U+2099 uni2099 2.33 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) -U+209a uni209A 2.33 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) -U+209b uni209B 2.33 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) -U+209c uni209C 2.33 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) -U+20a0 uni20A0 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.26 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) -U+20a1 colonmonetary 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.26 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.36 (Math TeX Gyre Regular) -U+20a2 uni20A2 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.26 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) -U+20a3 franc 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.26 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) -U+20a4 lira 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.26 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.36 (Math TeX Gyre Regular) -U+20a5 uni20A5 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.26 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) -U+20a6 uni20A6 2.3 -U+20a7 peseta 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.26 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) -U+20a8 uni20A8 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.26 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) -U+20a9 uni20A9 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.26 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.36 (Math TeX Gyre Regular) -U+20aa uni20AA 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.26 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) -U+20ab dong 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) 2.26 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.36 (Math TeX Gyre Regular) -U+20ac Euro original -U+20ad uni20AD 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.26 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) -U+20ae uni20AE 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.26 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) -U+20af uni20AF 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.26 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) -U+20b0 uni20B0 2.10 (Sans, Sans Bold, Sans Bold Oblique, Sans Oblique) 2.11 (Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique) 2.26 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) -U+20b1 uni20B1 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.14 (Sans ExtraLight, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) -U+20b2 uni20B2 2.10 (Sans, Sans Bold, Sans Bold Oblique, Sans Oblique) 2.11 (Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique) 2.26 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.36 (Math TeX Gyre Regular) -U+20b3 uni20B3 2.10 (Sans, Sans Bold, Sans Bold Oblique, Sans Oblique) 2.11 (Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique) 2.26 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) -U+20b4 uni20B4 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+20b5 uni20B5 2.2 -U+20b8 uni20B8 2.32 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique) 2.34 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) -U+20b9 uni20B9 2.32 -U+20ba uni20BA 2.34 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.35 (Sans ExtraLight, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.36 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) -U+20bd uni20BD 2.35 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.36 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) -U+20d0 uni20D0 2.10 (Sans, Sans Bold, Sans Bold Oblique, Sans Oblique) 2.11 (Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique) 2.36 (Math TeX Gyre Regular) -U+20d1 uni20D1 2.10 (Sans, Sans Bold, Sans Bold Oblique, Sans Oblique) 2.11 (Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique) 2.36 (Math TeX Gyre Regular) -U+20d2 uni20D2 2.36 (Math TeX Gyre Regular) -U+20d3 uni20D3 2.36 (Math TeX Gyre Regular) -U+20d4 uni20D4 2.36 (Math TeX Gyre Regular) -U+20d5 uni20D5 2.36 (Math TeX Gyre Regular) -U+20d6 uni20D6 2.8 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.36 (Math TeX Gyre Regular) -U+20d7 uni20D7 2.8 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.36 (Math TeX Gyre Regular) -U+20d8 uni20D8 2.36 (Math TeX Gyre Regular) -U+20db uni20DB 2.23 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.36 (Math TeX Gyre Regular) -U+20dc uni20DC 2.23 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.36 (Math TeX Gyre Regular) -U+20dd uni20DD 2.36 (Math TeX Gyre Regular) -U+20de uni20DE 2.36 (Math TeX Gyre Regular) -U+20df uni20DF 2.36 (Math TeX Gyre Regular) -U+20e1 uni20E1 2.23 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.36 (Math TeX Gyre Regular) -U+20e4 uni20E4 2.36 (Math TeX Gyre Regular) -U+20e5 uni20E5 2.36 (Math TeX Gyre Regular) -U+20e6 uni20E6 2.36 (Math TeX Gyre Regular) -U+20e8 uni20E8 2.36 (Math TeX Gyre Regular) -U+20e9 uni20E9 2.36 (Math TeX Gyre Regular) -U+20ea uni20EA 2.36 (Math TeX Gyre Regular) -U+20eb uni20EB 2.36 (Math TeX Gyre Regular) -U+20ec uni20EC 2.36 (Math TeX Gyre Regular) -U+20ed uni20ED 2.36 (Math TeX Gyre Regular) -U+20ee uni20EE 2.36 (Math TeX Gyre Regular) -U+20ef uni20EF 2.36 (Math TeX Gyre Regular) -U+20f0 uni20F0 2.36 (Math TeX Gyre Regular) -U+2100 uni2100 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+2101 uni2101 2.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+2102 uni2102 2.10 (Sans, Sans Bold, Sans Bold Oblique, Sans Oblique) 2.11 (Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique) 2.16 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.22 (Serif, Serif Condensed) 2.36 (Math TeX Gyre Regular) -U+2103 uni2103 2.2 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.4 (Sans ExtraLight) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) -U+2104 uni2104 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+2105 uni2105 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.26 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) -U+2106 uni2106 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+2107 uni2107 2.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.36 (Math TeX Gyre Regular) -U+2108 uni2108 2.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+2109 uni2109 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) -U+210a uni210A 2.36 (Math TeX Gyre Regular) -U+210b uni210B 2.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.36 (Math TeX Gyre Regular) -U+210c uni210C 2.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.36 (Math TeX Gyre Regular) -U+210d uni210D 2.10 (Sans, Sans Bold, Sans Bold Oblique, Sans Oblique) 2.11 (Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique) 2.22 (Serif, Serif Condensed) 2.26 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.36 (Math TeX Gyre Regular) -U+210e uni210E 2.5 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique) 2.23 (Serif Italic Condensed) 2.26 (Sans ExtraLight) 2.36 (Math TeX Gyre Regular) -U+210f uni210F 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.26 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.28 (Sans ExtraLight, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) 2.36 (Math TeX Gyre Regular) -U+2110 uni2110 2.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.36 (Math TeX Gyre Regular) -U+2111 Ifraktur 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.36 (Math TeX Gyre Regular) -U+2112 uni2112 2.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.36 (Math TeX Gyre Regular) -U+2113 uni2113 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.36 (Math TeX Gyre Regular) -U+2114 uni2114 2.12 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+2115 uni2115 2.10 (Sans, Sans Bold, Sans Bold Oblique, Sans Oblique) 2.11 (Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique) 2.22 (Serif, Serif Condensed) 2.26 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.36 (Math TeX Gyre Regular) -U+2116 uni2116 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.4 (Sans ExtraLight) 2.7 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) -U+2117 uni2117 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) 2.26 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.36 (Math TeX Gyre Regular) -U+2118 weierstrass 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.36 (Math TeX Gyre Regular) -U+2119 uni2119 2.10 (Sans, Sans Bold, Sans Bold Oblique, Sans Oblique) 2.11 (Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique) 2.22 (Serif, Serif Condensed) 2.26 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.36 (Math TeX Gyre Regular) -U+211a uni211A 2.10 (Sans, Sans Bold, Sans Bold Oblique, Sans Oblique) 2.11 (Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique) 2.22 (Serif, Serif Condensed) 2.26 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.36 (Math TeX Gyre Regular) -U+211b uni211B 2.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.36 (Math TeX Gyre Regular) -U+211c Rfraktur 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.36 (Math TeX Gyre Regular) -U+211d uni211D 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.22 (Serif, Serif Condensed) 2.26 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.36 (Math TeX Gyre Regular) -U+211e prescription 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.36 (Math TeX Gyre Regular) -U+211f uni211F 2.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+2120 uni2120 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.36 (Math TeX Gyre Regular) -U+2121 uni2121 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+2122 trademark original -U+2123 uni2123 2.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+2124 uni2124 2.10 (Sans, Sans Bold, Sans Bold Oblique, Sans Oblique) 2.11 (Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique) 2.22 (Serif, Serif Condensed) 2.26 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.36 (Math TeX Gyre Regular) -U+2125 uni2125 2.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+2126 uni2126 2.2 -U+2127 uni2127 2.2 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.4 (Sans ExtraLight) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) -U+2128 uni2128 2.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.36 (Math TeX Gyre Regular) -U+2129 uni2129 2.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+212a uni212A 2.2 -U+212b uni212B 2.2 -U+212c uni212C 2.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.36 (Math TeX Gyre Regular) -U+212d uni212D 2.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.36 (Math TeX Gyre Regular) -U+212e estimated 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) 2.26 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.36 (Math TeX Gyre Regular) -U+212f uni212F 2.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.36 (Math TeX Gyre Regular) -U+2130 uni2130 2.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.36 (Math TeX Gyre Regular) -U+2131 uni2131 2.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.36 (Math TeX Gyre Regular) -U+2132 uni2132 2.2 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.10 (Sans ExtraLight) 2.34 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) -U+2133 uni2133 2.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.36 (Math TeX Gyre Regular) -U+2134 uni2134 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) 2.36 (Math TeX Gyre Regular) -U+2135 aleph 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.36 (Math TeX Gyre Regular) -U+2136 uni2136 2.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.36 (Math TeX Gyre Regular) -U+2137 uni2137 2.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.36 (Math TeX Gyre Regular) -U+2138 uni2138 2.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.36 (Math TeX Gyre Regular) -U+2139 uni2139 2.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+213a uni213A 2.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+213b uni213B 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+213c uni213C 2.10 (Sans, Sans Bold, Sans Bold Oblique, Sans Oblique) 2.11 (Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique) 2.22 (Serif, Serif Condensed) 2.36 (Math TeX Gyre Regular) -U+213d uni213D 2.10 (Sans, Sans Bold, Sans Bold Oblique, Sans Oblique) 2.11 (Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique) 2.22 (Serif, Serif Condensed) 2.36 (Math TeX Gyre Regular) -U+213e uni213E 2.10 (Sans, Sans Bold, Sans Bold Oblique, Sans Oblique) 2.11 (Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique) 2.22 (Serif, Serif Condensed) 2.36 (Math TeX Gyre Regular) -U+213f uni213F 2.10 (Sans, Sans Bold, Sans Bold Oblique, Sans Oblique) 2.11 (Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique) 2.22 (Serif, Serif Condensed) 2.36 (Math TeX Gyre Regular) -U+2140 uni2140 2.10 (Sans, Sans Bold, Sans Bold Oblique, Sans Oblique) 2.11 (Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique) 2.22 (Serif, Serif Condensed) 2.36 (Math TeX Gyre Regular) -U+2141 uni2141 2.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.34 (Sans ExtraLight) -U+2142 uni2142 2.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.34 (Sans ExtraLight) -U+2143 uni2143 2.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.34 (Sans ExtraLight) -U+2144 uni2144 2.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.34 (Sans ExtraLight) -U+2145 uni2145 2.10 (Sans, Sans Bold, Sans Bold Oblique, Sans Oblique) 2.11 (Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique) 2.22 (Serif, Serif Condensed) 2.36 (Math TeX Gyre Regular) -U+2146 uni2146 2.10 (Sans, Sans Bold, Sans Bold Oblique, Sans Oblique) 2.11 (Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique) 2.22 (Serif, Serif Condensed) 2.36 (Math TeX Gyre Regular) -U+2147 uni2147 2.10 (Sans, Sans Bold, Sans Bold Oblique, Sans Oblique) 2.11 (Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique) 2.22 (Serif, Serif Condensed) 2.36 (Math TeX Gyre Regular) -U+2148 uni2148 2.10 (Sans, Sans Bold, Sans Bold Oblique, Sans Oblique) 2.11 (Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique) 2.22 (Serif, Serif Condensed) 2.34 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.36 (Math TeX Gyre Regular) -U+2149 uni2149 2.10 (Sans, Sans Bold, Sans Bold Oblique, Sans Oblique) 2.11 (Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique) 2.22 (Serif, Serif Condensed) 2.36 (Math TeX Gyre Regular) -U+214b uni214B 2.2 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.10 (Sans ExtraLight) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+214e uni214E 2.12 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.34 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) -U+2150 uni2150 2.32 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.35 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) -U+2151 uni2151 2.32 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.35 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) -U+2152 uni2152 2.32 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) -U+2153 onethird 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) 2.5 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.6 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+2154 twothirds 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) 2.5 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.6 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+2155 uni2155 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.5 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.6 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+2156 uni2156 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.5 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.6 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+2157 uni2157 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.5 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.6 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+2158 uni2158 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.5 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.6 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+2159 uni2159 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.5 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.6 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+215a uni215A 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.5 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.6 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+215b oneeighth 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.5 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.6 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+215c threeeighths 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.5 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.6 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+215d fiveeighths 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.5 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.6 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+215e seveneighths 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.5 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.6 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+215f uni215F 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) 2.5 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.6 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+2160 uni2160 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.4 (Sans ExtraLight) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+2161 uni2161 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.4 (Sans ExtraLight) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+2162 uni2162 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.4 (Sans ExtraLight) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+2163 uni2163 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.4 (Sans ExtraLight) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+2164 uni2164 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.4 (Sans ExtraLight) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+2165 uni2165 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.4 (Sans ExtraLight) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+2166 uni2166 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.4 (Sans ExtraLight) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+2167 uni2167 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.4 (Sans ExtraLight) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+2168 uni2168 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.4 (Sans ExtraLight) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+2169 uni2169 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.4 (Sans ExtraLight) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+216a uni216A 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.4 (Sans ExtraLight) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+216b uni216B 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.4 (Sans ExtraLight) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+216c uni216C 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.4 (Sans ExtraLight) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+216d uni216D 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.4 (Sans ExtraLight) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+216e uni216E 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.4 (Sans ExtraLight) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+216f uni216F 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.4 (Sans ExtraLight) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+2170 uni2170 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.4 (Sans ExtraLight) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+2171 uni2171 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.4 (Sans ExtraLight) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+2172 uni2172 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.4 (Sans ExtraLight) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+2173 uni2173 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.4 (Sans ExtraLight) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+2174 uni2174 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.4 (Sans ExtraLight) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+2175 uni2175 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.4 (Sans ExtraLight) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+2176 uni2176 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.4 (Sans ExtraLight) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+2177 uni2177 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.4 (Sans ExtraLight) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+2178 uni2178 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.4 (Sans ExtraLight) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+2179 uni2179 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.4 (Sans ExtraLight) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+217a uni217A 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.4 (Sans ExtraLight) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+217b uni217B 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.4 (Sans ExtraLight) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+217c uni217C 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.4 (Sans ExtraLight) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+217d uni217D 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.4 (Sans ExtraLight) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+217e uni217E 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.4 (Sans ExtraLight) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+217f uni217F 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.4 (Sans ExtraLight) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+2180 uni2180 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.10 (Sans ExtraLight) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+2181 uni2181 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.32 (Sans ExtraLight) -U+2182 uni2182 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.32 (Sans ExtraLight) -U+2183 uni2183 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.4 (Sans ExtraLight) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+2184 uni2184 2.9 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.10 (Sans ExtraLight) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+2185 uni2185 2.32 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) -U+2189 uni2189 2.32 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.35 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) -U+2190 arrowleft 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) 2.7 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.9 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) -U+2191 arrowup 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) 2.7 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.9 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) -U+2192 arrowright 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) 2.7 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.9 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) -U+2193 arrowdown 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) 2.7 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.9 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) -U+2194 arrowboth 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) 2.9 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) -U+2195 arrowupdn 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) 2.9 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) -U+2196 uni2196 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) 2.9 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) -U+2197 uni2197 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) 2.9 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) -U+2198 uni2198 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) 2.9 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) -U+2199 uni2199 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) 2.9 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) -U+219a uni219A 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.9 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) -U+219b uni219B 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.9 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) -U+219c uni219C 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.9 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+219d uni219D 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.9 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+219e uni219E 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.9 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) -U+219f uni219F 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.9 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) -U+21a0 uni21A0 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.9 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) -U+21a1 uni21A1 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.9 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) -U+21a2 uni21A2 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.9 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) -U+21a3 uni21A3 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.9 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) -U+21a4 uni21A4 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.9 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) -U+21a5 uni21A5 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.9 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) -U+21a6 uni21A6 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.9 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) -U+21a7 uni21A7 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.9 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) -U+21a8 arrowupdnbse 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.9 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+21a9 uni21A9 2.7 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.9 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) -U+21aa uni21AA 2.7 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.9 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) -U+21ab uni21AB 2.7 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.9 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) -U+21ac uni21AC 2.7 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.9 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) -U+21ad uni21AD 2.7 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.9 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) -U+21ae uni21AE 2.7 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.9 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) -U+21af uni21AF 2.7 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.9 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+21b0 uni21B0 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.9 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) -U+21b1 uni21B1 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.9 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) -U+21b2 uni21B2 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.9 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) -U+21b3 uni21B3 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.9 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) -U+21b4 uni21B4 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.9 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) -U+21b5 carriagereturn 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.9 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) -U+21b6 uni21B6 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.9 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) -U+21b7 uni21B7 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.9 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) -U+21b8 uni21B8 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.9 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+21b9 uni21B9 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.9 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+21ba uni21BA 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.9 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) -U+21bb uni21BB 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.9 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) -U+21bc uni21BC 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.9 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) -U+21bd uni21BD 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.9 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) -U+21be uni21BE 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.9 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) -U+21bf uni21BF 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.9 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) -U+21c0 uni21C0 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.9 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) -U+21c1 uni21C1 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.9 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) -U+21c2 uni21C2 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.9 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) -U+21c3 uni21C3 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.9 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) -U+21c4 uni21C4 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) 2.9 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) -U+21c5 uni21C5 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) 2.9 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) -U+21c6 uni21C6 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) 2.9 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) -U+21c7 uni21C7 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) 2.9 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) -U+21c8 uni21C8 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) 2.9 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) -U+21c9 uni21C9 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) 2.9 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) -U+21ca uni21CA 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) 2.9 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) -U+21cb uni21CB 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.9 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) -U+21cc uni21CC 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.9 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) -U+21cd uni21CD 2.7 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.9 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) -U+21ce uni21CE 2.7 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.9 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) -U+21cf uni21CF 2.7 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.9 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) -U+21d0 arrowdblleft 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.9 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) -U+21d1 arrowdblup 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.9 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) -U+21d2 arrowdblright 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.9 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) -U+21d3 arrowdbldown 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.9 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) -U+21d4 arrowdblboth 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.9 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) -U+21d5 uni21D5 2.7 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.9 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) -U+21d6 uni21D6 2.7 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.9 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) -U+21d7 uni21D7 2.7 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.9 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) -U+21d8 uni21D8 2.7 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.9 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) -U+21d9 uni21D9 2.7 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.9 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) -U+21da uni21DA 2.7 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.9 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) -U+21db uni21DB 2.7 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.9 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) -U+21dc uni21DC 2.7 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.9 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) -U+21dd uni21DD 2.7 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.9 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) -U+21de uni21DE 2.7 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.9 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+21df uni21DF 2.7 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.9 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+21e0 uni21E0 2.7 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.9 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+21e1 uni21E1 2.7 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.9 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+21e2 uni21E2 2.7 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.9 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+21e3 uni21E3 2.7 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.9 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+21e4 uni21E4 2.7 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.9 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+21e5 uni21E5 2.7 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.9 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+21e6 uni21E6 2.7 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.9 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) -U+21e7 uni21E7 2.7 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.9 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) -U+21e8 uni21E8 2.7 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.9 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) -U+21e9 uni21E9 2.7 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.9 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) -U+21ea uni21EA 2.7 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.9 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+21eb uni21EB 2.7 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.9 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+21ec uni21EC 2.7 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.9 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+21ed uni21ED 2.7 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.9 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+21ee uni21EE 2.7 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.9 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+21ef uni21EF 2.7 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.9 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+21f0 uni21F0 2.7 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.9 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+21f1 uni21F1 2.7 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.9 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+21f2 uni21F2 2.7 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.9 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+21f3 uni21F3 2.7 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.9 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) -U+21f4 uni21F4 2.7 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.9 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+21f5 uni21F5 2.7 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.9 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) -U+21f6 uni21F6 2.7 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.9 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) -U+21f7 uni21F7 2.7 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.9 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+21f8 uni21F8 2.7 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.9 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+21f9 uni21F9 2.7 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.9 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+21fa uni21FA 2.7 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.9 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+21fb uni21FB 2.7 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.9 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+21fc uni21FC 2.7 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.9 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+21fd uni21FD 2.7 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.9 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+21fe uni21FE 2.7 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.9 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+21ff uni21FF 2.7 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.9 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+2200 universal 2.1 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.10 (Sans ExtraLight) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.26 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.36 (Math TeX Gyre Regular) -U+2201 uni2201 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.26 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.36 (Math TeX Gyre Regular) -U+2202 partialdiff original -U+2203 existential 2.1 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.10 (Sans ExtraLight) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.26 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.36 (Math TeX Gyre Regular) -U+2204 uni2204 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.26 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.36 (Math TeX Gyre Regular) -U+2205 emptyset 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.14 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.36 (Math TeX Gyre Regular) -U+2206 Delta original -U+2207 gradient 2.1 -U+2208 element 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.6 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) -U+2209 notelement 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.6 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) -U+220a uni220A 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.6 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.36 (Math TeX Gyre Regular) -U+220b suchthat 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.6 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) -U+220c uni220C 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.6 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) -U+220d uni220D 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.6 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.36 (Math TeX Gyre Regular) -U+220e uni220E 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.35 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.36 (Math TeX Gyre Regular) -U+220f product original -U+2210 uni2210 2.2 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.18 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.35 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.36 (Math TeX Gyre Regular) -U+2211 summation original -U+2212 minus original -U+2213 uni2213 2.1 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.13 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) -U+2214 uni2214 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) -U+2215 uni2215 original -U+2216 uni2216 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) 2.36 (Math TeX Gyre Regular) -U+2217 asteriskmath 2.2 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.4 (Sans ExtraLight) 2.7 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) -U+2218 uni2218 2.2 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.4 (Sans ExtraLight) 2.7 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) -U+2219 uni2219 original -U+221a radical original -U+221b uni221B 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.18 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.26 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) -U+221c uni221C 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.18 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.26 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) -U+221d proportional 2.1 -U+221e infinity original -U+221f orthogonal 2.1 -U+2220 angle 2.3 -U+2221 uni2221 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.36 (Math TeX Gyre Regular) -U+2222 uni2222 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.36 (Math TeX Gyre Regular) -U+2223 uni2223 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.35 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.36 (Math TeX Gyre Regular) -U+2224 uni2224 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) -U+2225 uni2225 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) -U+2226 uni2226 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) -U+2227 logicaland 2.1 -U+2228 logicalor 2.1 -U+2229 intersection 2.1 -U+222a union 2.1 -U+222b integral original -U+222c uni222C 2.1 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.9 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.10 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) -U+222d uni222D 2.1 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.9 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.10 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) -U+222e uni222E 2.9 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.36 (Math TeX Gyre Regular) -U+222f uni222F 2.9 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.36 (Math TeX Gyre Regular) -U+2230 uni2230 2.9 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.36 (Math TeX Gyre Regular) -U+2231 uni2231 2.9 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.36 (Math TeX Gyre Regular) -U+2232 uni2232 2.9 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.36 (Math TeX Gyre Regular) -U+2233 uni2233 2.9 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.36 (Math TeX Gyre Regular) -U+2234 therefore 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) 2.31 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.36 (Math TeX Gyre Regular) -U+2235 uni2235 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) 2.31 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.36 (Math TeX Gyre Regular) -U+2236 uni2236 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) 2.31 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.36 (Math TeX Gyre Regular) -U+2237 uni2237 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) 2.31 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.36 (Math TeX Gyre Regular) -U+2238 uni2238 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.6 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) -U+2239 uni2239 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.6 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) -U+223a uni223A 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.6 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) -U+223b uni223B 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.6 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) -U+223c similar 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) 2.5 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) -U+223d uni223D 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) -U+223e uni223E 2.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.36 (Math TeX Gyre Regular) -U+223f uni223F 2.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.36 (Math TeX Gyre Regular) -U+2240 uni2240 2.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.36 (Math TeX Gyre Regular) -U+2241 uni2241 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique) 2.36 (Math TeX Gyre Regular) -U+2242 uni2242 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) -U+2243 uni2243 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) -U+2244 uni2244 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique) 2.36 (Math TeX Gyre Regular) -U+2245 congruent 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.5 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.36 (Math TeX Gyre Regular) -U+2246 uni2246 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique) 2.36 (Math TeX Gyre Regular) -U+2247 uni2247 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique) 2.36 (Math TeX Gyre Regular) -U+2248 approxequal original -U+2249 uni2249 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique) 2.36 (Math TeX Gyre Regular) -U+224a uni224A 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique) 2.36 (Math TeX Gyre Regular) -U+224b uni224B 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique) 2.36 (Math TeX Gyre Regular) -U+224c uni224C 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique) 2.36 (Math TeX Gyre Regular) -U+224d uni224D 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique) 2.36 (Math TeX Gyre Regular) -U+224e uni224E 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique) 2.36 (Math TeX Gyre Regular) -U+224f uni224F 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique) 2.36 (Math TeX Gyre Regular) -U+2250 uni2250 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) -U+2251 uni2251 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) -U+2252 uni2252 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) -U+2253 uni2253 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) -U+2254 uni2254 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) -U+2255 uni2255 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) -U+2256 uni2256 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique) 2.36 (Math TeX Gyre Regular) -U+2257 uni2257 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique) 2.36 (Math TeX Gyre Regular) -U+2258 uni2258 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique) 2.36 (Math TeX Gyre Regular) -U+2259 uni2259 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique) 2.36 (Math TeX Gyre Regular) -U+225a uni225A 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique) 2.36 (Math TeX Gyre Regular) -U+225b uni225B 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique) 2.36 (Math TeX Gyre Regular) -U+225c uni225C 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique) 2.36 (Math TeX Gyre Regular) -U+225d uni225D 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique) 2.36 (Math TeX Gyre Regular) -U+225e uni225E 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique) 2.36 (Math TeX Gyre Regular) -U+225f uni225F 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique) 2.36 (Math TeX Gyre Regular) -U+2260 notequal original -U+2261 equivalence 2.1 -U+2262 uni2262 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique) 2.36 (Math TeX Gyre Regular) -U+2263 uni2263 2.1 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.5 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.36 (Math TeX Gyre Regular) -U+2264 lessequal original -U+2265 greaterequal original -U+2266 uni2266 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique) 2.36 (Math TeX Gyre Regular) -U+2267 uni2267 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique) 2.36 (Math TeX Gyre Regular) -U+2268 uni2268 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique) 2.36 (Math TeX Gyre Regular) -U+2269 uni2269 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique) 2.36 (Math TeX Gyre Regular) -U+226a uni226A 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.36 (Math TeX Gyre Regular) -U+226b uni226B 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.36 (Math TeX Gyre Regular) -U+226c uni226C 2.7 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.36 (Math TeX Gyre Regular) -U+226d uni226D 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique) 2.36 (Math TeX Gyre Regular) -U+226e uni226E 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique) 2.36 (Math TeX Gyre Regular) -U+226f uni226F 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique) 2.36 (Math TeX Gyre Regular) -U+2270 uni2270 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique) 2.36 (Math TeX Gyre Regular) -U+2271 uni2271 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique) 2.36 (Math TeX Gyre Regular) -U+2272 uni2272 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique) 2.36 (Math TeX Gyre Regular) -U+2273 uni2273 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique) 2.36 (Math TeX Gyre Regular) -U+2274 uni2274 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique) 2.36 (Math TeX Gyre Regular) -U+2275 uni2275 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique) 2.36 (Math TeX Gyre Regular) -U+2276 uni2276 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique) 2.36 (Math TeX Gyre Regular) -U+2277 uni2277 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique) 2.36 (Math TeX Gyre Regular) -U+2278 uni2278 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.6 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.36 (Math TeX Gyre Regular) -U+2279 uni2279 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.6 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.36 (Math TeX Gyre Regular) -U+227a uni227A 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.6 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.36 (Math TeX Gyre Regular) -U+227b uni227B 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.6 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.36 (Math TeX Gyre Regular) -U+227c uni227C 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.6 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.36 (Math TeX Gyre Regular) -U+227d uni227D 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.6 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.36 (Math TeX Gyre Regular) -U+227e uni227E 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.6 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.36 (Math TeX Gyre Regular) -U+227f uni227F 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.6 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.36 (Math TeX Gyre Regular) -U+2280 uni2280 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.6 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.36 (Math TeX Gyre Regular) -U+2281 uni2281 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.6 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.36 (Math TeX Gyre Regular) -U+2282 propersubset 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.5 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) -U+2283 propersuperset 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.5 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) -U+2284 notsubset 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) -U+2285 uni2285 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) -U+2286 reflexsubset 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) -U+2287 reflexsuperset 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) -U+2288 uni2288 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique) 2.36 (Math TeX Gyre Regular) -U+2289 uni2289 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique) 2.36 (Math TeX Gyre Regular) -U+228a uni228A 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.6 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.36 (Math TeX Gyre Regular) -U+228b uni228B 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.6 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.36 (Math TeX Gyre Regular) -U+228c uni228C 2.7 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) -U+228d uni228D 2.7 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.35 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.36 (Math TeX Gyre Regular) -U+228e uni228E 2.7 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.35 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.36 (Math TeX Gyre Regular) -U+228f uni228F 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) -U+2290 uni2290 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) -U+2291 uni2291 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) -U+2292 uni2292 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) -U+2293 uni2293 2.7 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.35 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.36 (Math TeX Gyre Regular) -U+2294 uni2294 2.7 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.35 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.36 (Math TeX Gyre Regular) -U+2295 circleplus 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.7 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) -U+2296 uni2296 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.7 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) -U+2297 circlemultiply 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.7 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) -U+2298 uni2298 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.7 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) -U+2299 uni2299 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.7 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) -U+229a uni229A 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.7 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) -U+229b uni229B 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.7 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) -U+229c uni229C 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.7 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) -U+229d uni229D 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.7 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) -U+229e uni229E 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.7 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) -U+229f uni229F 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.7 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) -U+22a0 uni22A0 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.7 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) -U+22a1 uni22A1 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.7 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) -U+22a2 uni22A2 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.32 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.36 (Math TeX Gyre Regular) -U+22a3 uni22A3 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.32 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.36 (Math TeX Gyre Regular) -U+22a4 uni22A4 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.32 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.36 (Math TeX Gyre Regular) -U+22a5 perpendicular 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.32 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.36 (Math TeX Gyre Regular) -U+22a6 uni22A6 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) -U+22a7 uni22A7 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) -U+22a8 uni22A8 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) -U+22a9 uni22A9 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) -U+22aa uni22AA 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) -U+22ab uni22AB 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) -U+22ac uni22AC 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) -U+22ad uni22AD 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) -U+22ae uni22AE 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) -U+22af uni22AF 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) -U+22b0 uni22B0 2.27 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+22b1 uni22B1 2.27 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+22b2 uni22B2 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.35 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.36 (Math TeX Gyre Regular) -U+22b3 uni22B3 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.35 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.36 (Math TeX Gyre Regular) -U+22b4 uni22B4 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.35 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.36 (Math TeX Gyre Regular) -U+22b5 uni22B5 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.35 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.36 (Math TeX Gyre Regular) -U+22b6 uni22B6 2.9 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.36 (Math TeX Gyre Regular) -U+22b7 uni22B7 2.9 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.36 (Math TeX Gyre Regular) -U+22b8 uni22B8 2.9 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.35 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.36 (Math TeX Gyre Regular) -U+22b9 uni22B9 2.9 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.36 (Math TeX Gyre Regular) -U+22ba uni22BA 2.9 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.36 (Math TeX Gyre Regular) -U+22bb uni22BB 2.9 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.36 (Math TeX Gyre Regular) -U+22bc uni22BC 2.9 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.36 (Math TeX Gyre Regular) -U+22bd uni22BD 2.9 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.36 (Math TeX Gyre Regular) -U+22be uni22BE 2.16 (Sans, Sans Bold, Sans Bold Oblique, Sans Oblique) 2.17 (Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique) 2.36 (Math TeX Gyre Regular) -U+22bf uni22BF 2.16 (Sans, Sans Bold, Sans Bold Oblique, Sans Oblique) 2.17 (Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique) 2.36 (Math TeX Gyre Regular) -U+22c0 uni22C0 2.9 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.36 (Math TeX Gyre Regular) -U+22c1 uni22C1 2.9 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.36 (Math TeX Gyre Regular) -U+22c2 uni22C2 2.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.35 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.36 (Math TeX Gyre Regular) -U+22c3 uni22C3 2.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.35 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.36 (Math TeX Gyre Regular) -U+22c4 uni22C4 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.35 (Sans ExtraLight, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.36 (Math TeX Gyre Regular) -U+22c5 dotmath 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.13 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) -U+22c6 uni22C6 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.14 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.36 (Math TeX Gyre Regular) -U+22c7 uni22C7 2.27 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.36 (Math TeX Gyre Regular) -U+22c8 uni22C8 2.7 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.36 (Math TeX Gyre Regular) -U+22c9 uni22C9 2.7 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.36 (Math TeX Gyre Regular) -U+22ca uni22CA 2.7 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.36 (Math TeX Gyre Regular) -U+22cb uni22CB 2.7 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.36 (Math TeX Gyre Regular) -U+22cc uni22CC 2.7 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.36 (Math TeX Gyre Regular) -U+22cd uni22CD 2.6 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold, Sans Condensed Oblique, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique) 2.7 (Sans Bold Oblique, Sans Condensed Bold Oblique) 2.36 (Math TeX Gyre Regular) -U+22ce uni22CE 2.26 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.35 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.36 (Math TeX Gyre Regular) -U+22cf uni22CF 2.26 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.35 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.36 (Math TeX Gyre Regular) -U+22d0 uni22D0 2.27 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.35 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.36 (Math TeX Gyre Regular) -U+22d1 uni22D1 2.27 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.35 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.36 (Math TeX Gyre Regular) -U+22d2 uni22D2 2.27 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.36 (Math TeX Gyre Regular) -U+22d3 uni22D3 2.27 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.36 (Math TeX Gyre Regular) -U+22d4 uni22D4 2.27 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+22d5 uni22D5 2.27 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.36 (Math TeX Gyre Regular) -U+22d6 uni22D6 2.9 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.36 (Math TeX Gyre Regular) -U+22d7 uni22D7 2.9 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.36 (Math TeX Gyre Regular) -U+22d8 uni22D8 2.6 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold, Sans Condensed Oblique, Sans Oblique) 2.7 (Sans Bold Oblique, Sans Condensed Bold Oblique) 2.36 (Math TeX Gyre Regular) -U+22d9 uni22D9 2.6 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold, Sans Condensed Oblique, Sans Oblique) 2.7 (Sans Bold Oblique, Sans Condensed Bold Oblique) 2.36 (Math TeX Gyre Regular) -U+22da uni22DA 2.6 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold, Sans Condensed Oblique, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique) 2.7 (Sans Bold Oblique, Sans Condensed Bold Oblique) 2.36 (Math TeX Gyre Regular) -U+22db uni22DB 2.6 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold, Sans Condensed Oblique, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique) 2.7 (Sans Bold Oblique, Sans Condensed Bold Oblique) 2.36 (Math TeX Gyre Regular) -U+22dc uni22DC 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique) 2.36 (Math TeX Gyre Regular) -U+22dd uni22DD 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique) 2.36 (Math TeX Gyre Regular) -U+22de uni22DE 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique) 2.36 (Math TeX Gyre Regular) -U+22df uni22DF 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique) 2.36 (Math TeX Gyre Regular) -U+22e0 uni22E0 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique) 2.36 (Math TeX Gyre Regular) -U+22e1 uni22E1 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique) 2.36 (Math TeX Gyre Regular) -U+22e2 uni22E2 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique) 2.36 (Math TeX Gyre Regular) -U+22e3 uni22E3 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique) 2.36 (Math TeX Gyre Regular) -U+22e4 uni22E4 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique) 2.36 (Math TeX Gyre Regular) -U+22e5 uni22E5 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique) 2.36 (Math TeX Gyre Regular) -U+22e6 uni22E6 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique) 2.36 (Math TeX Gyre Regular) -U+22e7 uni22E7 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique) 2.36 (Math TeX Gyre Regular) -U+22e8 uni22E8 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique) 2.36 (Math TeX Gyre Regular) -U+22e9 uni22E9 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique) 2.36 (Math TeX Gyre Regular) -U+22ea uni22EA 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.36 (Math TeX Gyre Regular) -U+22eb uni22EB 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.36 (Math TeX Gyre Regular) -U+22ec uni22EC 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.36 (Math TeX Gyre Regular) -U+22ed uni22ED 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.36 (Math TeX Gyre Regular) -U+22ee uni22EE 2.18 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.36 (Math TeX Gyre Regular) -U+22ef uni22EF 2.13 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.18 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.36 (Math TeX Gyre Regular) -U+22f0 uni22F0 2.18 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.36 (Math TeX Gyre Regular) -U+22f1 uni22F1 2.18 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.36 (Math TeX Gyre Regular) -U+22f2 uni22F2 2.7 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+22f3 uni22F3 2.7 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+22f4 uni22F4 2.7 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+22f5 uni22F5 2.7 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+22f6 uni22F6 2.7 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+22f7 uni22F7 2.7 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+22f8 uni22F8 2.7 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+22f9 uni22F9 2.7 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+22fa uni22FA 2.7 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+22fb uni22FB 2.7 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+22fc uni22FC 2.7 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+22fd uni22FD 2.7 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+22fe uni22FE 2.7 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+22ff uni22FF 2.7 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+2300 uni2300 2.14 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.16 (Sans, Sans Bold, Sans Bold Oblique, Sans Oblique) 2.17 (Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique) 2.36 (Math TeX Gyre Regular) -U+2301 uni2301 2.14 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.16 (Sans, Sans Bold, Sans Bold Oblique, Sans Oblique) 2.17 (Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique) -U+2302 house 1.14 -U+2303 uni2303 2.14 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.16 (Sans, Sans Bold, Sans Bold Oblique, Sans Oblique) 2.17 (Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique) -U+2304 uni2304 2.14 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.16 (Sans, Sans Bold, Sans Bold Oblique, Sans Oblique) 2.17 (Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique) -U+2305 uni2305 2.14 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.16 (Sans, Sans Bold, Sans Bold Oblique, Sans Oblique) 2.17 (Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique) 2.36 (Math TeX Gyre Regular) -U+2306 uni2306 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.14 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.36 (Math TeX Gyre Regular) -U+2307 uni2307 2.16 (Sans, Sans Bold, Sans Bold Oblique, Sans Oblique) 2.17 (Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique) -U+2308 uni2308 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.10 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Italic) 2.11 (Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) -U+2309 uni2309 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.10 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Italic) 2.11 (Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) -U+230a uni230A 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.10 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Italic) 2.11 (Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) -U+230b uni230B 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.10 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Italic) 2.11 (Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) -U+230c uni230C 2.14 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.16 (Sans, Sans Bold, Sans Bold Oblique, Sans Oblique) 2.17 (Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique) -U+230d uni230D 2.14 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.16 (Sans, Sans Bold, Sans Bold Oblique, Sans Oblique) 2.17 (Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique) -U+230e uni230E 2.14 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.16 (Sans, Sans Bold, Sans Bold Oblique, Sans Oblique) 2.17 (Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique) -U+230f uni230F 2.14 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.16 (Sans, Sans Bold, Sans Bold Oblique, Sans Oblique) 2.17 (Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique) -U+2310 revlogicalnot 1.14 -U+2311 uni2311 1.15 -U+2312 uni2312 2.14 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) -U+2313 uni2313 2.14 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) -U+2314 uni2314 2.14 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) -U+2315 uni2315 2.14 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) -U+2318 uni2318 2.2 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.10 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.23 (Serif Italic Condensed) -U+2319 uni2319 1.14 -U+231c uni231C 2.14 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.16 (Sans, Sans Bold, Sans Bold Oblique, Sans Oblique) 2.17 (Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique) 2.36 (Math TeX Gyre Regular) -U+231d uni231D 2.14 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.16 (Sans, Sans Bold, Sans Bold Oblique, Sans Oblique) 2.17 (Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique) 2.36 (Math TeX Gyre Regular) -U+231e uni231E 2.14 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.16 (Sans, Sans Bold, Sans Bold Oblique, Sans Oblique) 2.17 (Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique) 2.36 (Math TeX Gyre Regular) -U+231f uni231F 2.14 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.16 (Sans, Sans Bold, Sans Bold Oblique, Sans Oblique) 2.17 (Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique) 2.36 (Math TeX Gyre Regular) -U+2320 integraltp 2.3 -U+2321 integralbt 2.3 -U+2322 uni2322 2.36 (Math TeX Gyre Regular) -U+2323 uni2323 2.36 (Math TeX Gyre Regular) -U+2324 uni2324 2.16 (Sans, Sans Bold, Sans Bold Oblique) 2.17 (Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique) 2.19 (Sans Condensed Oblique, Sans Oblique) -U+2325 uni2325 2.2 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.10 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.23 (Serif Italic Condensed) -U+2326 uni2326 2.14 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.16 (Sans, Sans Bold, Sans Bold Oblique, Sans Oblique) 2.17 (Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique) -U+2327 uni2327 2.14 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.16 (Sans, Sans Bold, Sans Bold Oblique, Sans Oblique) 2.17 (Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique) -U+2328 uni2328 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+2329 angleleft 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.10 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Italic) 2.11 (Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic) 2.36 (Math TeX Gyre Regular) -U+232a angleright 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.10 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Italic) 2.11 (Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic) 2.36 (Math TeX Gyre Regular) -U+232b uni232B 2.14 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.16 (Sans, Sans Bold, Sans Bold Oblique, Sans Oblique) 2.17 (Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique) -U+232c uni232C 2.16 (Sans, Sans Bold, Sans Bold Oblique, Sans Oblique) 2.17 (Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique) -U+2335 uni2335 2.14 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) -U+2336 uni2336 2.35 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) -U+2337 uni2337 2.14 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) -U+2338 uni2338 2.14 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) -U+2339 uni2339 2.14 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) -U+233a uni233A 2.14 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) -U+233b uni233B 2.14 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) -U+233c uni233C 2.14 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) -U+233d uni233D 2.14 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) -U+233e uni233E 2.14 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) -U+233f uni233F 2.35 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) -U+2340 uni2340 2.35 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) -U+2341 uni2341 2.14 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) -U+2342 uni2342 2.14 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) -U+2343 uni2343 2.14 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) -U+2344 uni2344 2.14 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) -U+2345 uni2345 2.35 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) -U+2346 uni2346 2.35 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) -U+2347 uni2347 2.14 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) -U+2348 uni2348 2.14 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) -U+2349 uni2349 2.14 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) -U+234a uni234A 2.35 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) -U+234b uni234B 2.14 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) -U+234c uni234C 2.14 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) -U+234d uni234D 2.14 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) -U+234e uni234E 2.35 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) -U+234f uni234F 2.35 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) -U+2350 uni2350 2.14 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) -U+2351 uni2351 2.35 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) -U+2352 uni2352 2.14 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) -U+2353 uni2353 2.14 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) -U+2354 uni2354 2.14 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) -U+2355 uni2355 2.35 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) -U+2356 uni2356 2.35 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) -U+2357 uni2357 2.14 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) -U+2358 uni2358 2.14 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) -U+2359 uni2359 2.14 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) -U+235a uni235A 2.14 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) -U+235b uni235B 2.14 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) -U+235c uni235C 2.14 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) -U+235d uni235D 2.35 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) -U+235e uni235E 2.14 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) -U+235f uni235F 2.14 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) -U+2360 uni2360 2.14 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) -U+2361 uni2361 2.35 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) -U+2362 uni2362 2.35 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) -U+2363 uni2363 2.14 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) -U+2364 uni2364 2.14 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) -U+2365 uni2365 2.14 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) -U+2366 uni2366 2.35 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) -U+2367 uni2367 2.35 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) -U+2368 uni2368 2.14 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) -U+2369 uni2369 2.14 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) -U+236a uni236A 2.35 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) -U+236b uni236B 2.14 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) -U+236c uni236C 2.14 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) -U+236d uni236D 2.14 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) -U+236e uni236E 2.14 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) -U+236f uni236F 2.14 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) -U+2370 uni2370 2.14 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) -U+2371 uni2371 2.35 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) -U+2372 uni2372 2.35 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) -U+2373 uni2373 2.14 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.16 (Sans, Sans Bold, Sans Bold Oblique, Sans Oblique) 2.17 (Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique) -U+2374 uni2374 2.14 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.16 (Sans, Sans Bold, Sans Bold Oblique, Sans Oblique) 2.17 (Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique) -U+2375 uni2375 2.14 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.16 (Sans, Sans Bold, Sans Bold Oblique, Sans Oblique) 2.17 (Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique) -U+2376 uni2376 2.14 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) -U+2377 uni2377 2.14 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) -U+2378 uni2378 2.14 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) -U+2379 uni2379 2.14 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) -U+237a uni237A 2.14 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.16 (Sans, Sans Bold, Sans Bold Oblique, Sans Oblique) 2.17 (Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique) -U+237d uni237D 1.15 -U+2380 uni2380 2.14 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) -U+2381 uni2381 2.14 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) -U+2382 uni2382 2.14 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) -U+2383 uni2383 2.14 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) -U+2387 uni2387 2.16 (Sans, Sans Bold, Sans Bold Oblique, Sans Oblique) 2.17 (Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique) -U+2388 uni2388 2.14 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) -U+2389 uni2389 2.14 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) -U+238a uni238A 2.14 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) -U+238b uni238B 2.14 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) -U+2394 uni2394 2.16 (Sans, Sans Bold, Sans Bold Oblique, Sans Oblique) 2.17 (Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique) -U+2395 uni2395 2.14 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) -U+239b uni239B 2.9 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique) 2.32 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.36 (Math TeX Gyre Regular) -U+239c uni239C 2.9 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique) 2.32 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.36 (Math TeX Gyre Regular) -U+239d uni239D 2.9 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique) 2.32 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.36 (Math TeX Gyre Regular) -U+239e uni239E 2.9 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique) 2.32 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.36 (Math TeX Gyre Regular) -U+239f uni239F 2.9 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique) 2.32 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.36 (Math TeX Gyre Regular) -U+23a0 uni23A0 2.9 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique) 2.32 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.36 (Math TeX Gyre Regular) -U+23a1 uni23A1 2.9 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique) 2.32 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.36 (Math TeX Gyre Regular) -U+23a2 uni23A2 2.9 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique) 2.32 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.36 (Math TeX Gyre Regular) -U+23a3 uni23A3 2.9 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique) 2.32 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.36 (Math TeX Gyre Regular) -U+23a4 uni23A4 2.9 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique) 2.32 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.36 (Math TeX Gyre Regular) -U+23a5 uni23A5 2.9 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique) 2.32 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.36 (Math TeX Gyre Regular) -U+23a6 uni23A6 2.9 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique) 2.32 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.36 (Math TeX Gyre Regular) -U+23a7 uni23A7 2.9 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique) 2.32 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.36 (Math TeX Gyre Regular) -U+23a8 uni23A8 2.9 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique) 2.32 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.36 (Math TeX Gyre Regular) -U+23a9 uni23A9 2.9 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique) 2.32 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.36 (Math TeX Gyre Regular) -U+23aa uni23AA 2.9 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique) 2.32 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.36 (Math TeX Gyre Regular) -U+23ab uni23AB 2.9 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique) 2.32 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.36 (Math TeX Gyre Regular) -U+23ac uni23AC 2.9 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique) 2.32 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.36 (Math TeX Gyre Regular) -U+23ad uni23AD 2.9 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique) 2.32 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.36 (Math TeX Gyre Regular) -U+23ae uni23AE 2.3 -U+23b2 uni23B2 2.36 (Math TeX Gyre Regular) -U+23b3 uni23B3 2.36 (Math TeX Gyre Regular) -U+23b4 uni23B4 2.36 (Math TeX Gyre Regular) -U+23b5 uni23B5 2.36 (Math TeX Gyre Regular) -U+23b7 uni23B7 2.35 (Serif, Serif Condensed) 2.36 (Math TeX Gyre Regular) -U+23ce uni23CE 2.15 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique) -U+23cf uni23CF 2.3 -U+23d0 uni23D0 2.36 (Math TeX Gyre Regular) -U+23dc uni23DC 2.36 (Math TeX Gyre Regular) -U+23dd uni23DD 2.36 (Math TeX Gyre Regular) -U+23de uni23DE 2.36 (Math TeX Gyre Regular) -U+23df uni23DF 2.36 (Math TeX Gyre Regular) -U+23e0 uni23E0 2.36 (Math TeX Gyre Regular) -U+23e1 uni23E1 2.36 (Math TeX Gyre Regular) -U+23e3 uni23E3 2.16 (Sans, Sans Bold, Sans Bold Oblique, Sans Oblique) 2.17 (Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique) -U+23e5 uni23E5 2.16 (Sans, Sans Bold, Sans Bold Oblique, Sans Oblique) 2.17 (Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique) -U+23e8 uni23E8 2.32 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+2422 uni2422 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.36 (Math TeX Gyre Regular) -U+2423 uni2423 1.6 -U+2460 uni2460 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+2461 uni2461 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+2462 uni2462 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+2463 uni2463 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+2464 uni2464 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+2465 uni2465 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+2466 uni2466 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+2467 uni2467 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+2468 uni2468 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+2469 uni2469 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+2500 SF100000 1.12 (Sans Mono, Sans Mono Oblique) 2.21 (Sans, Sans Condensed, Sans Condensed Oblique, Sans Oblique, Serif, Serif Condensed, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.35 (Sans Bold, Sans Bold Oblique, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Mono Bold, Sans Mono Bold Oblique, Serif Bold, Serif Bold Italic, Serif Condensed Bold, Serif Condensed Bold Italic) 2.36 (Math TeX Gyre Regular) -U+2501 uni2501 1.12 (Sans Mono, Sans Mono Oblique) 2.21 (Sans, Sans Condensed, Sans Condensed Oblique, Sans Oblique, Serif, Serif Condensed, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.35 (Sans Bold, Sans Bold Oblique, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Mono Bold, Sans Mono Bold Oblique, Serif Bold, Serif Bold Italic, Serif Condensed Bold, Serif Condensed Bold Italic) -U+2502 SF110000 1.12 (Sans Mono, Sans Mono Oblique) 2.21 (Sans, Sans Condensed, Sans Condensed Oblique, Sans Oblique, Serif, Serif Condensed, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.35 (Sans Bold, Sans Bold Oblique, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Mono Bold, Sans Mono Bold Oblique, Serif Bold, Serif Bold Italic, Serif Condensed Bold, Serif Condensed Bold Italic) 2.36 (Math TeX Gyre Regular) -U+2503 uni2503 1.12 (Sans Mono, Sans Mono Oblique) 2.21 (Sans, Sans Condensed, Sans Condensed Oblique, Sans Oblique, Serif, Serif Condensed, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.35 (Sans Bold, Sans Bold Oblique, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Mono Bold, Sans Mono Bold Oblique, Serif Bold, Serif Bold Italic, Serif Condensed Bold, Serif Condensed Bold Italic) -U+2504 uni2504 1.12 (Sans Mono, Sans Mono Oblique) 2.21 (Sans, Sans Condensed, Sans Condensed Oblique, Sans Oblique, Serif, Serif Condensed, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.35 (Sans Bold, Sans Bold Oblique, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Mono Bold, Sans Mono Bold Oblique, Serif Bold, Serif Bold Italic, Serif Condensed Bold, Serif Condensed Bold Italic) -U+2505 uni2505 1.12 (Sans Mono, Sans Mono Oblique) 2.21 (Sans, Sans Condensed, Sans Condensed Oblique, Sans Oblique, Serif, Serif Condensed, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.35 (Sans Bold, Sans Bold Oblique, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Mono Bold, Sans Mono Bold Oblique, Serif Bold, Serif Bold Italic, Serif Condensed Bold, Serif Condensed Bold Italic) -U+2506 uni2506 1.12 (Sans Mono, Sans Mono Oblique) 2.21 (Sans, Sans Condensed, Sans Condensed Oblique, Sans Oblique, Serif, Serif Condensed, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.35 (Sans Bold, Sans Bold Oblique, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Mono Bold, Sans Mono Bold Oblique, Serif Bold, Serif Bold Italic, Serif Condensed Bold, Serif Condensed Bold Italic) -U+2507 uni2507 1.12 (Sans Mono, Sans Mono Oblique) 2.21 (Sans, Sans Condensed, Sans Condensed Oblique, Sans Oblique, Serif, Serif Condensed, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.35 (Sans Bold, Sans Bold Oblique, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Mono Bold, Sans Mono Bold Oblique, Serif Bold, Serif Bold Italic, Serif Condensed Bold, Serif Condensed Bold Italic) -U+2508 uni2508 1.12 (Sans Mono, Sans Mono Oblique) 2.21 (Sans, Sans Condensed, Sans Condensed Oblique, Sans Oblique, Serif, Serif Condensed, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.35 (Sans Bold, Sans Bold Oblique, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Mono Bold, Sans Mono Bold Oblique, Serif Bold, Serif Bold Italic, Serif Condensed Bold, Serif Condensed Bold Italic) -U+2509 uni2509 1.12 (Sans Mono, Sans Mono Oblique) 2.21 (Sans, Sans Condensed, Sans Condensed Oblique, Sans Oblique, Serif, Serif Condensed, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.35 (Sans Bold, Sans Bold Oblique, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Mono Bold, Sans Mono Bold Oblique, Serif Bold, Serif Bold Italic, Serif Condensed Bold, Serif Condensed Bold Italic) -U+250a uni250A 1.12 (Sans Mono, Sans Mono Oblique) 2.21 (Sans, Sans Condensed, Sans Condensed Oblique, Sans Oblique, Serif, Serif Condensed, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.35 (Sans Bold, Sans Bold Oblique, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Mono Bold, Sans Mono Bold Oblique, Serif Bold, Serif Bold Italic, Serif Condensed Bold, Serif Condensed Bold Italic) -U+250b uni250B 1.12 (Sans Mono, Sans Mono Oblique) 2.21 (Sans, Sans Condensed, Sans Condensed Oblique, Sans Oblique, Serif, Serif Condensed, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.35 (Sans Bold, Sans Bold Oblique, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Mono Bold, Sans Mono Bold Oblique, Serif Bold, Serif Bold Italic, Serif Condensed Bold, Serif Condensed Bold Italic) -U+250c SF010000 1.12 (Sans Mono, Sans Mono Oblique) 2.21 (Sans, Sans Condensed, Sans Condensed Oblique, Sans Oblique, Serif, Serif Condensed, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.35 (Sans Bold, Sans Bold Oblique, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Mono Bold, Sans Mono Bold Oblique, Serif Bold, Serif Bold Italic, Serif Condensed Bold, Serif Condensed Bold Italic) 2.36 (Math TeX Gyre Regular) -U+250d uni250D 1.12 (Sans Mono, Sans Mono Oblique) 2.21 (Sans, Sans Condensed, Sans Condensed Oblique, Sans Oblique, Serif, Serif Condensed, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.35 (Sans Bold, Sans Bold Oblique, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Mono Bold, Sans Mono Bold Oblique, Serif Bold, Serif Bold Italic, Serif Condensed Bold, Serif Condensed Bold Italic) -U+250e uni250E 1.12 (Sans Mono, Sans Mono Oblique) 2.21 (Sans, Sans Condensed, Sans Condensed Oblique, Sans Oblique, Serif, Serif Condensed, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.35 (Sans Bold, Sans Bold Oblique, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Mono Bold, Sans Mono Bold Oblique, Serif Bold, Serif Bold Italic, Serif Condensed Bold, Serif Condensed Bold Italic) -U+250f uni250F 1.12 (Sans Mono, Sans Mono Oblique) 2.21 (Sans, Sans Condensed, Sans Condensed Oblique, Sans Oblique, Serif, Serif Condensed, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.35 (Sans Bold, Sans Bold Oblique, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Mono Bold, Sans Mono Bold Oblique, Serif Bold, Serif Bold Italic, Serif Condensed Bold, Serif Condensed Bold Italic) -U+2510 SF030000 1.12 (Sans Mono, Sans Mono Oblique) 2.21 (Sans, Sans Condensed, Sans Condensed Oblique, Sans Oblique, Serif, Serif Condensed, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.35 (Sans Bold, Sans Bold Oblique, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Mono Bold, Sans Mono Bold Oblique, Serif Bold, Serif Bold Italic, Serif Condensed Bold, Serif Condensed Bold Italic) 2.36 (Math TeX Gyre Regular) -U+2511 uni2511 1.12 (Sans Mono, Sans Mono Oblique) 2.21 (Sans, Sans Condensed, Sans Condensed Oblique, Sans Oblique, Serif, Serif Condensed, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.35 (Sans Bold, Sans Bold Oblique, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Mono Bold, Sans Mono Bold Oblique, Serif Bold, Serif Bold Italic, Serif Condensed Bold, Serif Condensed Bold Italic) -U+2512 uni2512 1.12 (Sans Mono, Sans Mono Oblique) 2.21 (Sans, Sans Condensed, Sans Condensed Oblique, Sans Oblique, Serif, Serif Condensed, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.35 (Sans Bold, Sans Bold Oblique, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Mono Bold, Sans Mono Bold Oblique, Serif Bold, Serif Bold Italic, Serif Condensed Bold, Serif Condensed Bold Italic) -U+2513 uni2513 1.12 (Sans Mono, Sans Mono Oblique) 2.21 (Sans, Sans Condensed, Sans Condensed Oblique, Sans Oblique, Serif, Serif Condensed, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.35 (Sans Bold, Sans Bold Oblique, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Mono Bold, Sans Mono Bold Oblique, Serif Bold, Serif Bold Italic, Serif Condensed Bold, Serif Condensed Bold Italic) -U+2514 SF020000 1.12 (Sans Mono, Sans Mono Oblique) 2.21 (Sans, Sans Condensed, Sans Condensed Oblique, Sans Oblique, Serif, Serif Condensed, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.35 (Sans Bold, Sans Bold Oblique, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Mono Bold, Sans Mono Bold Oblique, Serif Bold, Serif Bold Italic, Serif Condensed Bold, Serif Condensed Bold Italic) 2.36 (Math TeX Gyre Regular) -U+2515 uni2515 1.12 (Sans Mono, Sans Mono Oblique) 2.21 (Sans, Sans Condensed, Sans Condensed Oblique, Sans Oblique, Serif, Serif Condensed, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.35 (Sans Bold, Sans Bold Oblique, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Mono Bold, Sans Mono Bold Oblique, Serif Bold, Serif Bold Italic, Serif Condensed Bold, Serif Condensed Bold Italic) -U+2516 uni2516 1.12 (Sans Mono, Sans Mono Oblique) 2.21 (Sans, Sans Condensed, Sans Condensed Oblique, Sans Oblique, Serif, Serif Condensed, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.35 (Sans Bold, Sans Bold Oblique, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Mono Bold, Sans Mono Bold Oblique, Serif Bold, Serif Bold Italic, Serif Condensed Bold, Serif Condensed Bold Italic) -U+2517 uni2517 1.12 (Sans Mono, Sans Mono Oblique) 2.21 (Sans, Sans Condensed, Sans Condensed Oblique, Sans Oblique, Serif, Serif Condensed, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.35 (Sans Bold, Sans Bold Oblique, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Mono Bold, Sans Mono Bold Oblique, Serif Bold, Serif Bold Italic, Serif Condensed Bold, Serif Condensed Bold Italic) -U+2518 SF040000 1.12 (Sans Mono, Sans Mono Oblique) 2.21 (Sans, Sans Condensed, Sans Condensed Oblique, Sans Oblique, Serif, Serif Condensed, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.35 (Sans Bold, Sans Bold Oblique, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Mono Bold, Sans Mono Bold Oblique, Serif Bold, Serif Bold Italic, Serif Condensed Bold, Serif Condensed Bold Italic) 2.36 (Math TeX Gyre Regular) -U+2519 uni2519 1.12 (Sans Mono, Sans Mono Oblique) 2.21 (Sans, Sans Condensed, Sans Condensed Oblique, Sans Oblique, Serif, Serif Condensed, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.35 (Sans Bold, Sans Bold Oblique, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Mono Bold, Sans Mono Bold Oblique, Serif Bold, Serif Bold Italic, Serif Condensed Bold, Serif Condensed Bold Italic) -U+251a uni251A 1.12 (Sans Mono, Sans Mono Oblique) 2.21 (Sans, Sans Condensed, Sans Condensed Oblique, Sans Oblique, Serif, Serif Condensed, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.35 (Sans Bold, Sans Bold Oblique, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Mono Bold, Sans Mono Bold Oblique, Serif Bold, Serif Bold Italic, Serif Condensed Bold, Serif Condensed Bold Italic) -U+251b uni251B 1.12 (Sans Mono, Sans Mono Oblique) 2.21 (Sans, Sans Condensed, Sans Condensed Oblique, Sans Oblique, Serif, Serif Condensed, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.35 (Sans Bold, Sans Bold Oblique, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Mono Bold, Sans Mono Bold Oblique, Serif Bold, Serif Bold Italic, Serif Condensed Bold, Serif Condensed Bold Italic) -U+251c SF080000 1.12 (Sans Mono, Sans Mono Oblique) 2.21 (Sans, Sans Condensed, Sans Condensed Oblique, Sans Oblique, Serif, Serif Condensed, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.35 (Sans Bold, Sans Bold Oblique, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Mono Bold, Sans Mono Bold Oblique, Serif Bold, Serif Bold Italic, Serif Condensed Bold, Serif Condensed Bold Italic) 2.36 (Math TeX Gyre Regular) -U+251d uni251D 1.12 (Sans Mono, Sans Mono Oblique) 2.21 (Sans, Sans Condensed, Sans Condensed Oblique, Sans Oblique, Serif, Serif Condensed, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.35 (Sans Bold, Sans Bold Oblique, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Mono Bold, Sans Mono Bold Oblique, Serif Bold, Serif Bold Italic, Serif Condensed Bold, Serif Condensed Bold Italic) -U+251e uni251E 1.12 (Sans Mono, Sans Mono Oblique) 2.21 (Sans, Sans Condensed, Sans Condensed Oblique, Sans Oblique, Serif, Serif Condensed, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.35 (Sans Bold, Sans Bold Oblique, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Mono Bold, Sans Mono Bold Oblique, Serif Bold, Serif Bold Italic, Serif Condensed Bold, Serif Condensed Bold Italic) -U+251f uni251F 1.12 (Sans Mono, Sans Mono Oblique) 2.21 (Sans, Sans Condensed, Sans Condensed Oblique, Sans Oblique, Serif, Serif Condensed, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.35 (Sans Bold, Sans Bold Oblique, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Mono Bold, Sans Mono Bold Oblique, Serif Bold, Serif Bold Italic, Serif Condensed Bold, Serif Condensed Bold Italic) -U+2520 uni2520 1.12 (Sans Mono, Sans Mono Oblique) 2.21 (Sans, Sans Condensed, Sans Condensed Oblique, Sans Oblique, Serif, Serif Condensed, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.35 (Sans Bold, Sans Bold Oblique, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Mono Bold, Sans Mono Bold Oblique, Serif Bold, Serif Bold Italic, Serif Condensed Bold, Serif Condensed Bold Italic) -U+2521 uni2521 1.12 (Sans Mono, Sans Mono Oblique) 2.21 (Sans, Sans Condensed, Sans Condensed Oblique, Sans Oblique, Serif, Serif Condensed, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.35 (Sans Bold, Sans Bold Oblique, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Mono Bold, Sans Mono Bold Oblique, Serif Bold, Serif Bold Italic, Serif Condensed Bold, Serif Condensed Bold Italic) -U+2522 uni2522 1.12 (Sans Mono, Sans Mono Oblique) 2.21 (Sans, Sans Condensed, Sans Condensed Oblique, Sans Oblique, Serif, Serif Condensed, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.35 (Sans Bold, Sans Bold Oblique, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Mono Bold, Sans Mono Bold Oblique, Serif Bold, Serif Bold Italic, Serif Condensed Bold, Serif Condensed Bold Italic) -U+2523 uni2523 1.12 (Sans Mono, Sans Mono Oblique) 2.21 (Sans, Sans Condensed, Sans Condensed Oblique, Sans Oblique, Serif, Serif Condensed, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.35 (Sans Bold, Sans Bold Oblique, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Mono Bold, Sans Mono Bold Oblique, Serif Bold, Serif Bold Italic, Serif Condensed Bold, Serif Condensed Bold Italic) -U+2524 SF090000 1.12 (Sans Mono, Sans Mono Oblique) 2.21 (Sans, Sans Condensed, Sans Condensed Oblique, Sans Oblique, Serif, Serif Condensed, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.35 (Sans Bold, Sans Bold Oblique, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Mono Bold, Sans Mono Bold Oblique, Serif Bold, Serif Bold Italic, Serif Condensed Bold, Serif Condensed Bold Italic) 2.36 (Math TeX Gyre Regular) -U+2525 uni2525 1.12 (Sans Mono, Sans Mono Oblique) 2.21 (Sans, Sans Condensed, Sans Condensed Oblique, Sans Oblique, Serif, Serif Condensed, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.35 (Sans Bold, Sans Bold Oblique, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Mono Bold, Sans Mono Bold Oblique, Serif Bold, Serif Bold Italic, Serif Condensed Bold, Serif Condensed Bold Italic) -U+2526 uni2526 1.12 (Sans Mono, Sans Mono Oblique) 2.21 (Sans, Sans Condensed, Sans Condensed Oblique, Sans Oblique, Serif, Serif Condensed, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.35 (Sans Bold, Sans Bold Oblique, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Mono Bold, Sans Mono Bold Oblique, Serif Bold, Serif Bold Italic, Serif Condensed Bold, Serif Condensed Bold Italic) -U+2527 uni2527 1.12 (Sans Mono, Sans Mono Oblique) 2.21 (Sans, Sans Condensed, Sans Condensed Oblique, Sans Oblique, Serif, Serif Condensed, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.35 (Sans Bold, Sans Bold Oblique, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Mono Bold, Sans Mono Bold Oblique, Serif Bold, Serif Bold Italic, Serif Condensed Bold, Serif Condensed Bold Italic) -U+2528 uni2528 1.12 (Sans Mono, Sans Mono Oblique) 2.21 (Sans, Sans Condensed, Sans Condensed Oblique, Sans Oblique, Serif, Serif Condensed, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.35 (Sans Bold, Sans Bold Oblique, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Mono Bold, Sans Mono Bold Oblique, Serif Bold, Serif Bold Italic, Serif Condensed Bold, Serif Condensed Bold Italic) -U+2529 uni2529 1.12 (Sans Mono, Sans Mono Oblique) 2.21 (Sans, Sans Condensed, Sans Condensed Oblique, Sans Oblique, Serif, Serif Condensed, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.35 (Sans Bold, Sans Bold Oblique, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Mono Bold, Sans Mono Bold Oblique, Serif Bold, Serif Bold Italic, Serif Condensed Bold, Serif Condensed Bold Italic) -U+252a uni252A 1.12 (Sans Mono, Sans Mono Oblique) 2.21 (Sans, Sans Condensed, Sans Condensed Oblique, Sans Oblique, Serif, Serif Condensed, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.35 (Sans Bold, Sans Bold Oblique, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Mono Bold, Sans Mono Bold Oblique, Serif Bold, Serif Bold Italic, Serif Condensed Bold, Serif Condensed Bold Italic) -U+252b uni252B 1.12 (Sans Mono, Sans Mono Oblique) 2.21 (Sans, Sans Condensed, Sans Condensed Oblique, Sans Oblique, Serif, Serif Condensed, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.35 (Sans Bold, Sans Bold Oblique, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Mono Bold, Sans Mono Bold Oblique, Serif Bold, Serif Bold Italic, Serif Condensed Bold, Serif Condensed Bold Italic) -U+252c SF060000 1.12 (Sans Mono, Sans Mono Oblique) 2.21 (Sans, Sans Condensed, Sans Condensed Oblique, Sans Oblique, Serif, Serif Condensed, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.35 (Sans Bold, Sans Bold Oblique, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Mono Bold, Sans Mono Bold Oblique, Serif Bold, Serif Bold Italic, Serif Condensed Bold, Serif Condensed Bold Italic) 2.36 (Math TeX Gyre Regular) -U+252d uni252D 1.12 (Sans Mono, Sans Mono Oblique) 2.21 (Sans, Sans Condensed, Sans Condensed Oblique, Sans Oblique, Serif, Serif Condensed, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.35 (Sans Bold, Sans Bold Oblique, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Mono Bold, Sans Mono Bold Oblique, Serif Bold, Serif Bold Italic, Serif Condensed Bold, Serif Condensed Bold Italic) -U+252e uni252E 1.12 (Sans Mono, Sans Mono Oblique) 2.21 (Sans, Sans Condensed, Sans Condensed Oblique, Sans Oblique, Serif, Serif Condensed, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.35 (Sans Bold, Sans Bold Oblique, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Mono Bold, Sans Mono Bold Oblique, Serif Bold, Serif Bold Italic, Serif Condensed Bold, Serif Condensed Bold Italic) -U+252f uni252F 1.12 (Sans Mono, Sans Mono Oblique) 2.21 (Sans, Sans Condensed, Sans Condensed Oblique, Sans Oblique, Serif, Serif Condensed, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.35 (Sans Bold, Sans Bold Oblique, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Mono Bold, Sans Mono Bold Oblique, Serif Bold, Serif Bold Italic, Serif Condensed Bold, Serif Condensed Bold Italic) -U+2530 uni2530 1.12 (Sans Mono, Sans Mono Oblique) 2.21 (Sans, Sans Condensed, Sans Condensed Oblique, Sans Oblique, Serif, Serif Condensed, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.35 (Sans Bold, Sans Bold Oblique, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Mono Bold, Sans Mono Bold Oblique, Serif Bold, Serif Bold Italic, Serif Condensed Bold, Serif Condensed Bold Italic) -U+2531 uni2531 1.12 (Sans Mono, Sans Mono Oblique) 2.21 (Sans, Sans Condensed, Sans Condensed Oblique, Sans Oblique, Serif, Serif Condensed, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.35 (Sans Bold, Sans Bold Oblique, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Mono Bold, Sans Mono Bold Oblique, Serif Bold, Serif Bold Italic, Serif Condensed Bold, Serif Condensed Bold Italic) -U+2532 uni2532 1.12 (Sans Mono, Sans Mono Oblique) 2.21 (Sans, Sans Condensed, Sans Condensed Oblique, Sans Oblique, Serif, Serif Condensed, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.35 (Sans Bold, Sans Bold Oblique, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Mono Bold, Sans Mono Bold Oblique, Serif Bold, Serif Bold Italic, Serif Condensed Bold, Serif Condensed Bold Italic) -U+2533 uni2533 1.12 (Sans Mono, Sans Mono Oblique) 2.21 (Sans, Sans Condensed, Sans Condensed Oblique, Sans Oblique, Serif, Serif Condensed, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.35 (Sans Bold, Sans Bold Oblique, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Mono Bold, Sans Mono Bold Oblique, Serif Bold, Serif Bold Italic, Serif Condensed Bold, Serif Condensed Bold Italic) -U+2534 SF070000 1.12 (Sans Mono, Sans Mono Oblique) 2.21 (Sans, Sans Condensed, Sans Condensed Oblique, Sans Oblique, Serif, Serif Condensed, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.35 (Sans Bold, Sans Bold Oblique, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Mono Bold, Sans Mono Bold Oblique, Serif Bold, Serif Bold Italic, Serif Condensed Bold, Serif Condensed Bold Italic) 2.36 (Math TeX Gyre Regular) -U+2535 uni2535 1.12 (Sans Mono, Sans Mono Oblique) 2.21 (Sans, Sans Condensed, Sans Condensed Oblique, Sans Oblique, Serif, Serif Condensed, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.35 (Sans Bold, Sans Bold Oblique, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Mono Bold, Sans Mono Bold Oblique, Serif Bold, Serif Bold Italic, Serif Condensed Bold, Serif Condensed Bold Italic) -U+2536 uni2536 1.12 (Sans Mono, Sans Mono Oblique) 2.21 (Sans, Sans Condensed, Sans Condensed Oblique, Sans Oblique, Serif, Serif Condensed, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.35 (Sans Bold, Sans Bold Oblique, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Mono Bold, Sans Mono Bold Oblique, Serif Bold, Serif Bold Italic, Serif Condensed Bold, Serif Condensed Bold Italic) -U+2537 uni2537 1.12 (Sans Mono, Sans Mono Oblique) 2.21 (Sans, Sans Condensed, Sans Condensed Oblique, Sans Oblique, Serif, Serif Condensed, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.35 (Sans Bold, Sans Bold Oblique, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Mono Bold, Sans Mono Bold Oblique, Serif Bold, Serif Bold Italic, Serif Condensed Bold, Serif Condensed Bold Italic) -U+2538 uni2538 1.12 (Sans Mono, Sans Mono Oblique) 2.21 (Sans, Sans Condensed, Sans Condensed Oblique, Sans Oblique, Serif, Serif Condensed, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.35 (Sans Bold, Sans Bold Oblique, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Mono Bold, Sans Mono Bold Oblique, Serif Bold, Serif Bold Italic, Serif Condensed Bold, Serif Condensed Bold Italic) -U+2539 uni2539 1.12 (Sans Mono, Sans Mono Oblique) 2.21 (Sans, Sans Condensed, Sans Condensed Oblique, Sans Oblique, Serif, Serif Condensed, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.35 (Sans Bold, Sans Bold Oblique, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Mono Bold, Sans Mono Bold Oblique, Serif Bold, Serif Bold Italic, Serif Condensed Bold, Serif Condensed Bold Italic) -U+253a uni253A 1.12 (Sans Mono, Sans Mono Oblique) 2.21 (Sans, Sans Condensed, Sans Condensed Oblique, Sans Oblique, Serif, Serif Condensed, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.35 (Sans Bold, Sans Bold Oblique, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Mono Bold, Sans Mono Bold Oblique, Serif Bold, Serif Bold Italic, Serif Condensed Bold, Serif Condensed Bold Italic) -U+253b uni253B 1.12 (Sans Mono, Sans Mono Oblique) 2.21 (Sans, Sans Condensed, Sans Condensed Oblique, Sans Oblique, Serif, Serif Condensed, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.35 (Sans Bold, Sans Bold Oblique, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Mono Bold, Sans Mono Bold Oblique, Serif Bold, Serif Bold Italic, Serif Condensed Bold, Serif Condensed Bold Italic) -U+253c SF050000 1.12 (Sans Mono, Sans Mono Oblique) 2.21 (Sans, Sans Condensed, Sans Condensed Oblique, Sans Oblique, Serif, Serif Condensed, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.35 (Sans Bold, Sans Bold Oblique, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Mono Bold, Sans Mono Bold Oblique, Serif Bold, Serif Bold Italic, Serif Condensed Bold, Serif Condensed Bold Italic) 2.36 (Math TeX Gyre Regular) -U+253d uni253D 1.12 (Sans Mono, Sans Mono Oblique) 2.21 (Sans, Sans Condensed, Sans Condensed Oblique, Sans Oblique, Serif, Serif Condensed, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.35 (Sans Bold, Sans Bold Oblique, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Mono Bold, Sans Mono Bold Oblique, Serif Bold, Serif Bold Italic, Serif Condensed Bold, Serif Condensed Bold Italic) -U+253e uni253E 1.12 (Sans Mono, Sans Mono Oblique) 2.21 (Sans, Sans Condensed, Sans Condensed Oblique, Sans Oblique, Serif, Serif Condensed, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.35 (Sans Bold, Sans Bold Oblique, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Mono Bold, Sans Mono Bold Oblique, Serif Bold, Serif Bold Italic, Serif Condensed Bold, Serif Condensed Bold Italic) -U+253f uni253F 1.12 (Sans Mono, Sans Mono Oblique) 2.21 (Sans, Sans Condensed, Sans Condensed Oblique, Sans Oblique, Serif, Serif Condensed, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.35 (Sans Bold, Sans Bold Oblique, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Mono Bold, Sans Mono Bold Oblique, Serif Bold, Serif Bold Italic, Serif Condensed Bold, Serif Condensed Bold Italic) -U+2540 uni2540 1.12 (Sans Mono, Sans Mono Oblique) 2.21 (Sans, Sans Condensed, Sans Condensed Oblique, Sans Oblique, Serif, Serif Condensed, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.35 (Sans Bold, Sans Bold Oblique, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Mono Bold, Sans Mono Bold Oblique, Serif Bold, Serif Bold Italic, Serif Condensed Bold, Serif Condensed Bold Italic) -U+2541 uni2541 1.12 (Sans Mono, Sans Mono Oblique) 2.21 (Sans, Sans Condensed, Sans Condensed Oblique, Sans Oblique, Serif, Serif Condensed, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.35 (Sans Bold, Sans Bold Oblique, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Mono Bold, Sans Mono Bold Oblique, Serif Bold, Serif Bold Italic, Serif Condensed Bold, Serif Condensed Bold Italic) -U+2542 uni2542 1.12 (Sans Mono, Sans Mono Oblique) 2.21 (Sans, Sans Condensed, Sans Condensed Oblique, Sans Oblique, Serif, Serif Condensed, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.35 (Sans Bold, Sans Bold Oblique, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Mono Bold, Sans Mono Bold Oblique, Serif Bold, Serif Bold Italic, Serif Condensed Bold, Serif Condensed Bold Italic) -U+2543 uni2543 1.12 (Sans Mono, Sans Mono Oblique) 2.21 (Sans, Sans Condensed, Sans Condensed Oblique, Sans Oblique, Serif, Serif Condensed, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.35 (Sans Bold, Sans Bold Oblique, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Mono Bold, Sans Mono Bold Oblique, Serif Bold, Serif Bold Italic, Serif Condensed Bold, Serif Condensed Bold Italic) -U+2544 uni2544 1.12 (Sans Mono, Sans Mono Oblique) 2.21 (Sans, Sans Condensed, Sans Condensed Oblique, Sans Oblique, Serif, Serif Condensed, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.35 (Sans Bold, Sans Bold Oblique, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Mono Bold, Sans Mono Bold Oblique, Serif Bold, Serif Bold Italic, Serif Condensed Bold, Serif Condensed Bold Italic) -U+2545 uni2545 1.12 (Sans Mono, Sans Mono Oblique) 2.21 (Sans, Sans Condensed, Sans Condensed Oblique, Sans Oblique, Serif, Serif Condensed, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.35 (Sans Bold, Sans Bold Oblique, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Mono Bold, Sans Mono Bold Oblique, Serif Bold, Serif Bold Italic, Serif Condensed Bold, Serif Condensed Bold Italic) -U+2546 uni2546 1.12 (Sans Mono, Sans Mono Oblique) 2.21 (Sans, Sans Condensed, Sans Condensed Oblique, Sans Oblique, Serif, Serif Condensed, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.35 (Sans Bold, Sans Bold Oblique, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Mono Bold, Sans Mono Bold Oblique, Serif Bold, Serif Bold Italic, Serif Condensed Bold, Serif Condensed Bold Italic) -U+2547 uni2547 1.12 (Sans Mono, Sans Mono Oblique) 2.21 (Sans, Sans Condensed, Sans Condensed Oblique, Sans Oblique, Serif, Serif Condensed, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.35 (Sans Bold, Sans Bold Oblique, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Mono Bold, Sans Mono Bold Oblique, Serif Bold, Serif Bold Italic, Serif Condensed Bold, Serif Condensed Bold Italic) -U+2548 uni2548 1.12 (Sans Mono, Sans Mono Oblique) 2.21 (Sans, Sans Condensed, Sans Condensed Oblique, Sans Oblique, Serif, Serif Condensed, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.35 (Sans Bold, Sans Bold Oblique, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Mono Bold, Sans Mono Bold Oblique, Serif Bold, Serif Bold Italic, Serif Condensed Bold, Serif Condensed Bold Italic) -U+2549 uni2549 1.12 (Sans Mono, Sans Mono Oblique) 2.21 (Sans, Sans Condensed, Sans Condensed Oblique, Sans Oblique, Serif, Serif Condensed, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.35 (Sans Bold, Sans Bold Oblique, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Mono Bold, Sans Mono Bold Oblique, Serif Bold, Serif Bold Italic, Serif Condensed Bold, Serif Condensed Bold Italic) -U+254a uni254A 1.12 (Sans Mono, Sans Mono Oblique) 2.21 (Sans, Sans Condensed, Sans Condensed Oblique, Sans Oblique, Serif, Serif Condensed, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.35 (Sans Bold, Sans Bold Oblique, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Mono Bold, Sans Mono Bold Oblique, Serif Bold, Serif Bold Italic, Serif Condensed Bold, Serif Condensed Bold Italic) -U+254b uni254B 1.12 (Sans Mono, Sans Mono Oblique) 2.21 (Sans, Sans Condensed, Sans Condensed Oblique, Sans Oblique, Serif, Serif Condensed, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.35 (Sans Bold, Sans Bold Oblique, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Mono Bold, Sans Mono Bold Oblique, Serif Bold, Serif Bold Italic, Serif Condensed Bold, Serif Condensed Bold Italic) -U+254c uni254C 1.12 (Sans Mono, Sans Mono Oblique) 2.21 (Sans, Sans Condensed, Sans Condensed Oblique, Sans Oblique, Serif, Serif Condensed, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.35 (Sans Bold, Sans Bold Oblique, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Mono Bold, Sans Mono Bold Oblique, Serif Bold, Serif Bold Italic, Serif Condensed Bold, Serif Condensed Bold Italic) -U+254d uni254D 1.12 (Sans Mono, Sans Mono Oblique) 2.21 (Sans, Sans Condensed, Sans Condensed Oblique, Sans Oblique, Serif, Serif Condensed, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.35 (Sans Bold, Sans Bold Oblique, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Mono Bold, Sans Mono Bold Oblique, Serif Bold, Serif Bold Italic, Serif Condensed Bold, Serif Condensed Bold Italic) -U+254e uni254E 1.12 (Sans Mono, Sans Mono Oblique) 2.21 (Sans, Sans Condensed, Sans Condensed Oblique, Sans Oblique, Serif, Serif Condensed, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.35 (Sans Bold, Sans Bold Oblique, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Mono Bold, Sans Mono Bold Oblique, Serif Bold, Serif Bold Italic, Serif Condensed Bold, Serif Condensed Bold Italic) -U+254f uni254F 1.12 (Sans Mono, Sans Mono Oblique) 2.21 (Sans, Sans Condensed, Sans Condensed Oblique, Sans Oblique, Serif, Serif Condensed, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.35 (Sans Bold, Sans Bold Oblique, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Mono Bold, Sans Mono Bold Oblique, Serif Bold, Serif Bold Italic, Serif Condensed Bold, Serif Condensed Bold Italic) -U+2550 SF430000 1.12 (Sans Mono, Sans Mono Oblique) 2.21 (Sans, Sans Condensed, Sans Condensed Oblique, Sans Oblique, Serif, Serif Condensed, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.35 (Sans Bold, Sans Bold Oblique, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Mono Bold, Sans Mono Bold Oblique, Serif Bold, Serif Bold Italic, Serif Condensed Bold, Serif Condensed Bold Italic) -U+2551 SF240000 1.12 (Sans Mono, Sans Mono Oblique) 2.21 (Sans, Sans Condensed, Sans Condensed Oblique, Sans Oblique, Serif, Serif Condensed, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.35 (Sans Bold, Sans Bold Oblique, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Mono Bold, Sans Mono Bold Oblique, Serif Bold, Serif Bold Italic, Serif Condensed Bold, Serif Condensed Bold Italic) -U+2552 SF510000 1.12 (Sans Mono, Sans Mono Oblique) 2.21 (Sans, Sans Condensed, Sans Condensed Oblique, Sans Oblique, Serif, Serif Condensed, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.35 (Sans Bold, Sans Bold Oblique, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Mono Bold, Sans Mono Bold Oblique, Serif Bold, Serif Bold Italic, Serif Condensed Bold, Serif Condensed Bold Italic) -U+2553 SF520000 1.12 (Sans Mono, Sans Mono Oblique) 2.21 (Sans, Sans Condensed, Sans Condensed Oblique, Sans Oblique, Serif, Serif Condensed, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.35 (Sans Bold, Sans Bold Oblique, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Mono Bold, Sans Mono Bold Oblique, Serif Bold, Serif Bold Italic, Serif Condensed Bold, Serif Condensed Bold Italic) -U+2554 SF390000 1.12 (Sans Mono, Sans Mono Oblique) 2.21 (Sans, Sans Condensed, Sans Condensed Oblique, Sans Oblique, Serif, Serif Condensed, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.35 (Sans Bold, Sans Bold Oblique, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Mono Bold, Sans Mono Bold Oblique, Serif Bold, Serif Bold Italic, Serif Condensed Bold, Serif Condensed Bold Italic) -U+2555 SF220000 1.12 (Sans Mono, Sans Mono Oblique) 2.21 (Sans, Sans Condensed, Sans Condensed Oblique, Sans Oblique, Serif, Serif Condensed, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.35 (Sans Bold, Sans Bold Oblique, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Mono Bold, Sans Mono Bold Oblique, Serif Bold, Serif Bold Italic, Serif Condensed Bold, Serif Condensed Bold Italic) -U+2556 SF210000 1.12 (Sans Mono, Sans Mono Oblique) 2.21 (Sans, Sans Condensed, Sans Condensed Oblique, Sans Oblique, Serif, Serif Condensed, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.35 (Sans Bold, Sans Bold Oblique, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Mono Bold, Sans Mono Bold Oblique, Serif Bold, Serif Bold Italic, Serif Condensed Bold, Serif Condensed Bold Italic) -U+2557 SF250000 1.12 (Sans Mono, Sans Mono Oblique) 2.21 (Sans, Sans Condensed, Sans Condensed Oblique, Sans Oblique, Serif, Serif Condensed, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.35 (Sans Bold, Sans Bold Oblique, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Mono Bold, Sans Mono Bold Oblique, Serif Bold, Serif Bold Italic, Serif Condensed Bold, Serif Condensed Bold Italic) -U+2558 SF500000 1.12 (Sans Mono, Sans Mono Oblique) 2.21 (Sans, Sans Condensed, Sans Condensed Oblique, Sans Oblique, Serif, Serif Condensed, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.35 (Sans Bold, Sans Bold Oblique, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Mono Bold, Sans Mono Bold Oblique, Serif Bold, Serif Bold Italic, Serif Condensed Bold, Serif Condensed Bold Italic) -U+2559 SF490000 1.12 (Sans Mono, Sans Mono Oblique) 2.21 (Sans, Sans Condensed, Sans Condensed Oblique, Sans Oblique, Serif, Serif Condensed, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.35 (Sans Bold, Sans Bold Oblique, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Mono Bold, Sans Mono Bold Oblique, Serif Bold, Serif Bold Italic, Serif Condensed Bold, Serif Condensed Bold Italic) -U+255a SF380000 1.12 (Sans Mono, Sans Mono Oblique) 2.21 (Sans, Sans Condensed, Sans Condensed Oblique, Sans Oblique, Serif, Serif Condensed, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.35 (Sans Bold, Sans Bold Oblique, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Mono Bold, Sans Mono Bold Oblique, Serif Bold, Serif Bold Italic, Serif Condensed Bold, Serif Condensed Bold Italic) -U+255b SF280000 1.12 (Sans Mono, Sans Mono Oblique) 2.21 (Sans, Sans Condensed, Sans Condensed Oblique, Sans Oblique, Serif, Serif Condensed, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.35 (Sans Bold, Sans Bold Oblique, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Mono Bold, Sans Mono Bold Oblique, Serif Bold, Serif Bold Italic, Serif Condensed Bold, Serif Condensed Bold Italic) -U+255c SF270000 1.12 (Sans Mono, Sans Mono Oblique) 2.21 (Sans, Sans Condensed, Sans Condensed Oblique, Sans Oblique, Serif, Serif Condensed, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.35 (Sans Bold, Sans Bold Oblique, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Mono Bold, Sans Mono Bold Oblique, Serif Bold, Serif Bold Italic, Serif Condensed Bold, Serif Condensed Bold Italic) -U+255d SF260000 1.12 (Sans Mono, Sans Mono Oblique) 2.21 (Sans, Sans Condensed, Sans Condensed Oblique, Sans Oblique, Serif, Serif Condensed, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.35 (Sans Bold, Sans Bold Oblique, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Mono Bold, Sans Mono Bold Oblique, Serif Bold, Serif Bold Italic, Serif Condensed Bold, Serif Condensed Bold Italic) -U+255e SF360000 1.12 (Sans Mono, Sans Mono Oblique) 2.21 (Sans, Sans Condensed, Sans Condensed Oblique, Sans Oblique, Serif, Serif Condensed, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.35 (Sans Bold, Sans Bold Oblique, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Mono Bold, Sans Mono Bold Oblique, Serif Bold, Serif Bold Italic, Serif Condensed Bold, Serif Condensed Bold Italic) -U+255f SF370000 1.12 (Sans Mono, Sans Mono Oblique) 2.21 (Sans, Sans Condensed, Sans Condensed Oblique, Sans Oblique, Serif, Serif Condensed, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.35 (Sans Bold, Sans Bold Oblique, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Mono Bold, Sans Mono Bold Oblique, Serif Bold, Serif Bold Italic, Serif Condensed Bold, Serif Condensed Bold Italic) -U+2560 SF420000 1.12 (Sans Mono, Sans Mono Oblique) 2.21 (Sans, Sans Condensed, Sans Condensed Oblique, Sans Oblique, Serif, Serif Condensed, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.35 (Sans Bold, Sans Bold Oblique, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Mono Bold, Sans Mono Bold Oblique, Serif Bold, Serif Bold Italic, Serif Condensed Bold, Serif Condensed Bold Italic) -U+2561 SF190000 1.12 (Sans Mono, Sans Mono Oblique) 2.21 (Sans, Sans Condensed, Sans Condensed Oblique, Sans Oblique, Serif, Serif Condensed, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.35 (Sans Bold, Sans Bold Oblique, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Mono Bold, Sans Mono Bold Oblique, Serif Bold, Serif Bold Italic, Serif Condensed Bold, Serif Condensed Bold Italic) -U+2562 SF200000 1.12 (Sans Mono, Sans Mono Oblique) 2.21 (Sans, Sans Condensed, Sans Condensed Oblique, Sans Oblique, Serif, Serif Condensed, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.35 (Sans Bold, Sans Bold Oblique, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Mono Bold, Sans Mono Bold Oblique, Serif Bold, Serif Bold Italic, Serif Condensed Bold, Serif Condensed Bold Italic) -U+2563 SF230000 1.12 (Sans Mono, Sans Mono Oblique) 2.21 (Sans, Sans Condensed, Sans Condensed Oblique, Sans Oblique, Serif, Serif Condensed, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.35 (Sans Bold, Sans Bold Oblique, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Mono Bold, Sans Mono Bold Oblique, Serif Bold, Serif Bold Italic, Serif Condensed Bold, Serif Condensed Bold Italic) -U+2564 SF470000 1.12 (Sans Mono, Sans Mono Oblique) 2.21 (Sans, Sans Condensed, Sans Condensed Oblique, Sans Oblique, Serif, Serif Condensed, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.35 (Sans Bold, Sans Bold Oblique, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Mono Bold, Sans Mono Bold Oblique, Serif Bold, Serif Bold Italic, Serif Condensed Bold, Serif Condensed Bold Italic) -U+2565 SF480000 1.12 (Sans Mono, Sans Mono Oblique) 2.21 (Sans, Sans Condensed, Sans Condensed Oblique, Sans Oblique, Serif, Serif Condensed, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.35 (Sans Bold, Sans Bold Oblique, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Mono Bold, Sans Mono Bold Oblique, Serif Bold, Serif Bold Italic, Serif Condensed Bold, Serif Condensed Bold Italic) -U+2566 SF410000 1.12 (Sans Mono, Sans Mono Oblique) 2.21 (Sans, Sans Condensed, Sans Condensed Oblique, Sans Oblique, Serif, Serif Condensed, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.35 (Sans Bold, Sans Bold Oblique, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Mono Bold, Sans Mono Bold Oblique, Serif Bold, Serif Bold Italic, Serif Condensed Bold, Serif Condensed Bold Italic) -U+2567 SF450000 1.12 (Sans Mono, Sans Mono Oblique) 2.21 (Sans, Sans Condensed, Sans Condensed Oblique, Sans Oblique, Serif, Serif Condensed, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.35 (Sans Bold, Sans Bold Oblique, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Mono Bold, Sans Mono Bold Oblique, Serif Bold, Serif Bold Italic, Serif Condensed Bold, Serif Condensed Bold Italic) -U+2568 SF460000 1.12 (Sans Mono, Sans Mono Oblique) 2.21 (Sans, Sans Condensed, Sans Condensed Oblique, Sans Oblique, Serif, Serif Condensed, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.35 (Sans Bold, Sans Bold Oblique, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Mono Bold, Sans Mono Bold Oblique, Serif Bold, Serif Bold Italic, Serif Condensed Bold, Serif Condensed Bold Italic) -U+2569 SF400000 1.12 (Sans Mono, Sans Mono Oblique) 2.21 (Sans, Sans Condensed, Sans Condensed Oblique, Sans Oblique, Serif, Serif Condensed, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.35 (Sans Bold, Sans Bold Oblique, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Mono Bold, Sans Mono Bold Oblique, Serif Bold, Serif Bold Italic, Serif Condensed Bold, Serif Condensed Bold Italic) -U+256a SF540000 1.12 (Sans Mono, Sans Mono Oblique) 2.21 (Sans, Sans Condensed, Sans Condensed Oblique, Sans Oblique, Serif, Serif Condensed, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.35 (Sans Bold, Sans Bold Oblique, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Mono Bold, Sans Mono Bold Oblique, Serif Bold, Serif Bold Italic, Serif Condensed Bold, Serif Condensed Bold Italic) -U+256b SF530000 1.12 (Sans Mono, Sans Mono Oblique) 2.21 (Sans, Sans Condensed, Sans Condensed Oblique, Sans Oblique, Serif, Serif Condensed, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.35 (Sans Bold, Sans Bold Oblique, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Mono Bold, Sans Mono Bold Oblique, Serif Bold, Serif Bold Italic, Serif Condensed Bold, Serif Condensed Bold Italic) -U+256c SF440000 1.12 (Sans Mono, Sans Mono Oblique) 2.21 (Sans, Sans Condensed, Sans Condensed Oblique, Sans Oblique, Serif, Serif Condensed, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.35 (Sans Bold, Sans Bold Oblique, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Mono Bold, Sans Mono Bold Oblique, Serif Bold, Serif Bold Italic, Serif Condensed Bold, Serif Condensed Bold Italic) -U+256d uni256D 1.12 (Sans Mono, Sans Mono Oblique) 2.21 (Sans, Sans Condensed, Sans Condensed Oblique, Sans Oblique, Serif, Serif Condensed, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.35 (Sans Bold, Sans Bold Oblique, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Mono Bold, Sans Mono Bold Oblique, Serif Bold, Serif Bold Italic, Serif Condensed Bold, Serif Condensed Bold Italic) -U+256e uni256E 1.12 (Sans Mono, Sans Mono Oblique) 2.21 (Sans, Sans Condensed, Sans Condensed Oblique, Sans Oblique, Serif, Serif Condensed, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.35 (Sans Bold, Sans Bold Oblique, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Mono Bold, Sans Mono Bold Oblique, Serif Bold, Serif Bold Italic, Serif Condensed Bold, Serif Condensed Bold Italic) -U+256f uni256F 1.12 (Sans Mono, Sans Mono Oblique) 2.21 (Sans, Sans Condensed, Sans Condensed Oblique, Sans Oblique, Serif, Serif Condensed, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.35 (Sans Bold, Sans Bold Oblique, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Mono Bold, Sans Mono Bold Oblique, Serif Bold, Serif Bold Italic, Serif Condensed Bold, Serif Condensed Bold Italic) -U+2570 uni2570 1.12 (Sans Mono, Sans Mono Oblique) 2.21 (Sans, Sans Condensed, Sans Condensed Oblique, Sans Oblique, Serif, Serif Condensed, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.35 (Sans Bold, Sans Bold Oblique, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Mono Bold, Sans Mono Bold Oblique, Serif Bold, Serif Bold Italic, Serif Condensed Bold, Serif Condensed Bold Italic) -U+2571 uni2571 1.12 (Sans Mono, Sans Mono Oblique) 2.21 (Sans, Sans Condensed, Sans Condensed Oblique, Sans Oblique, Serif, Serif Condensed, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.35 (Sans Bold, Sans Bold Oblique, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Mono Bold, Sans Mono Bold Oblique, Serif Bold, Serif Bold Italic, Serif Condensed Bold, Serif Condensed Bold Italic) -U+2572 uni2572 1.12 (Sans Mono, Sans Mono Oblique) 2.21 (Sans, Sans Condensed, Sans Condensed Oblique, Sans Oblique, Serif, Serif Condensed, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.35 (Sans Bold, Sans Bold Oblique, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Mono Bold, Sans Mono Bold Oblique, Serif Bold, Serif Bold Italic, Serif Condensed Bold, Serif Condensed Bold Italic) -U+2573 uni2573 1.12 (Sans Mono, Sans Mono Oblique) 2.21 (Sans, Sans Condensed, Sans Condensed Oblique, Sans Oblique, Serif, Serif Condensed, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.35 (Sans Bold, Sans Bold Oblique, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Mono Bold, Sans Mono Bold Oblique, Serif Bold, Serif Bold Italic, Serif Condensed Bold, Serif Condensed Bold Italic) -U+2574 uni2574 1.12 (Sans Mono, Sans Mono Oblique) 2.21 (Sans, Sans Condensed, Sans Condensed Oblique, Sans Oblique, Serif, Serif Condensed, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.35 (Sans Bold, Sans Bold Oblique, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Mono Bold, Sans Mono Bold Oblique, Serif Bold, Serif Bold Italic, Serif Condensed Bold, Serif Condensed Bold Italic) -U+2575 uni2575 1.12 (Sans Mono, Sans Mono Oblique) 2.21 (Sans, Sans Condensed, Sans Condensed Oblique, Sans Oblique, Serif, Serif Condensed, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.35 (Sans Bold, Sans Bold Oblique, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Mono Bold, Sans Mono Bold Oblique, Serif Bold, Serif Bold Italic, Serif Condensed Bold, Serif Condensed Bold Italic) -U+2576 uni2576 1.12 (Sans Mono, Sans Mono Oblique) 2.21 (Sans, Sans Condensed, Sans Condensed Oblique, Sans Oblique, Serif, Serif Condensed, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.35 (Sans Bold, Sans Bold Oblique, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Mono Bold, Sans Mono Bold Oblique, Serif Bold, Serif Bold Italic, Serif Condensed Bold, Serif Condensed Bold Italic) -U+2577 uni2577 1.12 (Sans Mono, Sans Mono Oblique) 2.21 (Sans, Sans Condensed, Sans Condensed Oblique, Sans Oblique, Serif, Serif Condensed, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.35 (Sans Bold, Sans Bold Oblique, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Mono Bold, Sans Mono Bold Oblique, Serif Bold, Serif Bold Italic, Serif Condensed Bold, Serif Condensed Bold Italic) -U+2578 uni2578 1.12 (Sans Mono, Sans Mono Oblique) 2.21 (Sans, Sans Condensed, Sans Condensed Oblique, Sans Oblique, Serif, Serif Condensed, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.35 (Sans Bold, Sans Bold Oblique, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Mono Bold, Sans Mono Bold Oblique, Serif Bold, Serif Bold Italic, Serif Condensed Bold, Serif Condensed Bold Italic) -U+2579 uni2579 1.12 (Sans Mono, Sans Mono Oblique) 2.21 (Sans, Sans Condensed, Sans Condensed Oblique, Sans Oblique, Serif, Serif Condensed, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.35 (Sans Bold, Sans Bold Oblique, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Mono Bold, Sans Mono Bold Oblique, Serif Bold, Serif Bold Italic, Serif Condensed Bold, Serif Condensed Bold Italic) -U+257a uni257A 1.12 (Sans Mono, Sans Mono Oblique) 2.21 (Sans, Sans Condensed, Sans Condensed Oblique, Sans Oblique, Serif, Serif Condensed, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.35 (Sans Bold, Sans Bold Oblique, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Mono Bold, Sans Mono Bold Oblique, Serif Bold, Serif Bold Italic, Serif Condensed Bold, Serif Condensed Bold Italic) -U+257b uni257B 1.12 (Sans Mono, Sans Mono Oblique) 2.21 (Sans, Sans Condensed, Sans Condensed Oblique, Sans Oblique, Serif, Serif Condensed, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.35 (Sans Bold, Sans Bold Oblique, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Mono Bold, Sans Mono Bold Oblique, Serif Bold, Serif Bold Italic, Serif Condensed Bold, Serif Condensed Bold Italic) -U+257c uni257C 1.12 (Sans Mono, Sans Mono Oblique) 2.21 (Sans, Sans Condensed, Sans Condensed Oblique, Sans Oblique, Serif, Serif Condensed, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.35 (Sans Bold, Sans Bold Oblique, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Mono Bold, Sans Mono Bold Oblique, Serif Bold, Serif Bold Italic, Serif Condensed Bold, Serif Condensed Bold Italic) -U+257d uni257D 1.12 (Sans Mono, Sans Mono Oblique) 2.21 (Sans, Sans Condensed, Sans Condensed Oblique, Sans Oblique, Serif, Serif Condensed, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.35 (Sans Bold, Sans Bold Oblique, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Mono Bold, Sans Mono Bold Oblique, Serif Bold, Serif Bold Italic, Serif Condensed Bold, Serif Condensed Bold Italic) -U+257e uni257E 1.12 (Sans Mono, Sans Mono Oblique) 2.21 (Sans, Sans Condensed, Sans Condensed Oblique, Sans Oblique, Serif, Serif Condensed, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.35 (Sans Bold, Sans Bold Oblique, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Mono Bold, Sans Mono Bold Oblique, Serif Bold, Serif Bold Italic, Serif Condensed Bold, Serif Condensed Bold Italic) -U+257f uni257F 1.12 (Sans Mono, Sans Mono Oblique) 2.21 (Sans, Sans Condensed, Sans Condensed Oblique, Sans Oblique, Serif, Serif Condensed, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.35 (Sans Bold, Sans Bold Oblique, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Mono Bold, Sans Mono Bold Oblique, Serif Bold, Serif Bold Italic, Serif Condensed Bold, Serif Condensed Bold Italic) -U+2580 upblock 1.14 -U+2581 uni2581 1.14 -U+2582 uni2582 1.14 -U+2583 uni2583 1.14 -U+2584 dnblock 1.14 -U+2585 uni2585 1.14 -U+2586 uni2586 1.14 -U+2587 uni2587 1.14 -U+2588 block 1.14 -U+2589 uni2589 1.14 -U+258a uni258A 1.14 -U+258b uni258B 1.14 -U+258c lfblock 1.14 -U+258d uni258D 1.14 -U+258e uni258E 1.14 -U+258f uni258F 1.14 -U+2590 rtblock 1.14 -U+2591 ltshade 1.15 -U+2592 shade 1.15 -U+2593 dkshade 1.15 -U+2594 uni2594 1.14 -U+2595 uni2595 1.14 -U+2596 uni2596 1.14 -U+2597 uni2597 1.14 -U+2598 uni2598 1.14 -U+2599 uni2599 1.14 -U+259a uni259A 1.14 -U+259b uni259B 1.14 -U+259c uni259C 1.14 -U+259d uni259D 1.14 -U+259e uni259E 1.14 -U+259f uni259F 1.14 -U+25a0 filledbox 2.3 -U+25a1 H22073 2.3 -U+25a2 uni25A2 2.3 -U+25a3 uni25A3 2.3 -U+25a4 uni25A4 2.3 -U+25a5 uni25A5 2.3 -U+25a6 uni25A6 2.3 -U+25a7 uni25A7 2.3 -U+25a8 uni25A8 2.3 -U+25a9 uni25A9 2.3 -U+25aa H18543 2.3 -U+25ab H18551 2.3 -U+25ac filledrect 2.3 -U+25ad uni25AD 2.3 -U+25ae uni25AE 2.3 -U+25af uni25AF 2.3 -U+25b0 uni25B0 2.3 -U+25b1 uni25B1 2.3 -U+25b2 triagup 2.3 -U+25b3 uni25B3 2.3 -U+25b4 uni25B4 2.3 -U+25b5 uni25B5 2.3 -U+25b6 uni25B6 2.3 -U+25b7 uni25B7 2.3 -U+25b8 uni25B8 2.3 -U+25b9 uni25B9 2.3 -U+25ba triagrt 2.3 -U+25bb uni25BB 2.3 -U+25bc triagdn 2.3 -U+25bd uni25BD 2.3 -U+25be uni25BE 2.3 -U+25bf uni25BF 2.3 -U+25c0 uni25C0 2.3 -U+25c1 uni25C1 2.3 -U+25c2 uni25C2 2.3 -U+25c3 uni25C3 2.3 -U+25c4 triaglf 2.3 -U+25c5 uni25C5 2.3 -U+25c6 uni25C6 2.3 -U+25c7 uni25C7 2.3 -U+25c8 uni25C8 2.3 -U+25c9 uni25C9 2.3 -U+25ca lozenge original -U+25cb circle 2.3 -U+25cc uni25CC 2.3 -U+25cd uni25CD 2.3 -U+25ce uni25CE 2.3 -U+25cf H18533 2.3 -U+25d0 uni25D0 2.3 -U+25d1 uni25D1 2.3 -U+25d2 uni25D2 2.3 -U+25d3 uni25D3 2.3 -U+25d4 uni25D4 2.3 -U+25d5 uni25D5 2.3 -U+25d6 uni25D6 2.3 -U+25d7 uni25D7 2.3 -U+25d8 invbullet 2.2 -U+25d9 invcircle 2.3 -U+25da uni25DA 2.3 -U+25db uni25DB 2.3 -U+25dc uni25DC 2.3 -U+25dd uni25DD 2.3 -U+25de uni25DE 2.3 -U+25df uni25DF 2.3 -U+25e0 uni25E0 2.3 -U+25e1 uni25E1 2.3 -U+25e2 uni25E2 2.3 -U+25e3 uni25E3 2.3 -U+25e4 uni25E4 2.3 -U+25e5 uni25E5 2.3 -U+25e6 openbullet 2.2 -U+25e7 uni25E7 2.3 -U+25e8 uni25E8 2.3 -U+25e9 uni25E9 2.3 -U+25ea uni25EA 2.3 -U+25eb uni25EB 2.3 -U+25ec uni25EC 2.3 -U+25ed uni25ED 2.3 -U+25ee uni25EE 2.3 -U+25ef uni25EF 2.3 -U+25f0 uni25F0 2.3 -U+25f1 uni25F1 2.3 -U+25f2 uni25F2 2.3 -U+25f3 uni25F3 2.3 -U+25f4 uni25F4 2.3 -U+25f5 uni25F5 2.3 -U+25f6 uni25F6 2.3 -U+25f7 uni25F7 2.3 -U+25f8 uni25F8 2.3 -U+25f9 uni25F9 2.3 -U+25fa uni25FA 2.3 -U+25fb uni25FB 2.3 -U+25fc uni25FC 2.3 -U+25fd uni25FD 2.3 -U+25fe uni25FE 2.3 -U+25ff uni25FF 2.3 -U+2600 uni2600 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+2601 uni2601 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) 2.7 (Sans Mono, Sans Mono Bold) -U+2602 uni2602 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) 2.7 (Sans Mono, Sans Mono Bold) -U+2603 uni2603 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) 2.7 (Sans Mono, Sans Mono Bold) -U+2604 uni2604 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) 2.7 (Sans Mono, Sans Mono Bold) -U+2605 uni2605 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) 2.7 (Sans Mono, Sans Mono Bold) -U+2606 uni2606 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) 2.7 (Sans Mono, Sans Mono Bold) -U+2607 uni2607 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) 2.7 (Sans Mono, Sans Mono Bold) -U+2608 uni2608 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) 2.7 (Sans Mono, Sans Mono Bold) -U+2609 uni2609 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) 2.7 (Sans Mono, Sans Mono Bold) -U+260a uni260A 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) 2.7 (Sans Mono, Sans Mono Bold) -U+260b uni260B 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) 2.7 (Sans Mono, Sans Mono Bold) -U+260c uni260C 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) 2.7 (Sans Mono, Sans Mono Bold) -U+260d uni260D 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) 2.7 (Sans Mono, Sans Mono Bold) -U+260e uni260E 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) 2.7 (Sans Mono, Sans Mono Bold) -U+260f uni260F 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) 2.7 (Sans Mono, Sans Mono Bold) -U+2610 uni2610 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) 2.7 (Sans Mono, Sans Mono Bold) -U+2611 uni2611 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) 2.7 (Sans Mono, Sans Mono Bold) -U+2612 uni2612 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) 2.7 (Sans Mono, Sans Mono Bold) -U+2613 uni2613 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) 2.7 (Sans Mono, Sans Mono Bold) -U+2614 uni2614 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) 2.7 (Sans Mono, Sans Mono Bold) -U+2615 uni2615 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) 2.7 (Sans Mono, Sans Mono Bold) -U+2616 uni2616 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) 2.7 (Sans Mono, Sans Mono Bold) -U+2617 uni2617 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) 2.7 (Sans Mono, Sans Mono Bold) -U+2618 uni2618 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) 2.7 (Sans Mono, Sans Mono Bold) -U+2619 uni2619 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) 2.7 (Sans Mono, Sans Mono Bold) -U+261a uni261A 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) 2.7 (Sans Mono, Sans Mono Bold) -U+261b uni261B 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) 2.7 (Sans Mono, Sans Mono Bold) -U+261c uni261C 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) 2.7 (Sans Mono, Sans Mono Bold) -U+261d uni261D 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) 2.7 (Sans Mono, Sans Mono Bold) -U+261e uni261E 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) 2.7 (Sans Mono, Sans Mono Bold) -U+261f uni261F 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) 2.7 (Sans Mono, Sans Mono Bold) -U+2620 uni2620 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) 2.7 (Sans Mono, Sans Mono Bold) -U+2621 uni2621 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) 2.7 (Sans Mono, Sans Mono Bold) -U+2622 uni2622 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) 2.7 (Sans Mono, Sans Mono Bold) -U+2623 uni2623 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) 2.7 (Sans Mono, Sans Mono Bold) -U+2624 uni2624 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) 2.7 (Sans Mono, Sans Mono Bold) -U+2625 uni2625 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) 2.7 (Sans Mono, Sans Mono Bold) -U+2626 uni2626 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) 2.7 (Sans Mono, Sans Mono Bold) -U+2627 uni2627 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) 2.7 (Sans Mono, Sans Mono Bold) -U+2628 uni2628 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) 2.7 (Sans Mono, Sans Mono Bold) -U+2629 uni2629 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) 2.7 (Sans Mono, Sans Mono Bold) -U+262a uni262A 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) 2.7 (Sans Mono, Sans Mono Bold) -U+262b uni262B 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) 2.7 (Sans Mono, Sans Mono Bold) -U+262c uni262C 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) 2.7 (Sans Mono, Sans Mono Bold) -U+262d uni262D 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) 2.7 (Sans Mono, Sans Mono Bold) -U+262e uni262E 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) 2.7 (Sans Mono, Sans Mono Bold) -U+262f uni262F 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) 2.7 (Sans Mono, Sans Mono Bold) -U+2630 uni2630 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) -U+2631 uni2631 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) -U+2632 uni2632 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) -U+2633 uni2633 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) -U+2634 uni2634 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) -U+2635 uni2635 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) -U+2636 uni2636 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) -U+2637 uni2637 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) -U+2638 uni2638 1.15 -U+2639 uni2639 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+263a smileface 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+263b invsmileface 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+263c sun 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+263d uni263D 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) 2.7 (Sans Mono, Sans Mono Bold) -U+263e uni263E 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) 2.7 (Sans Mono, Sans Mono Bold) -U+263f uni263F 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+2640 female 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+2641 uni2641 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+2642 male 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+2643 uni2643 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+2644 uni2644 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+2645 uni2645 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+2646 uni2646 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+2647 uni2647 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+2648 uni2648 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) 2.7 (Sans Mono, Sans Mono Bold) -U+2649 uni2649 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) 2.7 (Sans Mono, Sans Mono Bold) -U+264a uni264A 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) 2.7 (Sans Mono, Sans Mono Bold) -U+264b uni264B 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) 2.7 (Sans Mono, Sans Mono Bold) -U+264c uni264C 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) 2.7 (Sans Mono, Sans Mono Bold) -U+264d uni264D 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) 2.7 (Sans Mono, Sans Mono Bold) -U+264e uni264E 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) 2.7 (Sans Mono, Sans Mono Bold) -U+264f uni264F 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) 2.7 (Sans Mono, Sans Mono Bold) -U+2650 uni2650 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) 2.7 (Sans Mono, Sans Mono Bold) -U+2651 uni2651 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) 2.7 (Sans Mono, Sans Mono Bold) -U+2652 uni2652 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) 2.7 (Sans Mono, Sans Mono Bold) -U+2653 uni2653 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) 2.7 (Sans Mono, Sans Mono Bold) -U+2654 uni2654 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) 2.7 (Sans Mono, Sans Mono Bold) -U+2655 uni2655 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) 2.7 (Sans Mono, Sans Mono Bold) -U+2656 uni2656 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) 2.7 (Sans Mono, Sans Mono Bold) -U+2657 uni2657 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) 2.7 (Sans Mono, Sans Mono Bold) -U+2658 uni2658 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) 2.7 (Sans Mono, Sans Mono Bold) -U+2659 uni2659 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) 2.7 (Sans Mono, Sans Mono Bold) -U+265a uni265A 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) 2.7 (Sans Mono, Sans Mono Bold) -U+265b uni265B 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) 2.7 (Sans Mono, Sans Mono Bold) -U+265c uni265C 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) 2.7 (Sans Mono, Sans Mono Bold) -U+265d uni265D 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) 2.7 (Sans Mono, Sans Mono Bold) -U+265e uni265E 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) 2.7 (Sans Mono, Sans Mono Bold) -U+265f uni265F 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) 2.7 (Sans Mono, Sans Mono Bold) -U+2660 spade 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) -U+2661 uni2661 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) -U+2662 uni2662 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) -U+2663 club 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) -U+2664 uni2664 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) -U+2665 heart 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) -U+2666 diamond 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) -U+2667 uni2667 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) -U+2668 uni2668 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) 2.7 (Sans Mono, Sans Mono Bold) -U+2669 uni2669 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+266a musicalnote 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) -U+266b musicalnotedbl 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+266c uni266C 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+266d uni266D 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) -U+266e uni266E 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) -U+266f uni266F 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) -U+2670 uni2670 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) 2.7 (Sans Mono, Sans Mono Bold) -U+2671 uni2671 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) 2.7 (Sans Mono, Sans Mono Bold) -U+2672 uni2672 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) 2.7 (Sans Mono, Sans Mono Bold) -U+2673 uni2673 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) 2.7 (Sans Mono, Sans Mono Bold) -U+2674 uni2674 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) 2.7 (Sans Mono, Sans Mono Bold) -U+2675 uni2675 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) 2.7 (Sans Mono, Sans Mono Bold) -U+2676 uni2676 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) 2.7 (Sans Mono, Sans Mono Bold) -U+2677 uni2677 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) 2.7 (Sans Mono, Sans Mono Bold) -U+2678 uni2678 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) 2.7 (Sans Mono, Sans Mono Bold) -U+2679 uni2679 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) 2.7 (Sans Mono, Sans Mono Bold) -U+267a uni267A 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) 2.7 (Sans Mono, Sans Mono Bold) -U+267b uni267B 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) 2.7 (Sans Mono, Sans Mono Bold) -U+267c uni267C 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) 2.7 (Sans Mono, Sans Mono Bold) -U+267d uni267D 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) 2.7 (Sans Mono, Sans Mono Bold) -U+267e uni267E 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) 2.7 (Sans Mono, Sans Mono Bold) -U+267f uni267F 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) 2.7 (Sans Mono, Sans Mono Bold) -U+2680 uni2680 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.4 (Sans ExtraLight) 2.7 (Sans Mono, Sans Mono Bold) -U+2681 uni2681 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.4 (Sans ExtraLight) 2.7 (Sans Mono, Sans Mono Bold) -U+2682 uni2682 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.4 (Sans ExtraLight) 2.7 (Sans Mono, Sans Mono Bold) -U+2683 uni2683 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.4 (Sans ExtraLight) 2.7 (Sans Mono, Sans Mono Bold) -U+2684 uni2684 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.4 (Sans ExtraLight) 2.7 (Sans Mono, Sans Mono Bold) -U+2685 uni2685 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.4 (Sans ExtraLight) 2.7 (Sans Mono, Sans Mono Bold) -U+2686 uni2686 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) 2.7 (Sans Mono, Sans Mono Bold) -U+2687 uni2687 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) 2.7 (Sans Mono, Sans Mono Bold) -U+2688 uni2688 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) 2.7 (Sans Mono, Sans Mono Bold) -U+2689 uni2689 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) 2.7 (Sans Mono, Sans Mono Bold) -U+268a uni268A 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) 2.7 (Sans Mono, Sans Mono Bold) -U+268b uni268B 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) 2.7 (Sans Mono, Sans Mono Bold) -U+268c uni268C 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) -U+268d uni268D 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) -U+268e uni268E 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) -U+268f uni268F 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) -U+2690 uni2690 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) 2.7 (Sans Mono, Sans Mono Bold) -U+2691 uni2691 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) 2.7 (Sans Mono, Sans Mono Bold) -U+2692 uni2692 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) 2.7 (Sans Mono, Sans Mono Bold) -U+2693 uni2693 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) 2.7 (Sans Mono, Sans Mono Bold) -U+2694 uni2694 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) 2.7 (Sans Mono, Sans Mono Bold) -U+2695 uni2695 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) 2.7 (Sans Mono, Sans Mono Bold) -U+2696 uni2696 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) 2.7 (Sans Mono, Sans Mono Bold) -U+2697 uni2697 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) 2.7 (Sans Mono, Sans Mono Bold) -U+2698 uni2698 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) 2.7 (Sans Mono, Sans Mono Bold) -U+2699 uni2699 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) 2.7 (Sans Mono, Sans Mono Bold) -U+269a uni269A 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) 2.7 (Sans Mono, Sans Mono Bold) -U+269b uni269B 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) 2.7 (Sans Mono, Sans Mono Bold) -U+269c uni269C 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) 2.7 (Sans Mono, Sans Mono Bold) -U+269e uni269E 2.35 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+269f uni269F 2.35 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+26a0 uni26A0 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) 2.7 (Sans Mono, Sans Mono Bold) -U+26a1 uni26A1 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) 2.7 (Sans Mono, Sans Mono Bold) -U+26a2 uni26A2 2.10 (Sans, Sans Bold, Sans Bold Oblique, Sans Oblique) 2.11 (Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique) -U+26a3 uni26A3 2.10 (Sans, Sans Bold, Sans Bold Oblique, Sans Oblique) 2.11 (Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique) -U+26a4 uni26A4 2.10 (Sans, Sans Bold, Sans Bold Oblique, Sans Oblique) 2.11 (Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique) -U+26a5 uni26A5 2.10 (Sans, Sans Bold, Sans Bold Oblique, Sans Oblique) 2.11 (Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique) -U+26a6 uni26A6 2.10 (Sans, Sans Bold, Sans Bold Oblique, Sans Oblique) 2.11 (Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique) -U+26a7 uni26A7 2.10 (Sans, Sans Bold, Sans Bold Oblique, Sans Oblique) 2.11 (Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique) -U+26a8 uni26A8 2.10 (Sans, Sans Bold, Sans Bold Oblique, Sans Oblique) 2.11 (Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique) -U+26a9 uni26A9 2.10 (Sans, Sans Bold, Sans Bold Oblique, Sans Oblique) 2.11 (Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique) -U+26aa uni26AA 2.10 (Sans, Sans Bold, Sans Bold Oblique, Sans Oblique) 2.11 (Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique) -U+26ab uni26AB 2.10 (Sans, Sans Bold, Sans Bold Oblique, Sans Oblique) 2.11 (Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique) -U+26ac uni26AC 2.10 (Sans, Sans Bold, Sans Bold Oblique, Sans Oblique) 2.11 (Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique) -U+26ad uni26AD 2.10 (Sans, Sans Bold, Sans Bold Oblique, Sans Oblique) 2.11 (Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique) 2.36 (Math TeX Gyre Regular) -U+26ae uni26AE 2.10 (Sans, Sans Bold, Sans Bold Oblique, Sans Oblique) 2.11 (Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique) 2.36 (Math TeX Gyre Regular) -U+26af uni26AF 2.10 (Sans, Sans Bold, Sans Bold Oblique, Sans Oblique) 2.11 (Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique) -U+26b0 uni26B0 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) 2.8 (Sans Mono, Sans Mono Bold) -U+26b1 uni26B1 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) 2.8 (Sans Mono, Sans Mono Bold) -U+26b2 uni26B2 2.12 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+26b3 uni26B3 2.29 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+26b4 uni26B4 2.29 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+26b5 uni26B5 2.29 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+26b6 uni26B6 2.29 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+26b7 uni26B7 2.29 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+26b8 uni26B8 2.29 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+26c0 uni26C0 2.32 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+26c1 uni26C1 2.32 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+26c2 uni26C2 2.32 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+26c3 uni26C3 2.32 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+26e2 uni26E2 2.33 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+2701 uni2701 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.8 (Sans Mono, Sans Mono Bold) -U+2702 uni2702 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.8 (Sans Mono, Sans Mono Bold) -U+2703 uni2703 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.8 (Sans Mono, Sans Mono Bold) -U+2704 uni2704 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.8 (Sans Mono, Sans Mono Bold) -U+2706 uni2706 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.8 (Sans Mono, Sans Mono Bold) -U+2707 uni2707 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.8 (Sans Mono, Sans Mono Bold) -U+2708 uni2708 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.8 (Sans Mono, Sans Mono Bold) -U+2709 uni2709 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.8 (Sans Mono, Sans Mono Bold) -U+270c uni270C 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.8 (Sans Mono, Sans Mono Bold) -U+270d uni270D 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.8 (Sans Mono, Sans Mono Bold) -U+270e uni270E 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.8 (Sans Mono, Sans Mono Bold) -U+270f uni270F 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.8 (Sans Mono, Sans Mono Bold) -U+2710 uni2710 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.8 (Sans Mono, Sans Mono Bold) -U+2711 uni2711 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.8 (Sans Mono, Sans Mono Bold) -U+2712 uni2712 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.8 (Sans Mono, Sans Mono Bold) -U+2713 uni2713 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.8 (Sans Mono, Sans Mono Bold) 2.36 (Math TeX Gyre Regular) -U+2714 uni2714 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.8 (Sans Mono, Sans Mono Bold) -U+2715 uni2715 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.8 (Sans Mono, Sans Mono Bold) -U+2716 uni2716 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.8 (Sans Mono, Sans Mono Bold) -U+2717 uni2717 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.8 (Sans Mono, Sans Mono Bold) -U+2718 uni2718 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.8 (Sans Mono, Sans Mono Bold) -U+2719 uni2719 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.8 (Sans Mono, Sans Mono Bold) -U+271a uni271A 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.8 (Sans Mono, Sans Mono Bold) -U+271b uni271B 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.8 (Sans Mono, Sans Mono Bold) -U+271c uni271C 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.8 (Sans Mono, Sans Mono Bold) -U+271d uni271D 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.8 (Sans Mono, Sans Mono Bold) -U+271e uni271E 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.8 (Sans Mono, Sans Mono Bold) -U+271f uni271F 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.8 (Sans Mono, Sans Mono Bold) -U+2720 uni2720 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.8 (Sans Mono, Sans Mono Bold) 2.36 (Math TeX Gyre Regular) -U+2721 uni2721 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.8 (Sans Mono, Sans Mono Bold) -U+2722 uni2722 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.8 (Sans Mono, Sans Mono Bold) -U+2723 uni2723 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.8 (Sans Mono, Sans Mono Bold) -U+2724 uni2724 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.8 (Sans Mono, Sans Mono Bold) -U+2725 uni2725 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.8 (Sans Mono, Sans Mono Bold) -U+2726 uni2726 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.8 (Sans Mono, Sans Mono Bold) -U+2727 uni2727 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.8 (Sans Mono, Sans Mono Bold) -U+2729 uni2729 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.8 (Sans Mono, Sans Mono Bold) -U+272a uni272A 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.8 (Sans Mono, Sans Mono Bold) -U+272b uni272B 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.8 (Sans Mono, Sans Mono Bold) -U+272c uni272C 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.8 (Sans Mono, Sans Mono Bold) -U+272d uni272D 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.8 (Sans Mono, Sans Mono Bold) -U+272e uni272E 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.8 (Sans Mono, Sans Mono Bold) -U+272f uni272F 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.8 (Sans Mono, Sans Mono Bold) -U+2730 uni2730 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.8 (Sans Mono, Sans Mono Bold) -U+2731 uni2731 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.8 (Sans Mono, Sans Mono Bold) -U+2732 uni2732 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.8 (Sans Mono, Sans Mono Bold) -U+2733 uni2733 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.8 (Sans Mono, Sans Mono Bold) -U+2734 uni2734 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.8 (Sans Mono, Sans Mono Bold) -U+2735 uni2735 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.8 (Sans Mono, Sans Mono Bold) -U+2736 uni2736 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.8 (Sans Mono, Sans Mono Bold) -U+2737 uni2737 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.8 (Sans Mono, Sans Mono Bold) -U+2738 uni2738 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.8 (Sans Mono, Sans Mono Bold) -U+2739 uni2739 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.8 (Sans Mono, Sans Mono Bold) -U+273a uni273A 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.8 (Sans Mono, Sans Mono Bold) -U+273b uni273B 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.8 (Sans Mono, Sans Mono Bold) -U+273c uni273C 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.8 (Sans Mono, Sans Mono Bold) -U+273d uni273D 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.8 (Sans Mono, Sans Mono Bold) -U+273e uni273E 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.8 (Sans Mono, Sans Mono Bold) -U+273f uni273F 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.8 (Sans Mono, Sans Mono Bold) -U+2740 uni2740 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.8 (Sans Mono, Sans Mono Bold) -U+2741 uni2741 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.8 (Sans Mono, Sans Mono Bold) -U+2742 uni2742 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.8 (Sans Mono, Sans Mono Bold) -U+2743 uni2743 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.8 (Sans Mono, Sans Mono Bold) -U+2744 uni2744 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.8 (Sans Mono, Sans Mono Bold) -U+2745 uni2745 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.8 (Sans Mono, Sans Mono Bold) -U+2746 uni2746 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.8 (Sans Mono, Sans Mono Bold) -U+2747 uni2747 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.8 (Sans Mono, Sans Mono Bold) -U+2748 uni2748 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.8 (Sans Mono, Sans Mono Bold) -U+2749 uni2749 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.8 (Sans Mono, Sans Mono Bold) -U+274a uni274A 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.8 (Sans Mono, Sans Mono Bold) -U+274b uni274B 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.8 (Sans Mono, Sans Mono Bold) -U+274d uni274D 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) 2.8 (Sans Mono, Sans Mono Bold) -U+274f uni274F 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) 2.8 (Sans Mono, Sans Mono Bold) -U+2750 uni2750 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) 2.8 (Sans Mono, Sans Mono Bold) -U+2751 uni2751 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) 2.8 (Sans Mono, Sans Mono Bold) -U+2752 uni2752 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) 2.8 (Sans Mono, Sans Mono Bold) -U+2756 uni2756 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) 2.8 (Sans Mono, Sans Mono Bold) -U+2758 uni2758 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.8 (Sans Mono, Sans Mono Bold) -U+2759 uni2759 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.8 (Sans Mono, Sans Mono Bold) -U+275a uni275A 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.8 (Sans Mono, Sans Mono Bold) -U+275b uni275B 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) 2.8 (Sans Mono, Sans Mono Bold) -U+275c uni275C 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) 2.8 (Sans Mono, Sans Mono Bold) -U+275d uni275D 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) 2.8 (Sans Mono, Sans Mono Bold) -U+275e uni275E 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) 2.8 (Sans Mono, Sans Mono Bold) -U+2761 uni2761 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.8 (Sans Mono, Sans Mono Bold) -U+2762 uni2762 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.8 (Sans Mono, Sans Mono Bold) -U+2763 uni2763 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.8 (Sans Mono, Sans Mono Bold) -U+2764 uni2764 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.8 (Sans Mono, Sans Mono Bold) -U+2765 uni2765 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.8 (Sans Mono, Sans Mono Bold) -U+2766 uni2766 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.8 (Sans Mono, Sans Mono Bold) -U+2767 uni2767 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.8 (Sans Mono, Sans Mono Bold) -U+2768 uni2768 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.8 (Sans Mono, Sans Mono Bold) -U+2769 uni2769 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.8 (Sans Mono, Sans Mono Bold) -U+276a uni276A 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.8 (Sans Mono, Sans Mono Bold) -U+276b uni276B 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.8 (Sans Mono, Sans Mono Bold) -U+276c uni276C 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.8 (Sans Mono, Sans Mono Bold) -U+276d uni276D 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.8 (Sans Mono, Sans Mono Bold) -U+276e uni276E 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.8 (Sans Mono, Sans Mono Bold) -U+276f uni276F 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.8 (Sans Mono, Sans Mono Bold) -U+2770 uni2770 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.8 (Sans Mono, Sans Mono Bold) -U+2771 uni2771 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.8 (Sans Mono, Sans Mono Bold) -U+2772 uni2772 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.8 (Sans Mono, Sans Mono Bold) -U+2773 uni2773 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.8 (Sans Mono, Sans Mono Bold) -U+2774 uni2774 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.8 (Sans Mono, Sans Mono Bold) -U+2775 uni2775 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.8 (Sans Mono, Sans Mono Bold) -U+2776 uni2776 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+2777 uni2777 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+2778 uni2778 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+2779 uni2779 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+277a uni277A 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+277b uni277B 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+277c uni277C 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+277d uni277D 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+277e uni277E 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+277f uni277F 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+2780 uni2780 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+2781 uni2781 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+2782 uni2782 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+2783 uni2783 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+2784 uni2784 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+2785 uni2785 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+2786 uni2786 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+2787 uni2787 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+2788 uni2788 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+2789 uni2789 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+278a uni278A 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+278b uni278B 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+278c uni278C 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+278d uni278D 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+278e uni278E 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+278f uni278F 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+2790 uni2790 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+2791 uni2791 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+2792 uni2792 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+2793 uni2793 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+2794 uni2794 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.7 (Sans Mono, Sans Mono Bold) -U+2798 uni2798 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.7 (Sans Mono, Sans Mono Bold) -U+2799 uni2799 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.7 (Sans Mono, Sans Mono Bold) -U+279a uni279A 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.7 (Sans Mono, Sans Mono Bold) -U+279b uni279B 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.7 (Sans Mono, Sans Mono Bold) -U+279c uni279C 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.7 (Sans Mono, Sans Mono Bold) -U+279d uni279D 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.7 (Sans Mono, Sans Mono Bold) -U+279e uni279E 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.7 (Sans Mono, Sans Mono Bold) -U+279f uni279F 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.7 (Sans Mono, Sans Mono Bold) -U+27a0 uni27A0 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.7 (Sans Mono, Sans Mono Bold) -U+27a1 uni27A1 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.7 (Sans Mono, Sans Mono Bold) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) -U+27a2 uni27A2 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.7 (Sans Mono, Sans Mono Bold) -U+27a3 uni27A3 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.7 (Sans Mono, Sans Mono Bold) -U+27a4 uni27A4 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.7 (Sans Mono, Sans Mono Bold) -U+27a5 uni27A5 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.7 (Sans Mono, Sans Mono Bold) -U+27a6 uni27A6 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.7 (Sans Mono, Sans Mono Bold) -U+27a7 uni27A7 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.7 (Sans Mono, Sans Mono Bold) -U+27a8 uni27A8 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.7 (Sans Mono, Sans Mono Bold) -U+27a9 uni27A9 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.7 (Sans Mono, Sans Mono Bold) -U+27aa uni27AA 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.7 (Sans Mono, Sans Mono Bold) -U+27ab uni27AB 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.7 (Sans Mono, Sans Mono Bold) -U+27ac uni27AC 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.7 (Sans Mono, Sans Mono Bold) -U+27ad uni27AD 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.7 (Sans Mono, Sans Mono Bold) -U+27ae uni27AE 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.7 (Sans Mono, Sans Mono Bold) -U+27af uni27AF 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.7 (Sans Mono, Sans Mono Bold) -U+27b1 uni27B1 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.7 (Sans Mono, Sans Mono Bold) -U+27b2 uni27B2 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.7 (Sans Mono, Sans Mono Bold) -U+27b3 uni27B3 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.7 (Sans Mono, Sans Mono Bold) -U+27b4 uni27B4 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.7 (Sans Mono, Sans Mono Bold) -U+27b5 uni27B5 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.7 (Sans Mono, Sans Mono Bold) -U+27b6 uni27B6 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.7 (Sans Mono, Sans Mono Bold) -U+27b7 uni27B7 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.7 (Sans Mono, Sans Mono Bold) -U+27b8 uni27B8 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.7 (Sans Mono, Sans Mono Bold) -U+27b9 uni27B9 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.7 (Sans Mono, Sans Mono Bold) -U+27ba uni27BA 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.7 (Sans Mono, Sans Mono Bold) -U+27bb uni27BB 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.7 (Sans Mono, Sans Mono Bold) -U+27bc uni27BC 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.7 (Sans Mono, Sans Mono Bold) -U+27bd uni27BD 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.7 (Sans Mono, Sans Mono Bold) -U+27be uni27BE 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.7 (Sans Mono, Sans Mono Bold) -U+27bf uni27BF 2.7 (Sans Mono Bold) -U+27c2 uni27C2 2.34 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.36 (Math TeX Gyre Regular) -U+27c5 uni27C5 2.26 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) -U+27c6 uni27C6 2.26 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) -U+27d8 uni27D8 2.36 (Math TeX Gyre Regular) -U+27d9 uni27D9 2.36 (Math TeX Gyre Regular) -U+27da uni27DA 2.36 (Math TeX Gyre Regular) -U+27db uni27DB 2.36 (Math TeX Gyre Regular) -U+27dc uni27DC 2.35 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.36 (Math TeX Gyre Regular) -U+27dd uni27DD 2.36 (Math TeX Gyre Regular) -U+27de uni27DE 2.36 (Math TeX Gyre Regular) -U+27e0 uni27E0 2.3 -U+27e1 uni27E1 2.36 (Math TeX Gyre Regular) -U+27e2 uni27E2 2.36 (Math TeX Gyre Regular) -U+27e3 uni27E3 2.36 (Math TeX Gyre Regular) -U+27e6 uni27E6 2.15 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.34 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.36 (Math TeX Gyre Regular) -U+27e7 uni27E7 2.15 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.34 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.36 (Math TeX Gyre Regular) -U+27e8 uni27E8 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.13 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) -U+27e9 uni27E9 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.13 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) -U+27ea uni27EA 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.35 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.36 (Math TeX Gyre Regular) -U+27eb uni27EB 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.35 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.36 (Math TeX Gyre Regular) -U+27ee uni27EE 2.36 (Math TeX Gyre Regular) -U+27ef uni27EF 2.36 (Math TeX Gyre Regular) -U+27f0 uni27F0 2.13 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+27f1 uni27F1 2.13 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+27f2 uni27F2 2.13 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+27f3 uni27F3 2.13 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+27f4 uni27F4 2.13 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) -U+27f5 uni27F5 2.13 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.35 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.36 (Math TeX Gyre Regular) -U+27f6 uni27F6 2.13 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.35 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.36 (Math TeX Gyre Regular) -U+27f7 uni27F7 2.13 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.35 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.36 (Math TeX Gyre Regular) -U+27f8 uni27F8 2.13 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) -U+27f9 uni27F9 2.13 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) -U+27fa uni27FA 2.13 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) -U+27fb uni27FB 2.13 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) -U+27fc uni27FC 2.13 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) -U+27fd uni27FD 2.13 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) -U+27fe uni27FE 2.13 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) -U+27ff uni27FF 2.13 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) -U+2800 uni2800 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.18 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+2801 uni2801 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.18 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+2802 uni2802 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.18 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+2803 uni2803 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.18 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+2804 uni2804 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.18 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+2805 uni2805 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.18 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+2806 uni2806 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.18 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+2807 uni2807 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.18 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+2808 uni2808 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.18 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+2809 uni2809 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.18 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+280a uni280A 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.18 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+280b uni280B 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.18 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+280c uni280C 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.18 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+280d uni280D 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.18 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+280e uni280E 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.18 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+280f uni280F 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.18 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+2810 uni2810 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.18 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+2811 uni2811 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.18 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+2812 uni2812 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.18 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+2813 uni2813 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.18 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+2814 uni2814 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.18 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+2815 uni2815 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.18 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+2816 uni2816 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.18 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+2817 uni2817 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.18 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+2818 uni2818 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.18 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+2819 uni2819 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.18 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+281a uni281A 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.18 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+281b uni281B 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.18 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+281c uni281C 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.18 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+281d uni281D 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.18 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+281e uni281E 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.18 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+281f uni281F 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.18 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+2820 uni2820 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.18 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+2821 uni2821 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.18 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+2822 uni2822 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.18 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+2823 uni2823 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.18 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+2824 uni2824 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.18 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+2825 uni2825 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.18 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+2826 uni2826 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.18 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+2827 uni2827 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.18 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+2828 uni2828 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.18 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+2829 uni2829 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.18 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+282a uni282A 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.18 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+282b uni282B 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.18 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+282c uni282C 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.18 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+282d uni282D 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.18 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+282e uni282E 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.18 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+282f uni282F 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.18 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+2830 uni2830 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.18 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+2831 uni2831 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.18 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+2832 uni2832 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.18 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+2833 uni2833 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.18 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+2834 uni2834 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.18 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+2835 uni2835 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.18 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+2836 uni2836 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.18 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+2837 uni2837 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.18 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+2838 uni2838 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.18 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+2839 uni2839 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.18 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+283a uni283A 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.18 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+283b uni283B 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.18 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+283c uni283C 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.18 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+283d uni283D 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.18 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+283e uni283E 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.18 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+283f uni283F 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.18 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+2840 uni2840 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.18 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+2841 uni2841 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.18 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+2842 uni2842 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.18 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+2843 uni2843 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.18 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+2844 uni2844 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.18 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+2845 uni2845 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.18 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+2846 uni2846 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.18 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+2847 uni2847 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.18 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+2848 uni2848 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.18 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+2849 uni2849 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.18 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+284a uni284A 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.18 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+284b uni284B 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.18 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+284c uni284C 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.18 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+284d uni284D 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.18 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+284e uni284E 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.18 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+284f uni284F 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.18 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+2850 uni2850 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.18 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+2851 uni2851 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.18 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+2852 uni2852 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.18 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+2853 uni2853 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.18 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+2854 uni2854 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.18 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+2855 uni2855 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.18 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+2856 uni2856 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.18 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+2857 uni2857 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.18 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+2858 uni2858 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.18 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+2859 uni2859 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.18 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+285a uni285A 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.18 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+285b uni285B 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.18 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+285c uni285C 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.18 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+285d uni285D 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.18 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+285e uni285E 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.18 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+285f uni285F 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.18 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+2860 uni2860 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.18 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+2861 uni2861 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.18 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+2862 uni2862 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.18 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+2863 uni2863 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.18 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+2864 uni2864 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.18 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+2865 uni2865 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.18 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+2866 uni2866 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.18 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+2867 uni2867 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.18 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+2868 uni2868 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.18 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+2869 uni2869 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.18 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+286a uni286A 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.18 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+286b uni286B 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.18 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+286c uni286C 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.18 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+286d uni286D 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.18 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+286e uni286E 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.18 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+286f uni286F 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.18 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+2870 uni2870 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.18 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+2871 uni2871 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.18 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+2872 uni2872 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.18 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+2873 uni2873 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.18 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+2874 uni2874 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.18 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+2875 uni2875 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.18 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+2876 uni2876 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.18 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+2877 uni2877 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.18 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+2878 uni2878 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.18 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+2879 uni2879 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.18 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+287a uni287A 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.18 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+287b uni287B 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.18 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+287c uni287C 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.18 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+287d uni287D 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.18 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+287e uni287E 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.18 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+287f uni287F 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.18 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+2880 uni2880 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.18 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+2881 uni2881 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.18 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+2882 uni2882 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.18 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+2883 uni2883 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.18 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+2884 uni2884 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.18 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+2885 uni2885 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.18 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+2886 uni2886 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.18 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+2887 uni2887 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.18 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+2888 uni2888 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.18 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+2889 uni2889 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.18 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+288a uni288A 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.18 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+288b uni288B 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.18 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+288c uni288C 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.18 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+288d uni288D 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.18 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+288e uni288E 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.18 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+288f uni288F 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.18 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+2890 uni2890 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.18 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+2891 uni2891 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.18 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+2892 uni2892 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.18 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+2893 uni2893 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.18 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+2894 uni2894 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.18 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+2895 uni2895 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.18 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+2896 uni2896 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.18 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+2897 uni2897 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.18 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+2898 uni2898 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.18 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+2899 uni2899 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.18 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+289a uni289A 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.18 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+289b uni289B 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.18 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+289c uni289C 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.18 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+289d uni289D 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.18 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+289e uni289E 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.18 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+289f uni289F 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.18 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+28a0 uni28A0 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.18 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+28a1 uni28A1 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.18 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+28a2 uni28A2 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.18 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+28a3 uni28A3 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.18 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+28a4 uni28A4 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.18 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+28a5 uni28A5 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.18 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+28a6 uni28A6 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.18 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+28a7 uni28A7 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.18 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+28a8 uni28A8 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.18 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+28a9 uni28A9 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.18 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+28aa uni28AA 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.18 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+28ab uni28AB 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.18 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+28ac uni28AC 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.18 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+28ad uni28AD 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.18 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+28ae uni28AE 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.18 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+28af uni28AF 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.18 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+28b0 uni28B0 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.18 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+28b1 uni28B1 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.18 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+28b2 uni28B2 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.18 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+28b3 uni28B3 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.18 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+28b4 uni28B4 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.18 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+28b5 uni28B5 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.18 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+28b6 uni28B6 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.18 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+28b7 uni28B7 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.18 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+28b8 uni28B8 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.18 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+28b9 uni28B9 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.18 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+28ba uni28BA 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.18 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+28bb uni28BB 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.18 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+28bc uni28BC 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.18 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+28bd uni28BD 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.18 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+28be uni28BE 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.18 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+28bf uni28BF 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.18 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+28c0 uni28C0 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.18 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+28c1 uni28C1 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.18 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+28c2 uni28C2 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.18 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+28c3 uni28C3 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.18 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+28c4 uni28C4 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.18 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+28c5 uni28C5 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.18 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+28c6 uni28C6 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.18 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+28c7 uni28C7 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.18 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+28c8 uni28C8 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.18 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+28c9 uni28C9 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.18 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+28ca uni28CA 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.18 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+28cb uni28CB 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.18 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+28cc uni28CC 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.18 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+28cd uni28CD 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.18 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+28ce uni28CE 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.18 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+28cf uni28CF 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.18 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+28d0 uni28D0 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.18 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+28d1 uni28D1 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.18 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+28d2 uni28D2 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.18 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+28d3 uni28D3 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.18 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+28d4 uni28D4 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.18 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+28d5 uni28D5 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.18 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+28d6 uni28D6 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.18 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+28d7 uni28D7 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.18 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+28d8 uni28D8 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.18 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+28d9 uni28D9 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.18 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+28da uni28DA 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.18 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+28db uni28DB 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.18 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+28dc uni28DC 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.18 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+28dd uni28DD 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.18 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+28de uni28DE 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.18 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+28df uni28DF 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.18 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+28e0 uni28E0 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.18 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+28e1 uni28E1 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.18 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+28e2 uni28E2 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.18 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+28e3 uni28E3 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.18 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+28e4 uni28E4 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.18 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+28e5 uni28E5 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.18 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+28e6 uni28E6 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.18 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+28e7 uni28E7 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.18 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+28e8 uni28E8 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.18 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+28e9 uni28E9 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.18 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+28ea uni28EA 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.18 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+28eb uni28EB 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.18 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+28ec uni28EC 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.18 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+28ed uni28ED 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.18 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+28ee uni28EE 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.18 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+28ef uni28EF 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.18 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+28f0 uni28F0 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.18 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+28f1 uni28F1 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.18 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+28f2 uni28F2 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.18 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+28f3 uni28F3 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.18 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+28f4 uni28F4 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.18 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+28f5 uni28F5 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.18 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+28f6 uni28F6 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.18 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+28f7 uni28F7 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.18 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+28f8 uni28F8 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.18 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+28f9 uni28F9 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.18 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+28fa uni28FA 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.18 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+28fb uni28FB 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.18 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+28fc uni28FC 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.18 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+28fd uni28FD 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.18 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+28fe uni28FE 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.18 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+28ff uni28FF 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.18 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+2900 uni2900 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+2901 uni2901 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+2902 uni2902 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+2903 uni2903 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+2904 uni2904 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+2905 uni2905 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+2906 uni2906 2.13 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) -U+2907 uni2907 2.13 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) -U+2908 uni2908 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+2909 uni2909 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+290a uni290A 2.13 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+290b uni290B 2.13 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+290c uni290C 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+290d uni290D 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+290e uni290E 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+290f uni290F 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+2910 uni2910 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+2911 uni2911 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+2912 uni2912 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+2913 uni2913 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+2914 uni2914 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+2915 uni2915 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+2916 uni2916 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+2917 uni2917 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+2918 uni2918 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+2919 uni2919 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+291a uni291A 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+291b uni291B 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+291c uni291C 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+291d uni291D 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+291e uni291E 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+291f uni291F 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+2920 uni2920 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+2921 uni2921 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+2922 uni2922 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+2923 uni2923 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+2924 uni2924 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+2925 uni2925 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+2926 uni2926 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+2927 uni2927 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+2928 uni2928 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+2929 uni2929 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+292a uni292A 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+292b uni292B 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+292c uni292C 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+292d uni292D 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+292e uni292E 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+292f uni292F 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+2930 uni2930 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+2931 uni2931 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+2932 uni2932 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+2933 uni2933 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+2934 uni2934 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+2935 uni2935 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+2936 uni2936 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+2937 uni2937 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+2938 uni2938 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+2939 uni2939 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+293a uni293A 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+293b uni293B 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+293c uni293C 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+293d uni293D 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+293e uni293E 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+293f uni293F 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+2940 uni2940 2.13 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+2941 uni2941 2.13 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+2942 uni2942 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+2943 uni2943 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+2944 uni2944 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+2945 uni2945 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+2946 uni2946 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+2947 uni2947 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+2948 uni2948 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+2949 uni2949 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+294a uni294A 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+294b uni294B 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+294c uni294C 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+294d uni294D 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+294e uni294E 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+294f uni294F 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+2950 uni2950 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+2951 uni2951 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+2952 uni2952 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+2953 uni2953 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+2954 uni2954 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+2955 uni2955 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+2956 uni2956 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+2957 uni2957 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+2958 uni2958 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+2959 uni2959 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+295a uni295A 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+295b uni295B 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+295c uni295C 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+295d uni295D 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+295e uni295E 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+295f uni295F 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+2960 uni2960 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+2961 uni2961 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+2962 uni2962 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+2963 uni2963 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+2964 uni2964 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+2965 uni2965 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+2966 uni2966 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+2967 uni2967 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+2968 uni2968 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+2969 uni2969 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+296a uni296A 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+296b uni296B 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+296c uni296C 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+296d uni296D 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+296e uni296E 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+296f uni296F 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+2970 uni2970 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+2971 uni2971 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+2972 uni2972 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+2973 uni2973 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+2974 uni2974 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+2975 uni2975 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+2976 uni2976 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+2977 uni2977 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+2978 uni2978 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+2979 uni2979 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+297a uni297A 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+297b uni297B 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+297c uni297C 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+297d uni297D 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+297e uni297E 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+297f uni297F 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+2983 uni2983 2.16 (Sans, Sans Bold, Sans Bold Oblique, Sans Oblique) 2.17 (Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique) -U+2984 uni2984 2.16 (Sans, Sans Bold, Sans Bold Oblique, Sans Oblique) 2.17 (Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique) -U+2987 uni2987 2.35 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) -U+2988 uni2988 2.35 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) -U+2997 uni2997 2.35 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) -U+2998 uni2998 2.35 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) -U+29ce uni29CE 2.7 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+29cf uni29CF 2.7 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+29d0 uni29D0 2.7 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+29d1 uni29D1 2.7 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+29d2 uni29D2 2.7 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+29d3 uni29D3 2.7 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+29d4 uni29D4 2.7 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+29d5 uni29D5 2.7 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+29eb uni29EB 2.2 -U+29fa uni29FA 2.18 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique) -U+29fb uni29FB 2.18 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique) -U+2a00 uni2A00 2.9 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.35 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.36 (Math TeX Gyre Regular) -U+2a01 uni2A01 2.9 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.36 (Math TeX Gyre Regular) -U+2a02 uni2A02 2.9 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.36 (Math TeX Gyre Regular) -U+2a03 uni2A03 2.36 (Math TeX Gyre Regular) -U+2a04 uni2A04 2.36 (Math TeX Gyre Regular) -U+2a05 uni2A05 2.36 (Math TeX Gyre Regular) -U+2a06 uni2A06 2.36 (Math TeX Gyre Regular) -U+2a09 uni2A09 2.36 (Math TeX Gyre Regular) -U+2a0c uni2A0C 2.2 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.9 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) -U+2a0d uni2A0D 2.2 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.9 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+2a0e uni2A0E 2.2 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.9 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+2a0f uni2A0F 2.9 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+2a10 uni2A10 2.9 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+2a11 uni2A11 2.9 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.36 (Math TeX Gyre Regular) -U+2a12 uni2A12 2.9 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+2a13 uni2A13 2.9 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+2a14 uni2A14 2.9 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+2a15 uni2A15 2.9 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+2a16 uni2A16 2.9 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+2a17 uni2A17 2.9 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+2a18 uni2A18 2.9 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+2a19 uni2A19 2.9 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+2a1a uni2A1A 2.9 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+2a1b uni2A1B 2.9 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+2a1c uni2A1C 2.9 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+2a2f uni2A2F 2.16 (Sans, Sans Bold, Sans Bold Oblique, Sans ExtraLight, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Italic) 2.17 (Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) -U+2a3f uni2A3F 2.36 (Math TeX Gyre Regular) -U+2a6a uni2A6A 2.34 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) -U+2a6b uni2A6B 2.34 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) -U+2a7d uni2A7D 2.7 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.36 (Math TeX Gyre Regular) -U+2a7e uni2A7E 2.7 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.36 (Math TeX Gyre Regular) -U+2a7f uni2A7F 2.7 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+2a80 uni2A80 2.7 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+2a81 uni2A81 2.7 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+2a82 uni2A82 2.7 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+2a83 uni2A83 2.7 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+2a84 uni2A84 2.7 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+2a85 uni2A85 2.7 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.36 (Math TeX Gyre Regular) -U+2a86 uni2A86 2.7 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.36 (Math TeX Gyre Regular) -U+2a87 uni2A87 2.7 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.36 (Math TeX Gyre Regular) -U+2a88 uni2A88 2.7 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.36 (Math TeX Gyre Regular) -U+2a89 uni2A89 2.7 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.36 (Math TeX Gyre Regular) -U+2a8a uni2A8A 2.7 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.36 (Math TeX Gyre Regular) -U+2a8b uni2A8B 2.7 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.36 (Math TeX Gyre Regular) -U+2a8c uni2A8C 2.7 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.36 (Math TeX Gyre Regular) -U+2a8d uni2A8D 2.7 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+2a8e uni2A8E 2.7 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+2a8f uni2A8F 2.7 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+2a90 uni2A90 2.7 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+2a91 uni2A91 2.7 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+2a92 uni2A92 2.7 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+2a93 uni2A93 2.7 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+2a94 uni2A94 2.7 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+2a95 uni2A95 2.7 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.36 (Math TeX Gyre Regular) -U+2a96 uni2A96 2.7 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.36 (Math TeX Gyre Regular) -U+2a97 uni2A97 2.7 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+2a98 uni2A98 2.7 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+2a99 uni2A99 2.7 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+2a9a uni2A9A 2.7 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+2a9b uni2A9B 2.7 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+2a9c uni2A9C 2.7 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+2a9d uni2A9D 2.7 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+2a9e uni2A9E 2.7 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+2a9f uni2A9F 2.7 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+2aa0 uni2AA0 2.7 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+2aae uni2AAE 2.7 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+2aaf uni2AAF 2.7 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.36 (Math TeX Gyre Regular) -U+2ab0 uni2AB0 2.7 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.36 (Math TeX Gyre Regular) -U+2ab1 uni2AB1 2.7 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+2ab2 uni2AB2 2.7 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+2ab3 uni2AB3 2.7 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+2ab4 uni2AB4 2.7 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+2ab5 uni2AB5 2.7 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+2ab6 uni2AB6 2.7 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+2ab7 uni2AB7 2.7 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+2ab8 uni2AB8 2.7 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+2ab9 uni2AB9 2.7 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+2aba uni2ABA 2.7 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+2af9 uni2AF9 2.7 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+2afa uni2AFA 2.7 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+2b00 uni2B00 2.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+2b01 uni2B01 2.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+2b02 uni2B02 2.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+2b03 uni2B03 2.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+2b04 uni2B04 2.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) -U+2b05 uni2B05 2.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.34 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.36 (Math TeX Gyre Regular) -U+2b06 uni2B06 2.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.34 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.36 (Math TeX Gyre Regular) -U+2b07 uni2B07 2.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.34 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.36 (Math TeX Gyre Regular) -U+2b08 uni2B08 2.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.34 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) -U+2b09 uni2B09 2.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.34 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) -U+2b0a uni2B0A 2.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.34 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) -U+2b0b uni2B0B 2.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.34 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) -U+2b0c uni2B0C 2.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.34 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.36 (Math TeX Gyre Regular) -U+2b0d uni2B0D 2.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.34 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.36 (Math TeX Gyre Regular) -U+2b0e uni2B0E 2.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+2b0f uni2B0F 2.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+2b10 uni2B10 2.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+2b11 uni2B11 2.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.22 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+2b12 uni2B12 2.3 -U+2b13 uni2B13 2.3 -U+2b14 uni2B14 2.10 (Sans, Sans Bold, Sans Bold Oblique, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Italic) 2.11 (Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic) 2.23 (Serif Italic Condensed) -U+2b15 uni2B15 2.10 (Sans, Sans Bold, Sans Bold Oblique, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Italic) 2.11 (Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic) 2.23 (Serif Italic Condensed) -U+2b16 uni2B16 2.10 (Sans, Sans Bold, Sans Bold Oblique, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Italic) 2.11 (Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic) 2.23 (Serif Italic Condensed) -U+2b17 uni2B17 2.10 (Sans, Sans Bold, Sans Bold Oblique, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Italic) 2.11 (Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic) 2.23 (Serif Italic Condensed) -U+2b18 uni2B18 2.10 (Sans, Sans Bold, Sans Bold Oblique, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Italic) 2.11 (Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic) 2.23 (Serif Italic Condensed) -U+2b19 uni2B19 2.10 (Sans, Sans Bold, Sans Bold Oblique, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Italic) 2.11 (Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic) 2.23 (Serif Italic Condensed) -U+2b1a uni2B1A 2.10 (Sans, Sans Bold, Sans Bold Oblique, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Italic) 2.11 (Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) -U+2b1f uni2B1F 2.29 (Sans, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.30 (Sans Bold) -U+2b20 uni2B20 2.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+2b21 uni2B21 2.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+2b22 uni2B22 2.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+2b23 uni2B23 2.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+2b24 uni2B24 2.29 (Sans, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.30 (Sans Bold) -U+2b31 uni2B31 2.36 (Math TeX Gyre Regular) -U+2b33 uni2B33 2.36 (Math TeX Gyre Regular) -U+2b53 uni2B53 2.29 (Sans, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.30 (Sans Bold) -U+2b54 uni2B54 2.29 (Sans, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.30 (Sans Bold) -U+2c60 uni2C60 2.10 (Sans, Sans Bold, Sans Bold Oblique, Sans Oblique) 2.11 (Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique) 2.33 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) -U+2c61 uni2C61 2.10 (Sans, Sans Bold, Sans Bold Oblique, Sans Oblique) 2.11 (Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique) 2.33 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) -U+2c62 uni2C62 2.10 (Sans, Sans Bold, Sans Bold Oblique, Sans Oblique) 2.11 (Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique) -U+2c63 uni2C63 2.10 (Sans, Sans Bold, Sans Bold Oblique, Sans Oblique) 2.11 (Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique) 2.33 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) -U+2c64 uni2C64 2.10 (Sans, Sans Bold, Sans Bold Oblique, Sans Oblique) 2.11 (Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique) 2.27 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) -U+2c65 uni2C65 2.10 (Sans, Sans Bold, Sans Bold Oblique, Sans Oblique) 2.11 (Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique) -U+2c66 uni2C66 2.10 (Sans, Sans Bold, Sans Bold Oblique, Sans Oblique) 2.11 (Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique) -U+2c67 uni2C67 2.9 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.18 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+2c68 uni2C68 2.9 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.18 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+2c69 uni2C69 2.9 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.18 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+2c6a uni2C6A 2.9 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.18 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+2c6b uni2C6B 2.10 (Sans, Sans Bold, Sans Bold Oblique, Sans Oblique) 2.11 (Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique) 2.18 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+2c6c uni2C6C 2.10 (Sans, Sans Bold, Sans Bold Oblique, Sans Oblique) 2.11 (Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique) 2.18 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+2c6d uni2C6D 2.26 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.31 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) -U+2c6e uni2C6E 2.26 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) 2.27 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) -U+2c6f uni2C6F 2.26 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) 2.27 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Italic, Serif Italic Condensed) 2.28 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.31 (Serif Condensed Italic) -U+2c70 uni2C70 2.31 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) -U+2c71 uni2C71 2.26 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.31 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) -U+2c72 uni2C72 2.26 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.31 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) -U+2c73 uni2C73 2.26 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.31 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) -U+2c74 uni2C74 2.10 (Sans, Sans Bold, Sans Bold Oblique, Sans Oblique) 2.11 (Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique) -U+2c75 uni2C75 2.9 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.18 (Sans ExtraLight, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.20 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.23 (Serif Italic Condensed) -U+2c76 uni2C76 2.9 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.18 (Sans ExtraLight, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.20 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.23 (Serif Italic Condensed) -U+2c77 uni2C77 2.9 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.18 (Sans ExtraLight, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.20 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.23 (Serif Italic Condensed) -U+2c79 uni2C79 2.26 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.27 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Italic, Serif Italic Condensed) 2.28 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.31 (Serif Condensed Italic) -U+2c7a uni2C7A 2.27 -U+2c7b uni2C7B 2.26 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.34 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) -U+2c7c uni2C7C 2.26 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.27 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Italic, Serif Italic Condensed) 2.28 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.31 (Serif Condensed Italic) -U+2c7d uni2C7D 2.26 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.27 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Italic, Serif Italic Condensed) 2.28 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.31 (Serif Condensed Italic) -U+2c7e uni2C7E 2.31 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) -U+2c7f uni2C7F 2.31 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) -U+2d00 uni2D00 2.28 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) 2.34 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+2d01 uni2D01 2.28 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) 2.34 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+2d02 uni2D02 2.28 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) 2.34 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+2d03 uni2D03 2.28 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) 2.34 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+2d04 uni2D04 2.28 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) 2.34 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+2d05 uni2D05 2.28 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) 2.34 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+2d06 uni2D06 2.28 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) 2.34 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+2d07 uni2D07 2.28 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) 2.34 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+2d08 uni2D08 2.28 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) 2.34 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+2d09 uni2D09 2.28 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) 2.34 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+2d0a uni2D0A 2.28 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) 2.34 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+2d0b uni2D0B 2.28 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) 2.34 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+2d0c uni2D0C 2.28 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) 2.34 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+2d0d uni2D0D 2.28 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) 2.34 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+2d0e uni2D0E 2.28 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) 2.34 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+2d0f uni2D0F 2.28 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) 2.34 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+2d10 uni2D10 2.28 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) 2.34 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+2d11 uni2D11 2.28 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) 2.34 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+2d12 uni2D12 2.28 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) 2.34 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+2d13 uni2D13 2.28 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) 2.34 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+2d14 uni2D14 2.28 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) 2.34 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+2d15 uni2D15 2.28 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) 2.34 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+2d16 uni2D16 2.28 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) 2.34 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+2d17 uni2D17 2.28 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) 2.34 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+2d18 uni2D18 2.28 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) 2.34 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+2d19 uni2D19 2.28 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) 2.34 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+2d1a uni2D1A 2.28 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) 2.34 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+2d1b uni2D1B 2.28 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) 2.34 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+2d1c uni2D1C 2.28 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) 2.34 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+2d1d uni2D1D 2.28 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) 2.34 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+2d1e uni2D1E 2.28 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) 2.34 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+2d1f uni2D1F 2.28 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) 2.34 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+2d20 uni2D20 2.28 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) 2.34 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+2d21 uni2D21 2.28 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) 2.34 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+2d22 uni2D22 2.28 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) 2.34 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+2d23 uni2D23 2.28 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) 2.34 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+2d24 uni2D24 2.28 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) 2.34 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+2d25 uni2D25 2.28 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) 2.34 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+2d30 uni2D30 2.18 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) -U+2d31 uni2D31 2.18 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) -U+2d32 uni2D32 2.18 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) -U+2d33 uni2D33 2.18 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) -U+2d34 uni2D34 2.18 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) -U+2d35 uni2D35 2.18 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) -U+2d36 uni2D36 2.18 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) -U+2d37 uni2D37 2.18 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) -U+2d38 uni2D38 2.18 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) -U+2d39 uni2D39 2.18 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) -U+2d3a uni2D3A 2.18 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) -U+2d3b uni2D3B 2.18 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) -U+2d3c uni2D3C 2.18 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) -U+2d3d uni2D3D 2.18 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) -U+2d3e uni2D3E 2.18 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) -U+2d3f uni2D3F 2.18 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) -U+2d40 uni2D40 2.18 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) -U+2d41 uni2D41 2.18 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) -U+2d42 uni2D42 2.18 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) -U+2d43 uni2D43 2.18 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) -U+2d44 uni2D44 2.18 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) -U+2d45 uni2D45 2.18 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) -U+2d46 uni2D46 2.18 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) -U+2d47 uni2D47 2.18 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) -U+2d48 uni2D48 2.18 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) -U+2d49 uni2D49 2.18 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) -U+2d4a uni2D4A 2.18 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) -U+2d4b uni2D4B 2.18 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) -U+2d4c uni2D4C 2.18 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) -U+2d4d uni2D4D 2.18 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) -U+2d4e uni2D4E 2.18 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) -U+2d4f uni2D4F 2.18 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) -U+2d50 uni2D50 2.18 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) -U+2d51 uni2D51 2.18 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) -U+2d52 uni2D52 2.18 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) -U+2d53 uni2D53 2.18 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) -U+2d54 uni2D54 2.18 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) -U+2d55 uni2D55 2.18 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) -U+2d56 uni2D56 2.18 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) -U+2d57 uni2D57 2.18 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) -U+2d58 uni2D58 2.18 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) -U+2d59 uni2D59 2.18 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) -U+2d5a uni2D5A 2.18 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) -U+2d5b uni2D5B 2.18 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) -U+2d5c uni2D5C 2.18 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) -U+2d5d uni2D5D 2.18 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) -U+2d5e uni2D5E 2.18 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) -U+2d5f uni2D5F 2.18 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) -U+2d60 uni2D60 2.18 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) -U+2d61 uni2D61 2.18 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) -U+2d62 uni2D62 2.18 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) -U+2d63 uni2D63 2.18 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) -U+2d64 uni2D64 2.18 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) -U+2d65 uni2D65 2.18 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) -U+2d6f uni2D6F 2.18 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) -U+2e18 uni2E18 2.26 -U+2e1e uni2E1E 2.34 (Sans, Sans Condensed) -U+2e1f uni2E1F 2.34 (Sans Bold, Sans Bold Oblique, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.35 (Sans, Sans Condensed) -U+2e22 uni2E22 2.29 (Sans, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Italic, Serif Italic Condensed) 2.30 (Sans Bold) 2.31 (Serif Condensed Italic) -U+2e23 uni2E23 2.29 (Sans, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Italic, Serif Italic Condensed) 2.30 (Sans Bold) 2.31 (Serif Condensed Italic) -U+2e24 uni2E24 2.29 (Sans, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Italic, Serif Italic Condensed) 2.30 (Sans Bold) 2.31 (Serif Condensed Italic) -U+2e25 uni2E25 2.29 (Sans, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Italic, Serif Italic Condensed) 2.30 (Sans Bold) 2.31 (Serif Condensed Italic) -U+2e2e uni2E2E 2.26 -U+3016 whitelenticularbracketleft 2.36 (Math TeX Gyre Regular) -U+3017 whitelenticularbracketright 2.36 (Math TeX Gyre Regular) -U+4dc0 uni4DC0 2.22 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+4dc1 uni4DC1 2.22 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+4dc2 uni4DC2 2.22 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+4dc3 uni4DC3 2.22 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+4dc4 uni4DC4 2.22 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+4dc5 uni4DC5 2.22 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+4dc6 uni4DC6 2.22 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+4dc7 uni4DC7 2.22 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+4dc8 uni4DC8 2.22 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+4dc9 uni4DC9 2.22 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+4dca uni4DCA 2.22 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+4dcb uni4DCB 2.22 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+4dcc uni4DCC 2.22 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+4dcd uni4DCD 2.22 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+4dce uni4DCE 2.22 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+4dcf uni4DCF 2.22 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+4dd0 uni4DD0 2.22 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+4dd1 uni4DD1 2.22 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+4dd2 uni4DD2 2.22 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+4dd3 uni4DD3 2.22 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+4dd4 uni4DD4 2.22 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+4dd5 uni4DD5 2.22 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+4dd6 uni4DD6 2.22 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+4dd7 uni4DD7 2.22 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+4dd8 uni4DD8 2.22 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+4dd9 uni4DD9 2.22 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+4dda uni4DDA 2.22 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+4ddb uni4DDB 2.22 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+4ddc uni4DDC 2.22 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+4ddd uni4DDD 2.22 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+4dde uni4DDE 2.22 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+4ddf uni4DDF 2.22 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+4de0 uni4DE0 2.22 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+4de1 uni4DE1 2.22 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+4de2 uni4DE2 2.22 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+4de3 uni4DE3 2.22 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+4de4 uni4DE4 2.22 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+4de5 uni4DE5 2.22 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+4de6 uni4DE6 2.22 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+4de7 uni4DE7 2.22 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+4de8 uni4DE8 2.22 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+4de9 uni4DE9 2.22 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+4dea uni4DEA 2.22 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+4deb uni4DEB 2.22 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+4dec uni4DEC 2.22 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+4ded uni4DED 2.22 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+4dee uni4DEE 2.22 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+4def uni4DEF 2.22 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+4df0 uni4DF0 2.22 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+4df1 uni4DF1 2.22 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+4df2 uni4DF2 2.22 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+4df3 uni4DF3 2.22 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+4df4 uni4DF4 2.22 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+4df5 uni4DF5 2.22 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+4df6 uni4DF6 2.22 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+4df7 uni4DF7 2.22 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+4df8 uni4DF8 2.22 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+4df9 uni4DF9 2.22 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+4dfa uni4DFA 2.22 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+4dfb uni4DFB 2.22 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+4dfc uni4DFC 2.22 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+4dfd uni4DFD 2.22 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+4dfe uni4DFE 2.22 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+4dff uni4DFF 2.22 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+a4d0 uniA4D0 2.34 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) -U+a4d1 uniA4D1 2.34 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) -U+a4d2 uniA4D2 2.34 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) -U+a4d3 uniA4D3 2.34 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) -U+a4d4 uniA4D4 2.34 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) -U+a4d5 uniA4D5 2.34 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) -U+a4d6 uniA4D6 2.34 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) -U+a4d7 uniA4D7 2.34 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) -U+a4d8 uniA4D8 2.34 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) -U+a4d9 uniA4D9 2.34 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) -U+a4da uniA4DA 2.34 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) -U+a4db uniA4DB 2.34 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) -U+a4dc uniA4DC 2.34 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) -U+a4dd uniA4DD 2.34 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) -U+a4de uniA4DE 2.34 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) -U+a4df uniA4DF 2.34 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) -U+a4e0 uniA4E0 2.34 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) -U+a4e1 uniA4E1 2.34 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) -U+a4e2 uniA4E2 2.34 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) -U+a4e3 uniA4E3 2.34 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) -U+a4e4 uniA4E4 2.34 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) -U+a4e5 uniA4E5 2.34 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) -U+a4e6 uniA4E6 2.34 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) -U+a4e7 uniA4E7 2.34 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) -U+a4e8 uniA4E8 2.34 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) -U+a4e9 uniA4E9 2.34 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) -U+a4ea uniA4EA 2.34 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) -U+a4eb uniA4EB 2.34 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) -U+a4ec uniA4EC 2.34 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) -U+a4ed uniA4ED 2.34 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) -U+a4ee uniA4EE 2.34 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) -U+a4ef uniA4EF 2.34 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) -U+a4f0 uniA4F0 2.34 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) -U+a4f1 uniA4F1 2.34 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) -U+a4f2 uniA4F2 2.34 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) -U+a4f3 uniA4F3 2.34 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) -U+a4f4 uniA4F4 2.34 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) -U+a4f5 uniA4F5 2.34 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) -U+a4f6 uniA4F6 2.34 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) -U+a4f7 uniA4F7 2.34 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) -U+a4f8 uniA4F8 2.34 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) -U+a4f9 uniA4F9 2.34 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) -U+a4fa uniA4FA 2.34 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) -U+a4fb uniA4FB 2.34 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) -U+a4fc uniA4FC 2.34 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) -U+a4fd uniA4FD 2.34 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) -U+a4fe uniA4FE 2.34 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) -U+a4ff uniA4FF 2.34 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) -U+a644 uniA644 2.26 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) 2.27 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) -U+a645 uniA645 2.26 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) 2.27 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) -U+a646 uniA646 2.26 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) 2.27 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) -U+a647 uniA647 2.26 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) 2.27 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) -U+a64c uniA64C 2.26 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+a64d uniA64D 2.26 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+a650 uniA650 2.26 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) 2.27 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) -U+a651 uniA651 2.26 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) 2.27 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) -U+a654 uniA654 2.26 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) 2.27 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) -U+a655 uniA655 2.26 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) 2.27 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) -U+a656 uniA656 2.26 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) 2.27 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) -U+a657 uniA657 2.26 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) 2.27 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) -U+a662 uniA662 2.26 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) -U+a663 uniA663 2.26 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) -U+a664 uniA664 2.26 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) -U+a665 uniA665 2.26 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) -U+a666 uniA666 2.26 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) -U+a667 uniA667 2.26 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) -U+a668 uniA668 2.27 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) -U+a669 uniA669 2.27 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) -U+a66a uniA66A 2.27 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) -U+a66b uniA66B 2.27 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) -U+a66c uniA66C 2.27 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) -U+a66d uniA66D 2.27 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) -U+a66e uniA66E 2.27 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) -U+a68a uniA68A 2.26 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+a68b uniA68B 2.26 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+a68c uniA68C 2.26 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) -U+a68d uniA68D 2.26 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) -U+a694 uniA694 2.26 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) -U+a695 uniA695 2.26 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) -U+a698 uniA698 2.36 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) -U+a699 uniA699 2.36 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) -U+a708 uniA708 2.27 -U+a709 uniA709 2.27 -U+a70a uniA70A 2.27 -U+a70b uniA70B 2.27 -U+a70c uniA70C 2.27 -U+a70d uniA70D 2.27 -U+a70e uniA70E 2.27 -U+a70f uniA70F 2.27 -U+a710 uniA710 2.27 -U+a711 uniA711 2.27 -U+a712 uniA712 2.26 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) 2.27 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) -U+a713 uniA713 2.26 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) 2.27 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) -U+a714 uniA714 2.26 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) 2.27 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) -U+a715 uniA715 2.26 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) 2.27 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) -U+a716 uniA716 2.26 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) 2.27 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) -U+a71b uniA71B 2.27 -U+a71c uniA71C 2.27 -U+a71d uniA71D 2.27 -U+a71e uniA71E 2.27 -U+a71f uniA71F 2.27 -U+a722 uniA722 2.32 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique) -U+a723 uniA723 2.32 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique) -U+a724 uniA724 2.32 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique) -U+a725 uniA725 2.32 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique) -U+a726 uniA726 2.26 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) 2.30 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.33 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) -U+a727 uniA727 2.26 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) 2.30 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.33 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) -U+a728 uniA728 2.26 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.33 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) -U+a729 uniA729 2.26 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.33 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) -U+a72a uniA72A 2.26 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.33 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) -U+a72b uniA72B 2.26 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.33 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) -U+a72c uniA72C 2.33 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) -U+a72d uniA72D 2.33 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) -U+a72e uniA72E 2.33 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) -U+a72f uniA72F 2.33 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) -U+a730 uniA730 2.26 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) 2.33 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) -U+a731 uniA731 2.26 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) 2.33 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) -U+a732 uniA732 2.26 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) 2.33 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) -U+a733 uniA733 2.26 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) 2.33 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) -U+a734 uniA734 2.26 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.33 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) -U+a735 uniA735 2.26 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.33 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) -U+a736 uniA736 2.26 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.33 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) -U+a737 uniA737 2.26 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.33 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) -U+a738 uniA738 2.26 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.33 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) -U+a739 uniA739 2.26 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.33 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) -U+a73a uniA73A 2.26 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.33 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) -U+a73b uniA73B 2.26 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.33 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) -U+a73c uniA73C 2.26 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.33 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) -U+a73d uniA73D 2.26 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.32 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) -U+a73e uniA73E 2.26 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) 2.33 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) -U+a73f uniA73F 2.26 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) 2.33 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) -U+a740 uniA740 2.34 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) -U+a741 uniA741 2.34 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) -U+a746 uniA746 2.26 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) 2.33 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) -U+a747 uniA747 2.26 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) 2.33 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) -U+a748 uniA748 2.26 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+a749 uniA749 2.26 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+a74a uniA74A 2.26 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.33 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) -U+a74b uniA74B 2.26 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.33 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) -U+a74e uniA74E 2.26 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) 2.33 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) -U+a74f uniA74F 2.26 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) 2.33 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) -U+a750 uniA750 2.32 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+a751 uniA751 2.32 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+a752 uniA752 2.32 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+a753 uniA753 2.32 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+a756 uniA756 2.32 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+a757 uniA757 2.32 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+a764 uniA764 2.32 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+a765 uniA765 2.32 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+a766 uniA766 2.32 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+a767 uniA767 2.32 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+a768 uniA768 2.33 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) -U+a769 uniA769 2.33 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) -U+a77b uniA77B 2.33 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) -U+a77c uniA77C 2.33 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) -U+a780 uniA780 2.26 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) 2.33 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) -U+a781 uniA781 2.26 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) 2.33 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) -U+a782 uniA782 2.27 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.33 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) -U+a783 uniA783 2.27 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.33 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) -U+a784 uniA784 2.33 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) -U+a785 uniA785 2.33 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) -U+a786 uniA786 2.33 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) -U+a787 uniA787 2.33 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) -U+a789 uniA789 2.28 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique) -U+a78a uniA78A 2.28 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique) -U+a78b uniA78B 2.26 -U+a78c uniA78C 2.26 -U+a78d uniA78D 2.31 -U+a78e uniA78E 2.33 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique) -U+a790 uniA790 2.33 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) -U+a791 uniA791 2.33 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) -U+a7a0 uniA7A0 2.34 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+a7a1 uniA7A1 2.34 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+a7a2 uniA7A2 2.34 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+a7a3 uniA7A3 2.34 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+a7a4 uniA7A4 2.34 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+a7a5 uniA7A5 2.34 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+a7a6 uniA7A6 2.34 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+a7a7 uniA7A7 2.34 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+a7a8 uniA7A8 2.34 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+a7a9 uniA7A9 2.34 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+a7aa uniA7AA 2.34 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) -U+a7f8 uniA7F8 2.35 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) -U+a7f9 uniA7F9 2.35 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) -U+a7fa uniA7FA 2.33 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) -U+a7fb uniA7FB 2.26 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) 2.33 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) -U+a7fc uniA7FC 2.26 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) 2.33 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) -U+a7fd uniA7FD 2.26 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) 2.33 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) -U+a7fe uniA7FE 2.26 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) 2.33 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) -U+a7ff uniA7FF 2.26 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) 2.33 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) -U+e000 uniE000 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) -U+e001 uniE001 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) -U+e002 uniE002 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) -U+e003 uniE003 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) -U+e004 uniE004 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) -U+e005 uniE005 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) -U+e006 uniE006 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+e007 uniE007 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) -U+e008 uniE008 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) -U+e009 uniE009 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.5 (Sans ExtraLight) -U+e00a uniE00A 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.5 (Sans ExtraLight) -U+e00b uniE00B 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.5 (Sans ExtraLight) -U+e00c uniE00C 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.5 (Sans ExtraLight) -U+e00d uniE00D 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.5 (Sans ExtraLight) -U+e00e uniE00E 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.5 (Sans ExtraLight) -U+e00f uniE00F 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.5 (Sans ExtraLight) -U+e010 uniE010 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.5 (Sans ExtraLight) -U+e011 uniE011 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.5 (Sans ExtraLight) -U+e012 uniE012 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.5 (Sans ExtraLight) -U+e013 uniE013 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.5 (Sans ExtraLight) -U+e014 uniE014 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.5 (Sans ExtraLight) -U+e015 uniE015 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+e016 uniE016 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+e017 uniE017 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+e018 uniE018 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+e019 uniE019 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+e01a uniE01A 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+e01b uniE01B 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+e01c uniE01C 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+e01d uniE01D 2.4 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+ef00 uni02E5.5 2.32 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+ef01 uni02E6.5 2.32 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+ef02 uni02E7.5 2.32 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+ef03 uni02E8.5 2.32 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+ef04 uni02E9.5 2.32 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+ef05 uni02E5.4 2.32 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+ef06 uni02E6.4 2.32 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+ef07 uni02E7.4 2.32 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+ef08 uni02E8.4 2.32 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+ef09 uni02E9.4 2.32 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+ef0a uni02E5.3 2.32 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+ef0b uni02E6.3 2.32 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+ef0c uni02E7.3 2.32 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+ef0d uni02E8.3 2.32 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+ef0e uni02E9.3 2.32 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+ef0f uni02E5.2 2.32 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+ef10 uni02E6.2 2.32 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+ef11 uni02E7.2 2.32 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+ef12 uni02E8.2 2.32 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+ef13 uni02E9.2 2.32 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+ef14 uni02E5.1 2.32 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+ef15 uni02E6.1 2.32 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+ef16 uni02E7.1 2.32 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+ef17 uni02E8.1 2.32 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+ef18 uni02E9.1 2.32 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+ef19 stem 2.32 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+f000 uniF000 2.10 (Sans) 2.11 (Sans Condensed) -U+f001 uniF001 2.10 (Sans) 2.11 (Sans Condensed) -U+f002 uniF002 2.33 (Sans, Sans Condensed) -U+f003 uniF003 2.33 (Sans, Sans Condensed) -U+f208 uniF208 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+f20a uniF20A 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+f215 uniF215 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+f216 uniF216 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+f217 uniF217 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+f21a uniF21A 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+f21b uniF21B 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+f25f uniF25F 2.6 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+f400 uniF400 2.28 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) 2.34 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) -U+f401 uniF401 2.28 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) 2.34 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) -U+f402 uniF402 2.28 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) 2.34 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) -U+f403 uniF403 2.28 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) 2.34 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) -U+f404 uniF404 2.28 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) 2.34 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) -U+f405 uniF405 2.28 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) 2.34 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) -U+f406 uniF406 2.28 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) 2.34 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) -U+f407 uniF407 2.28 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) 2.34 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) -U+f408 uniF408 2.28 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) 2.34 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) -U+f409 uniF409 2.28 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) 2.34 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) -U+f40a uniF40A 2.28 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) 2.34 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) -U+f40b uniF40B 2.28 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) 2.34 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) -U+f40c uniF40C 2.28 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) 2.34 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) -U+f40d uniF40D 2.28 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) 2.34 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) -U+f40e uniF40E 2.28 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) 2.34 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) -U+f40f uniF40F 2.28 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) 2.34 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) -U+f410 uniF410 2.28 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) 2.34 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) -U+f411 uniF411 2.28 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) 2.34 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) -U+f412 uniF412 2.28 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) 2.34 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) -U+f413 uniF413 2.28 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) 2.34 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) -U+f414 uniF414 2.28 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) 2.34 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) -U+f415 uniF415 2.28 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) 2.34 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) -U+f416 uniF416 2.28 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) 2.34 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) -U+f417 uniF417 2.28 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) 2.34 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) -U+f418 uniF418 2.28 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) 2.34 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) -U+f419 uniF419 2.28 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) 2.34 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) -U+f41a uniF41A 2.28 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) 2.34 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) -U+f41b uniF41B 2.28 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) 2.34 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) -U+f41c uniF41C 2.28 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) 2.34 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) -U+f41d uniF41D 2.28 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) 2.34 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) -U+f41e uniF41E 2.28 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) 2.34 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) -U+f41f uniF41F 2.28 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) 2.34 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) -U+f420 uniF420 2.28 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) 2.34 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) -U+f421 uniF421 2.28 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) 2.34 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) -U+f422 uniF422 2.28 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) 2.34 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) -U+f423 uniF423 2.28 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) 2.34 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) -U+f424 uniF424 2.28 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) 2.34 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) -U+f425 uniF425 2.28 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) 2.34 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique) -U+f426 uniF426 2.28 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) 2.34 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+f428 uniF428 2.28 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) 2.34 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+f429 uniF429 2.34 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+f42a uniF42A 2.34 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+f42b uniF42B 2.34 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+f42c uniF42C 2.34 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+f42d uniF42D 2.34 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+f42e uniF42E 2.34 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+f42f uniF42F 2.34 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+f430 uniF430 2.34 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+f431 uniF431 2.34 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+f432 uniF432 2.34 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+f433 uniF433 2.34 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+f434 uniF434 2.34 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+f435 uniF435 2.34 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+f436 uniF436 2.34 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+f437 uniF437 2.34 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+f438 uniF438 2.34 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+f439 uniF439 2.34 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+f43a uniF43A 2.34 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+f43b uniF43B 2.34 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+f43c uniF43C 2.34 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+f43d uniF43D 2.34 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+f43e uniF43E 2.34 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+f43f uniF43F 2.34 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+f440 uniF440 2.34 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+f441 uniF441 2.34 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+f5c5 uniF5C5 2.9 (Sans Bold Oblique, Sans Condensed Bold Oblique) -U+f6c4 uniF6C4 2.10 (Serif Bold Italic, Serif Italic) 2.11 (Serif Condensed Bold Italic, Serif Condensed Italic) 2.23 (Serif Italic Condensed) -U+f6c5 uniF6C5 2.5 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.7 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.9 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold, Sans Condensed Oblique, Sans Oblique) 2.18 (Sans ExtraLight) 2.23 (Serif Italic Condensed) -U+f6c6 uniF6C6 2.5 (Serif Bold Italic, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+f6c7 uniF6C7 2.11 (Serif Bold Italic, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+f6c8 uniF6C8 2.11 (Serif Bold Italic, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+f6d1 cyrBreve 2.5 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+f6d4 cyrbreve 2.5 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+fb00 uniFB00 2.2 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.5 (Sans ExtraLight) 2.8 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) -U+fb01 fi original -U+fb02 fl original -U+fb03 uniFB03 2.2 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.5 (Sans ExtraLight) 2.8 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) -U+fb04 uniFB04 2.2 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.5 (Sans ExtraLight) 2.8 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) 2.36 (Math TeX Gyre Regular) -U+fb05 uniFB05 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.8 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+fb06 uniFB06 2.5 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.8 (Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+fb13 uniFB13 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+fb14 uniFB14 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+fb15 uniFB15 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+fb16 uniFB16 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+fb17 uniFB17 2.3 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+fb1d uniFB1D 2.9 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+fb1e uniFB1E 2.16 (Sans, Sans Bold, Sans Bold Oblique, Sans Oblique) 2.17 (Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique) -U+fb1f uniFB1F 2.9 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+fb20 uniFB20 2.9 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+fb21 uniFB21 2.16 (Sans, Sans Bold, Sans Bold Oblique, Sans Oblique) 2.17 (Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique) -U+fb22 uniFB22 2.16 (Sans, Sans Bold, Sans Bold Oblique, Sans Oblique) 2.17 (Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique) -U+fb23 uniFB23 2.16 (Sans, Sans Bold, Sans Bold Oblique, Sans Oblique) 2.17 (Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique) -U+fb24 uniFB24 2.16 (Sans, Sans Bold, Sans Bold Oblique, Sans Oblique) 2.17 (Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique) -U+fb25 uniFB25 2.16 (Sans, Sans Bold, Sans Bold Oblique, Sans Oblique) 2.17 (Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique) -U+fb26 uniFB26 2.16 (Sans, Sans Bold, Sans Bold Oblique, Sans Oblique) 2.17 (Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique) -U+fb27 uniFB27 2.16 (Sans, Sans Bold, Sans Bold Oblique, Sans Oblique) 2.17 (Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique) -U+fb28 uniFB28 2.16 (Sans, Sans Bold, Sans Bold Oblique, Sans Oblique) 2.17 (Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique) -U+fb29 uniFB29 2.10 (Sans, Sans Bold, Sans Bold Oblique, Sans ExtraLight, Sans Oblique) 2.11 (Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique) -U+fb2a uniFB2A 2.9 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+fb2b uniFB2B 2.9 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+fb2c uniFB2C 2.9 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+fb2d uniFB2D 2.9 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+fb2e uniFB2E 2.9 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+fb2f uniFB2F 2.9 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+fb30 uniFB30 2.9 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+fb31 uniFB31 2.9 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+fb32 uniFB32 2.9 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+fb33 uniFB33 2.9 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+fb34 uniFB34 2.9 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+fb35 uniFB35 2.9 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+fb36 uniFB36 2.9 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+fb37 uniFB37 2.11 (Sans Condensed Oblique, Sans Oblique) 2.33 (Sans Bold Oblique, Sans Condensed Bold Oblique) -U+fb38 uniFB38 2.9 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+fb39 uniFB39 2.9 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+fb3a uniFB3A 2.9 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+fb3b uniFB3B 2.9 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+fb3c uniFB3C 2.9 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+fb3d uniFB3D 2.33 (Sans Bold Oblique, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+fb3e uniFB3E 2.9 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+fb3f uniFB3F 2.33 (Sans Bold Oblique, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+fb40 uniFB40 2.9 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+fb41 uniFB41 2.9 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+fb42 uniFB42 2.33 (Sans Bold Oblique, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+fb43 uniFB43 2.9 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+fb44 uniFB44 2.9 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+fb45 uniFB45 2.33 (Sans Bold Oblique, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+fb46 uniFB46 2.9 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+fb47 uniFB47 2.9 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+fb48 uniFB48 2.9 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+fb49 uniFB49 2.9 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+fb4a uniFB4A 2.9 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+fb4b uniFB4B 2.9 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+fb4c uniFB4C 2.9 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+fb4d uniFB4D 2.9 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+fb4e uniFB4E 2.9 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+fb4f uniFB4F 2.16 (Sans, Sans Bold, Sans Bold Oblique, Sans Oblique) 2.17 (Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique) -U+fb52 uniFB52 2.4 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) 2.16 (Sans Mono, Sans Mono Bold) -U+fb53 uniFB53 2.4 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) 2.16 (Sans Mono, Sans Mono Bold) -U+fb54 uniFB54 2.4 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) 2.16 (Sans Mono, Sans Mono Bold) -U+fb55 uniFB55 2.4 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) 2.16 (Sans Mono, Sans Mono Bold) -U+fb56 uniFB56 2.4 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) 2.16 (Sans Mono, Sans Mono Bold) -U+fb57 uniFB57 2.4 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) 2.16 (Sans Mono, Sans Mono Bold) -U+fb58 uniFB58 2.4 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) 2.16 (Sans Mono, Sans Mono Bold) -U+fb59 uniFB59 2.4 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) 2.16 (Sans Mono, Sans Mono Bold) -U+fb5a uniFB5A 2.4 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) 2.16 (Sans Mono, Sans Mono Bold) -U+fb5b uniFB5B 2.4 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) 2.16 (Sans Mono, Sans Mono Bold) -U+fb5c uniFB5C 2.4 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) 2.16 (Sans Mono, Sans Mono Bold) -U+fb5d uniFB5D 2.4 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) 2.16 (Sans Mono, Sans Mono Bold) -U+fb5e uniFB5E 2.4 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) 2.16 (Sans Mono, Sans Mono Bold) -U+fb5f uniFB5F 2.4 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) 2.16 (Sans Mono, Sans Mono Bold) -U+fb60 uniFB60 2.4 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) 2.16 (Sans Mono, Sans Mono Bold) -U+fb61 uniFB61 2.4 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) 2.16 (Sans Mono, Sans Mono Bold) -U+fb62 uniFB62 2.4 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) 2.16 (Sans Mono, Sans Mono Bold) -U+fb63 uniFB63 2.4 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) 2.16 (Sans Mono, Sans Mono Bold) -U+fb64 uniFB64 2.4 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) 2.16 (Sans Mono, Sans Mono Bold) -U+fb65 uniFB65 2.4 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) 2.16 (Sans Mono, Sans Mono Bold) -U+fb66 uniFB66 2.4 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) 2.16 (Sans Mono, Sans Mono Bold) -U+fb67 uniFB67 2.4 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) 2.16 (Sans Mono, Sans Mono Bold) -U+fb68 uniFB68 2.4 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) 2.16 (Sans Mono, Sans Mono Bold) -U+fb69 uniFB69 2.4 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) 2.16 (Sans Mono, Sans Mono Bold) -U+fb6a uniFB6A 2.4 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) 2.16 (Sans Mono, Sans Mono Bold) -U+fb6b uniFB6B 2.4 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) 2.16 (Sans Mono, Sans Mono Bold) -U+fb6c uniFB6C 2.4 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) 2.16 (Sans Mono, Sans Mono Bold) -U+fb6d uniFB6D 2.4 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) 2.16 (Sans Mono, Sans Mono Bold) -U+fb6e uniFB6E 2.4 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) 2.16 (Sans Mono, Sans Mono Bold) -U+fb6f uniFB6F 2.4 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) 2.16 (Sans Mono, Sans Mono Bold) -U+fb70 uniFB70 2.4 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) 2.16 (Sans Mono, Sans Mono Bold) -U+fb71 uniFB71 2.4 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) 2.16 (Sans Mono, Sans Mono Bold) -U+fb72 uniFB72 2.4 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) 2.16 (Sans Mono, Sans Mono Bold) -U+fb73 uniFB73 2.4 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) 2.16 (Sans Mono, Sans Mono Bold) -U+fb74 uniFB74 2.4 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) 2.16 (Sans Mono, Sans Mono Bold) -U+fb75 uniFB75 2.4 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) 2.16 (Sans Mono, Sans Mono Bold) -U+fb76 uniFB76 2.4 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) 2.16 (Sans Mono, Sans Mono Bold) -U+fb77 uniFB77 2.4 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) 2.16 (Sans Mono, Sans Mono Bold) -U+fb78 uniFB78 2.4 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) 2.16 (Sans Mono, Sans Mono Bold) -U+fb79 uniFB79 2.4 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) 2.16 (Sans Mono, Sans Mono Bold) -U+fb7a uniFB7A 2.4 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) 2.16 (Sans Mono, Sans Mono Bold) -U+fb7b uniFB7B 2.4 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) 2.16 (Sans Mono, Sans Mono Bold) -U+fb7c uniFB7C 2.4 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) 2.16 (Sans Mono, Sans Mono Bold) -U+fb7d uniFB7D 2.4 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) 2.16 (Sans Mono, Sans Mono Bold) -U+fb7e uniFB7E 2.4 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) 2.16 (Sans Mono, Sans Mono Bold) -U+fb7f uniFB7F 2.4 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) 2.16 (Sans Mono, Sans Mono Bold) -U+fb80 uniFB80 2.4 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) 2.16 (Sans Mono, Sans Mono Bold) -U+fb81 uniFB81 2.4 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) 2.16 (Sans Mono, Sans Mono Bold) -U+fb82 uniFB82 2.31 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) -U+fb83 uniFB83 2.31 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) -U+fb84 uniFB84 2.31 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) -U+fb85 uniFB85 2.31 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) -U+fb86 uniFB86 2.31 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) -U+fb87 uniFB87 2.31 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) -U+fb88 uniFB88 2.31 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) -U+fb89 uniFB89 2.31 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) -U+fb8a uniFB8A 2.4 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) 2.16 (Sans Mono, Sans Mono Bold) -U+fb8b uniFB8B 2.4 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) 2.16 (Sans Mono, Sans Mono Bold) -U+fb8c uniFB8C 2.4 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) 2.16 (Sans Mono, Sans Mono Bold) -U+fb8d uniFB8D 2.4 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) 2.16 (Sans Mono, Sans Mono Bold) -U+fb8e uniFB8E 2.4 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) 2.16 (Sans Mono, Sans Mono Bold) -U+fb8f uniFB8F 2.4 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) 2.16 (Sans Mono, Sans Mono Bold) -U+fb90 uniFB90 2.4 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) 2.16 (Sans Mono, Sans Mono Bold) -U+fb91 uniFB91 2.4 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) 2.16 (Sans Mono, Sans Mono Bold) -U+fb92 uniFB92 2.4 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) 2.16 (Sans Mono, Sans Mono Bold) -U+fb93 uniFB93 2.4 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) 2.16 (Sans Mono, Sans Mono Bold) -U+fb94 uniFB94 2.4 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) 2.16 (Sans Mono, Sans Mono Bold) -U+fb95 uniFB95 2.4 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) 2.16 (Sans Mono, Sans Mono Bold) -U+fb96 uniFB96 2.31 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) -U+fb97 uniFB97 2.31 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) -U+fb98 uniFB98 2.31 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) -U+fb99 uniFB99 2.31 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) -U+fb9a uniFB9A 2.31 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) -U+fb9b uniFB9B 2.31 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) -U+fb9c uniFB9C 2.31 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) -U+fb9d uniFB9D 2.31 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) -U+fb9e uniFB9E 2.4 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) 2.16 (Sans Mono, Sans Mono Bold) -U+fb9f uniFB9F 2.4 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) 2.16 (Sans Mono, Sans Mono Bold) -U+fba0 uniFBA0 2.31 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) -U+fba1 uniFBA1 2.31 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) -U+fba2 uniFBA2 2.31 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) -U+fba3 uniFBA3 2.31 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) -U+fbaa uniFBAA 2.16 (Sans Mono, Sans Mono Bold) 2.31 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) -U+fbab uniFBAB 2.16 (Sans Mono, Sans Mono Bold) 2.31 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) -U+fbac uniFBAC 2.16 (Sans Mono, Sans Mono Bold) 2.31 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) -U+fbad uniFBAD 2.16 (Sans Mono, Sans Mono Bold) 2.31 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) -U+fbd3 uniFBD3 2.31 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) -U+fbd4 uniFBD4 2.31 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) -U+fbd5 uniFBD5 2.31 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) -U+fbd6 uniFBD6 2.31 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) -U+fbd7 uniFBD7 2.35 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) -U+fbd8 uniFBD8 2.35 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) -U+fbd9 uniFBD9 2.7 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) -U+fbda uniFBDA 2.7 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) -U+fbdb uniFBDB 2.35 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) -U+fbdc uniFBDC 2.35 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) -U+fbde uniFBDE 2.35 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) -U+fbdf uniFBDF 2.35 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) -U+fbe4 uniFBE4 2.35 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) -U+fbe5 uniFBE5 2.35 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) -U+fbe6 uniFBE6 2.35 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) -U+fbe7 uniFBE7 2.35 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) -U+fbe8 uniFBE8 2.4 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) 2.16 (Sans Mono, Sans Mono Bold) -U+fbe9 uniFBE9 2.4 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) 2.16 (Sans Mono, Sans Mono Bold) -U+fbfc uniFBFC 2.4 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) 2.16 (Sans Mono, Sans Mono Bold) -U+fbfd uniFBFD 2.4 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) 2.16 (Sans Mono, Sans Mono Bold) -U+fbfe uniFBFE 2.4 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) 2.16 (Sans Mono, Sans Mono Bold) -U+fbff uniFBFF 2.4 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) 2.16 (Sans Mono, Sans Mono Bold) -U+fe00 uniFE00 2.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+fe01 uniFE01 2.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+fe02 uniFE02 2.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+fe03 uniFE03 2.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+fe04 uniFE04 2.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+fe05 uniFE05 2.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+fe06 uniFE06 2.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+fe07 uniFE07 2.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+fe08 uniFE08 2.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+fe09 uniFE09 2.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+fe0a uniFE0A 2.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+fe0b uniFE0B 2.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+fe0c uniFE0C 2.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+fe0d uniFE0D 2.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+fe0e uniFE0E 2.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+fe0f uniFE0F 2.14 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans ExtraLight, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+fe20 uniFE20 2.21 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+fe21 uniFE21 2.21 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+fe22 uniFE22 2.21 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+fe23 uniFE23 2.21 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+fe70 uniFE70 2.4 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) 2.16 (Sans Mono, Sans Mono Bold) -U+fe71 uniFE71 2.4 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) 2.16 (Sans Mono, Sans Mono Bold) -U+fe72 uniFE72 2.4 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) 2.16 (Sans Mono, Sans Mono Bold) -U+fe73 uniFE73 2.4 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) 2.16 (Sans Mono, Sans Mono Bold) -U+fe74 uniFE74 2.4 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) 2.16 (Sans Mono, Sans Mono Bold) -U+fe76 uniFE76 2.4 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) 2.16 (Sans Mono, Sans Mono Bold) -U+fe77 uniFE77 2.4 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) 2.16 (Sans Mono, Sans Mono Bold) -U+fe78 uniFE78 2.4 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) 2.16 (Sans Mono, Sans Mono Bold) -U+fe79 uniFE79 2.4 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) 2.16 (Sans Mono, Sans Mono Bold) -U+fe7a uniFE7A 2.4 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) 2.16 (Sans Mono, Sans Mono Bold) -U+fe7b uniFE7B 2.4 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) 2.16 (Sans Mono, Sans Mono Bold) -U+fe7c uniFE7C 2.4 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) 2.16 (Sans Mono, Sans Mono Bold) -U+fe7d uniFE7D 2.4 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) 2.16 (Sans Mono, Sans Mono Bold) -U+fe7e uniFE7E 2.4 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) 2.16 (Sans Mono, Sans Mono Bold) -U+fe7f uniFE7F 2.4 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) 2.16 (Sans Mono, Sans Mono Bold) -U+fe80 uniFE80 2.4 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) 2.16 (Sans Mono, Sans Mono Bold) -U+fe81 uniFE81 2.4 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) 2.16 (Sans Mono, Sans Mono Bold) -U+fe82 uniFE82 2.4 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) 2.16 (Sans Mono, Sans Mono Bold) -U+fe83 uniFE83 2.4 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) 2.16 (Sans Mono, Sans Mono Bold) -U+fe84 uniFE84 2.4 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) 2.16 (Sans Mono, Sans Mono Bold) -U+fe85 uniFE85 2.4 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) 2.16 (Sans Mono, Sans Mono Bold) -U+fe86 uniFE86 2.4 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) 2.16 (Sans Mono, Sans Mono Bold) -U+fe87 uniFE87 2.4 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) 2.16 (Sans Mono, Sans Mono Bold) -U+fe88 uniFE88 2.4 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) 2.16 (Sans Mono, Sans Mono Bold) -U+fe89 uniFE89 2.4 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) 2.16 (Sans Mono, Sans Mono Bold) -U+fe8a uniFE8A 2.4 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) 2.16 (Sans Mono, Sans Mono Bold) -U+fe8b uniFE8B 2.4 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) 2.16 (Sans Mono, Sans Mono Bold) -U+fe8c uniFE8C 2.4 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) 2.16 (Sans Mono, Sans Mono Bold) -U+fe8d uniFE8D 2.4 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) 2.16 (Sans Mono, Sans Mono Bold) -U+fe8e uniFE8E 2.4 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) 2.16 (Sans Mono, Sans Mono Bold) -U+fe8f uniFE8F 2.4 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) 2.16 (Sans Mono, Sans Mono Bold) -U+fe90 uniFE90 2.4 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) 2.16 (Sans Mono, Sans Mono Bold) -U+fe91 uniFE91 2.4 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) 2.16 (Sans Mono, Sans Mono Bold) -U+fe92 uniFE92 2.4 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) 2.16 (Sans Mono, Sans Mono Bold) -U+fe93 uniFE93 2.4 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) 2.16 (Sans Mono, Sans Mono Bold) -U+fe94 uniFE94 2.4 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) 2.16 (Sans Mono, Sans Mono Bold) -U+fe95 uniFE95 2.4 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) 2.16 (Sans Mono, Sans Mono Bold) -U+fe96 uniFE96 2.4 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) 2.16 (Sans Mono, Sans Mono Bold) -U+fe97 uniFE97 2.4 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) 2.16 (Sans Mono, Sans Mono Bold) -U+fe98 uniFE98 2.4 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) 2.16 (Sans Mono, Sans Mono Bold) -U+fe99 uniFE99 2.4 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) 2.16 (Sans Mono, Sans Mono Bold) -U+fe9a uniFE9A 2.4 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) 2.16 (Sans Mono, Sans Mono Bold) -U+fe9b uniFE9B 2.4 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) 2.16 (Sans Mono, Sans Mono Bold) -U+fe9c uniFE9C 2.4 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) 2.16 (Sans Mono, Sans Mono Bold) -U+fe9d uniFE9D 2.4 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) 2.16 (Sans Mono, Sans Mono Bold) -U+fe9e uniFE9E 2.4 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) 2.16 (Sans Mono, Sans Mono Bold) -U+fe9f uniFE9F 2.4 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) 2.16 (Sans Mono, Sans Mono Bold) -U+fea0 uniFEA0 2.4 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) 2.16 (Sans Mono, Sans Mono Bold) -U+fea1 uniFEA1 2.4 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) 2.16 (Sans Mono, Sans Mono Bold) -U+fea2 uniFEA2 2.4 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) 2.16 (Sans Mono, Sans Mono Bold) -U+fea3 uniFEA3 2.4 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) 2.16 (Sans Mono, Sans Mono Bold) -U+fea4 uniFEA4 2.4 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) 2.16 (Sans Mono, Sans Mono Bold) -U+fea5 uniFEA5 2.4 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) 2.16 (Sans Mono, Sans Mono Bold) -U+fea6 uniFEA6 2.4 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) 2.16 (Sans Mono, Sans Mono Bold) -U+fea7 uniFEA7 2.4 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) 2.16 (Sans Mono, Sans Mono Bold) -U+fea8 uniFEA8 2.4 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) 2.16 (Sans Mono, Sans Mono Bold) -U+fea9 uniFEA9 2.4 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) 2.16 (Sans Mono, Sans Mono Bold) -U+feaa uniFEAA 2.4 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) 2.16 (Sans Mono, Sans Mono Bold) -U+feab uniFEAB 2.4 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) 2.16 (Sans Mono, Sans Mono Bold) -U+feac uniFEAC 2.4 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) 2.16 (Sans Mono, Sans Mono Bold) -U+fead uniFEAD 2.4 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) 2.16 (Sans Mono, Sans Mono Bold) -U+feae uniFEAE 2.4 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) 2.16 (Sans Mono, Sans Mono Bold) -U+feaf uniFEAF 2.4 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) 2.16 (Sans Mono, Sans Mono Bold) -U+feb0 uniFEB0 2.4 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) 2.16 (Sans Mono, Sans Mono Bold) -U+feb1 uniFEB1 2.4 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) 2.16 (Sans Mono, Sans Mono Bold) -U+feb2 uniFEB2 2.4 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) 2.16 (Sans Mono, Sans Mono Bold) -U+feb3 uniFEB3 2.4 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) 2.16 (Sans Mono, Sans Mono Bold) -U+feb4 uniFEB4 2.4 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) 2.16 (Sans Mono, Sans Mono Bold) -U+feb5 uniFEB5 2.4 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) 2.16 (Sans Mono, Sans Mono Bold) -U+feb6 uniFEB6 2.4 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) 2.16 (Sans Mono, Sans Mono Bold) -U+feb7 uniFEB7 2.4 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) 2.16 (Sans Mono, Sans Mono Bold) -U+feb8 uniFEB8 2.4 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) 2.16 (Sans Mono, Sans Mono Bold) -U+feb9 uniFEB9 2.4 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) 2.16 (Sans Mono, Sans Mono Bold) -U+feba uniFEBA 2.4 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) 2.16 (Sans Mono, Sans Mono Bold) -U+febb uniFEBB 2.4 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) 2.16 (Sans Mono, Sans Mono Bold) -U+febc uniFEBC 2.4 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) 2.16 (Sans Mono, Sans Mono Bold) -U+febd uniFEBD 2.4 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) 2.16 (Sans Mono, Sans Mono Bold) -U+febe uniFEBE 2.4 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) 2.16 (Sans Mono, Sans Mono Bold) -U+febf uniFEBF 2.4 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) 2.16 (Sans Mono, Sans Mono Bold) -U+fec0 uniFEC0 2.4 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) 2.16 (Sans Mono, Sans Mono Bold) -U+fec1 uniFEC1 2.4 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) 2.16 (Sans Mono, Sans Mono Bold) -U+fec2 uniFEC2 2.4 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) 2.16 (Sans Mono, Sans Mono Bold) -U+fec3 uniFEC3 2.4 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) 2.16 (Sans Mono, Sans Mono Bold) -U+fec4 uniFEC4 2.4 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) 2.16 (Sans Mono, Sans Mono Bold) -U+fec5 uniFEC5 2.4 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) 2.16 (Sans Mono, Sans Mono Bold) -U+fec6 uniFEC6 2.4 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) 2.16 (Sans Mono, Sans Mono Bold) -U+fec7 uniFEC7 2.4 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) 2.16 (Sans Mono, Sans Mono Bold) -U+fec8 uniFEC8 2.4 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) 2.16 (Sans Mono, Sans Mono Bold) -U+fec9 uniFEC9 2.4 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) 2.16 (Sans Mono, Sans Mono Bold) -U+feca uniFECA 2.4 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) 2.16 (Sans Mono, Sans Mono Bold) -U+fecb uniFECB 2.4 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) 2.16 (Sans Mono, Sans Mono Bold) -U+fecc uniFECC 2.4 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) 2.16 (Sans Mono, Sans Mono Bold) -U+fecd uniFECD 2.4 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) 2.16 (Sans Mono, Sans Mono Bold) -U+fece uniFECE 2.4 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) 2.16 (Sans Mono, Sans Mono Bold) -U+fecf uniFECF 2.4 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) 2.16 (Sans Mono, Sans Mono Bold) -U+fed0 uniFED0 2.4 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) 2.16 (Sans Mono, Sans Mono Bold) -U+fed1 uniFED1 2.4 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) 2.16 (Sans Mono, Sans Mono Bold) -U+fed2 uniFED2 2.4 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) 2.16 (Sans Mono, Sans Mono Bold) -U+fed3 uniFED3 2.4 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) 2.16 (Sans Mono, Sans Mono Bold) -U+fed4 uniFED4 2.4 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) 2.16 (Sans Mono, Sans Mono Bold) -U+fed5 uniFED5 2.4 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) 2.16 (Sans Mono, Sans Mono Bold) -U+fed6 uniFED6 2.4 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) 2.16 (Sans Mono, Sans Mono Bold) -U+fed7 uniFED7 2.4 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) 2.16 (Sans Mono, Sans Mono Bold) -U+fed8 uniFED8 2.4 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) 2.16 (Sans Mono, Sans Mono Bold) -U+fed9 uniFED9 2.4 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) 2.16 (Sans Mono, Sans Mono Bold) -U+feda uniFEDA 2.4 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) 2.16 (Sans Mono, Sans Mono Bold) -U+fedb uniFEDB 2.4 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) 2.16 (Sans Mono, Sans Mono Bold) -U+fedc uniFEDC 2.4 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) 2.16 (Sans Mono, Sans Mono Bold) -U+fedd uniFEDD 2.4 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) 2.16 (Sans Mono, Sans Mono Bold) -U+fede uniFEDE 2.4 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) 2.16 (Sans Mono, Sans Mono Bold) -U+fedf uniFEDF 2.4 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) 2.16 (Sans Mono, Sans Mono Bold) -U+fee0 uniFEE0 2.4 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) 2.16 (Sans Mono, Sans Mono Bold) -U+fee1 uniFEE1 2.4 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) 2.16 (Sans Mono, Sans Mono Bold) -U+fee2 uniFEE2 2.4 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) 2.16 (Sans Mono, Sans Mono Bold) -U+fee3 uniFEE3 2.4 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) 2.16 (Sans Mono, Sans Mono Bold) -U+fee4 uniFEE4 2.4 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) 2.16 (Sans Mono, Sans Mono Bold) -U+fee5 uniFEE5 2.4 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) 2.16 (Sans Mono, Sans Mono Bold) -U+fee6 uniFEE6 2.4 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) 2.16 (Sans Mono, Sans Mono Bold) -U+fee7 uniFEE7 2.4 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) 2.16 (Sans Mono, Sans Mono Bold) -U+fee8 uniFEE8 2.4 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) 2.16 (Sans Mono, Sans Mono Bold) -U+fee9 uniFEE9 2.4 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) 2.16 (Sans Mono, Sans Mono Bold) -U+feea uniFEEA 2.4 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) 2.16 (Sans Mono, Sans Mono Bold) -U+feeb uniFEEB 2.4 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) 2.16 (Sans Mono, Sans Mono Bold) -U+feec uniFEEC 2.4 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) 2.16 (Sans Mono, Sans Mono Bold) -U+feed uniFEED 2.4 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) 2.16 (Sans Mono, Sans Mono Bold) -U+feee uniFEEE 2.4 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) 2.16 (Sans Mono, Sans Mono Bold) -U+feef uniFEEF 2.4 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) 2.16 (Sans Mono, Sans Mono Bold) -U+fef0 uniFEF0 2.4 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) 2.16 (Sans Mono, Sans Mono Bold) -U+fef1 uniFEF1 2.4 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) 2.16 (Sans Mono, Sans Mono Bold) -U+fef2 uniFEF2 2.4 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) 2.16 (Sans Mono, Sans Mono Bold) -U+fef3 uniFEF3 2.4 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) 2.16 (Sans Mono, Sans Mono Bold) -U+fef4 uniFEF4 2.4 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) 2.16 (Sans Mono, Sans Mono Bold) -U+fef5 uniFEF5 2.4 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) 2.16 (Sans Mono, Sans Mono Bold) -U+fef6 uniFEF6 2.4 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) 2.16 (Sans Mono, Sans Mono Bold) -U+fef7 uniFEF7 2.4 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) 2.16 (Sans Mono, Sans Mono Bold) -U+fef8 uniFEF8 2.4 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) 2.16 (Sans Mono, Sans Mono Bold) -U+fef9 uniFEF9 2.4 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) 2.16 (Sans Mono, Sans Mono Bold) -U+fefa uniFEFA 2.4 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) 2.16 (Sans Mono, Sans Mono Bold) -U+fefb uniFEFB 2.4 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) 2.16 (Sans Mono, Sans Mono Bold) -U+fefc uniFEFC 2.4 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) 2.16 (Sans Mono, Sans Mono Bold) -U+feff uniFEFF 2.4 (Sans, Sans Bold, Sans Condensed, Sans Condensed Bold) 2.16 (Sans Mono, Sans Mono Bold) 2.36 (Math TeX Gyre Regular) -U+fff9 uniFFF9 2.22 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+fffa uniFFFA 2.22 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+fffb uniFFFB 2.22 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+fffc uniFFFC 2.22 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique, Sans Oblique, Serif, Serif Bold, Serif Bold Italic, Serif Condensed, Serif Condensed Bold, Serif Condensed Bold Italic, Serif Condensed Italic, Serif Italic) 2.23 (Serif Italic Condensed) -U+fffd uniFFFD 1.12 -U+10300 u10300 2.33 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+10301 u10301 2.33 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+10302 u10302 2.33 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+10303 u10303 2.33 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+10304 u10304 2.33 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+10305 u10305 2.33 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+10306 u10306 2.33 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+10307 u10307 2.33 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+10308 u10308 2.33 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+10309 u10309 2.33 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1030a u1030A 2.33 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1030b u1030B 2.33 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1030c u1030C 2.33 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1030d u1030D 2.33 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1030e u1030E 2.33 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1030f u1030F 2.33 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+10310 u10310 2.33 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+10311 u10311 2.33 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+10312 u10312 2.33 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+10313 u10313 2.33 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+10314 u10314 2.33 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+10315 u10315 2.33 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+10316 u10316 2.33 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+10317 u10317 2.33 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+10318 u10318 2.33 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+10319 u10319 2.33 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1031a u1031A 2.33 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1031b u1031B 2.33 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1031c u1031C 2.33 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1031d u1031D 2.33 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1031e u1031E 2.33 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+10320 u10320 2.33 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+10321 u10321 2.33 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+10322 u10322 2.33 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+10323 u10323 2.33 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1d300 u1D300 2.18 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1d301 u1D301 2.18 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1d302 u1D302 2.18 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1d303 u1D303 2.18 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1d304 u1D304 2.18 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1d305 u1D305 2.18 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1d306 u1D306 2.18 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1d307 u1D307 2.18 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1d308 u1D308 2.18 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1d309 u1D309 2.18 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1d30a u1D30A 2.18 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1d30b u1D30B 2.18 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1d30c u1D30C 2.18 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1d30d u1D30D 2.18 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1d30e u1D30E 2.18 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1d30f u1D30F 2.18 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1d310 u1D310 2.18 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1d311 u1D311 2.18 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1d312 u1D312 2.18 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1d313 u1D313 2.18 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1d314 u1D314 2.18 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1d315 u1D315 2.18 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1d316 u1D316 2.18 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1d317 u1D317 2.18 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1d318 u1D318 2.18 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1d319 u1D319 2.18 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1d31a u1D31A 2.18 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1d31b u1D31B 2.18 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1d31c u1D31C 2.18 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1d31d u1D31D 2.18 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1d31e u1D31E 2.18 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1d31f u1D31F 2.18 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1d320 u1D320 2.18 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1d321 u1D321 2.18 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1d322 u1D322 2.18 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1d323 u1D323 2.18 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1d324 u1D324 2.18 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1d325 u1D325 2.18 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1d326 u1D326 2.18 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1d327 u1D327 2.18 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1d328 u1D328 2.18 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1d329 u1D329 2.18 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1d32a u1D32A 2.18 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1d32b u1D32B 2.18 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1d32c u1D32C 2.18 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1d32d u1D32D 2.18 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1d32e u1D32E 2.18 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1d32f u1D32F 2.18 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1d330 u1D330 2.18 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1d331 u1D331 2.18 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1d332 u1D332 2.18 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1d333 u1D333 2.18 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1d334 u1D334 2.18 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1d335 u1D335 2.18 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1d336 u1D336 2.18 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1d337 u1D337 2.18 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1d338 u1D338 2.18 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1d339 u1D339 2.18 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1d33a u1D33A 2.18 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1d33b u1D33B 2.18 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1d33c u1D33C 2.18 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1d33d u1D33D 2.18 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1d33e u1D33E 2.18 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1d33f u1D33F 2.18 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1d340 u1D340 2.18 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1d341 u1D341 2.18 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1d342 u1D342 2.18 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1d343 u1D343 2.18 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1d344 u1D344 2.18 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1d345 u1D345 2.18 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1d346 u1D346 2.18 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1d347 u1D347 2.18 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1d348 u1D348 2.18 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1d349 u1D349 2.18 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1d34a u1D34A 2.18 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1d34b u1D34B 2.18 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1d34c u1D34C 2.18 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1d34d u1D34D 2.18 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1d34e u1D34E 2.18 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1d34f u1D34F 2.18 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1d350 u1D350 2.18 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1d351 u1D351 2.18 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1d352 u1D352 2.18 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1d353 u1D353 2.18 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1d354 u1D354 2.18 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1d355 u1D355 2.18 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1d356 u1D356 2.18 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1d400 u1D400 2.23 (Serif Bold, Serif Condensed Bold) 2.36 (Math TeX Gyre Regular) -U+1d401 u1D401 2.23 (Serif Bold, Serif Condensed Bold) 2.36 (Math TeX Gyre Regular) -U+1d402 u1D402 2.23 (Serif Bold, Serif Condensed Bold) 2.36 (Math TeX Gyre Regular) -U+1d403 u1D403 2.23 (Serif Bold, Serif Condensed Bold) 2.36 (Math TeX Gyre Regular) -U+1d404 u1D404 2.23 (Serif Bold, Serif Condensed Bold) 2.36 (Math TeX Gyre Regular) -U+1d405 u1D405 2.23 (Serif Bold, Serif Condensed Bold) 2.36 (Math TeX Gyre Regular) -U+1d406 u1D406 2.23 (Serif Bold, Serif Condensed Bold) 2.36 (Math TeX Gyre Regular) -U+1d407 u1D407 2.23 (Serif Bold, Serif Condensed Bold) 2.36 (Math TeX Gyre Regular) -U+1d408 u1D408 2.23 (Serif Bold, Serif Condensed Bold) 2.36 (Math TeX Gyre Regular) -U+1d409 u1D409 2.23 (Serif Bold, Serif Condensed Bold) 2.36 (Math TeX Gyre Regular) -U+1d40a u1D40A 2.23 (Serif Bold, Serif Condensed Bold) 2.36 (Math TeX Gyre Regular) -U+1d40b u1D40B 2.23 (Serif Bold, Serif Condensed Bold) 2.36 (Math TeX Gyre Regular) -U+1d40c u1D40C 2.23 (Serif Bold, Serif Condensed Bold) 2.36 (Math TeX Gyre Regular) -U+1d40d u1D40D 2.23 (Serif Bold, Serif Condensed Bold) 2.36 (Math TeX Gyre Regular) -U+1d40e u1D40E 2.23 (Serif Bold, Serif Condensed Bold) 2.36 (Math TeX Gyre Regular) -U+1d40f u1D40F 2.23 (Serif Bold, Serif Condensed Bold) 2.36 (Math TeX Gyre Regular) -U+1d410 u1D410 2.23 (Serif Bold, Serif Condensed Bold) 2.36 (Math TeX Gyre Regular) -U+1d411 u1D411 2.23 (Serif Bold, Serif Condensed Bold) 2.36 (Math TeX Gyre Regular) -U+1d412 u1D412 2.23 (Serif Bold, Serif Condensed Bold) 2.36 (Math TeX Gyre Regular) -U+1d413 u1D413 2.23 (Serif Bold, Serif Condensed Bold) 2.36 (Math TeX Gyre Regular) -U+1d414 u1D414 2.23 (Serif Bold, Serif Condensed Bold) 2.36 (Math TeX Gyre Regular) -U+1d415 u1D415 2.23 (Serif Bold, Serif Condensed Bold) 2.36 (Math TeX Gyre Regular) -U+1d416 u1D416 2.23 (Serif Bold, Serif Condensed Bold) 2.36 (Math TeX Gyre Regular) -U+1d417 u1D417 2.23 (Serif Bold, Serif Condensed Bold) 2.36 (Math TeX Gyre Regular) -U+1d418 u1D418 2.23 (Serif Bold, Serif Condensed Bold) 2.36 (Math TeX Gyre Regular) -U+1d419 u1D419 2.23 (Serif Bold, Serif Condensed Bold) 2.36 (Math TeX Gyre Regular) -U+1d41a u1D41A 2.23 (Serif Bold, Serif Condensed Bold) 2.36 (Math TeX Gyre Regular) -U+1d41b u1D41B 2.23 (Serif Bold, Serif Condensed Bold) 2.36 (Math TeX Gyre Regular) -U+1d41c u1D41C 2.23 (Serif Bold, Serif Condensed Bold) 2.36 (Math TeX Gyre Regular) -U+1d41d u1D41D 2.23 (Serif Bold, Serif Condensed Bold) 2.36 (Math TeX Gyre Regular) -U+1d41e u1D41E 2.23 (Serif Bold, Serif Condensed Bold) 2.36 (Math TeX Gyre Regular) -U+1d41f u1D41F 2.23 (Serif Bold, Serif Condensed Bold) 2.36 (Math TeX Gyre Regular) -U+1d420 u1D420 2.23 (Serif Bold, Serif Condensed Bold) 2.36 (Math TeX Gyre Regular) -U+1d421 u1D421 2.23 (Serif Bold, Serif Condensed Bold) 2.36 (Math TeX Gyre Regular) -U+1d422 u1D422 2.23 (Serif Bold, Serif Condensed Bold) 2.36 (Math TeX Gyre Regular) -U+1d423 u1D423 2.23 (Serif Bold, Serif Condensed Bold) 2.36 (Math TeX Gyre Regular) -U+1d424 u1D424 2.23 (Serif Bold, Serif Condensed Bold) 2.36 (Math TeX Gyre Regular) -U+1d425 u1D425 2.23 (Serif Bold, Serif Condensed Bold) 2.36 (Math TeX Gyre Regular) -U+1d426 u1D426 2.23 (Serif Bold, Serif Condensed Bold) 2.36 (Math TeX Gyre Regular) -U+1d427 u1D427 2.23 (Serif Bold, Serif Condensed Bold) 2.36 (Math TeX Gyre Regular) -U+1d428 u1D428 2.23 (Serif Bold, Serif Condensed Bold) 2.36 (Math TeX Gyre Regular) -U+1d429 u1D429 2.23 (Serif Bold, Serif Condensed Bold) 2.36 (Math TeX Gyre Regular) -U+1d42a u1D42A 2.23 (Serif Bold, Serif Condensed Bold) 2.36 (Math TeX Gyre Regular) -U+1d42b u1D42B 2.23 (Serif Bold, Serif Condensed Bold) 2.36 (Math TeX Gyre Regular) -U+1d42c u1D42C 2.23 (Serif Bold, Serif Condensed Bold) 2.36 (Math TeX Gyre Regular) -U+1d42d u1D42D 2.23 (Serif Bold, Serif Condensed Bold) 2.36 (Math TeX Gyre Regular) -U+1d42e u1D42E 2.23 (Serif Bold, Serif Condensed Bold) 2.36 (Math TeX Gyre Regular) -U+1d42f u1D42F 2.23 (Serif Bold, Serif Condensed Bold) 2.36 (Math TeX Gyre Regular) -U+1d430 u1D430 2.23 (Serif Bold, Serif Condensed Bold) 2.36 (Math TeX Gyre Regular) -U+1d431 u1D431 2.23 (Serif Bold, Serif Condensed Bold) 2.36 (Math TeX Gyre Regular) -U+1d432 u1D432 2.23 (Serif Bold, Serif Condensed Bold) 2.36 (Math TeX Gyre Regular) -U+1d433 u1D433 2.23 (Serif Bold, Serif Condensed Bold) 2.36 (Math TeX Gyre Regular) -U+1d434 u1D434 2.23 (Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) 2.35 (Serif, Serif Condensed) 2.36 (Math TeX Gyre Regular) -U+1d435 u1D435 2.23 (Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) 2.35 (Serif, Serif Condensed) 2.36 (Math TeX Gyre Regular) -U+1d436 u1D436 2.23 (Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) 2.35 (Serif, Serif Condensed) 2.36 (Math TeX Gyre Regular) -U+1d437 u1D437 2.23 (Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) 2.35 (Serif, Serif Condensed) 2.36 (Math TeX Gyre Regular) -U+1d438 u1D438 2.23 (Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) 2.35 (Serif, Serif Condensed) 2.36 (Math TeX Gyre Regular) -U+1d439 u1D439 2.23 (Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) 2.35 (Serif, Serif Condensed) 2.36 (Math TeX Gyre Regular) -U+1d43a u1D43A 2.23 (Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) 2.35 (Serif, Serif Condensed) 2.36 (Math TeX Gyre Regular) -U+1d43b u1D43B 2.23 (Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) 2.35 (Serif, Serif Condensed) 2.36 (Math TeX Gyre Regular) -U+1d43c u1D43C 2.23 (Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) 2.35 (Serif, Serif Condensed) 2.36 (Math TeX Gyre Regular) -U+1d43d u1D43D 2.23 (Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) 2.35 (Serif, Serif Condensed) 2.36 (Math TeX Gyre Regular) -U+1d43e u1D43E 2.23 (Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) 2.35 (Serif, Serif Condensed) 2.36 (Math TeX Gyre Regular) -U+1d43f u1D43F 2.23 (Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) 2.35 (Serif, Serif Condensed) 2.36 (Math TeX Gyre Regular) -U+1d440 u1D440 2.23 (Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) 2.35 (Serif, Serif Condensed) 2.36 (Math TeX Gyre Regular) -U+1d441 u1D441 2.23 (Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) 2.35 (Serif, Serif Condensed) 2.36 (Math TeX Gyre Regular) -U+1d442 u1D442 2.23 (Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) 2.35 (Serif, Serif Condensed) 2.36 (Math TeX Gyre Regular) -U+1d443 u1D443 2.23 (Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) 2.35 (Serif, Serif Condensed) 2.36 (Math TeX Gyre Regular) -U+1d444 u1D444 2.23 (Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) 2.35 (Serif, Serif Condensed) 2.36 (Math TeX Gyre Regular) -U+1d445 u1D445 2.23 (Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) 2.35 (Serif, Serif Condensed) 2.36 (Math TeX Gyre Regular) -U+1d446 u1D446 2.23 (Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) 2.35 (Serif, Serif Condensed) 2.36 (Math TeX Gyre Regular) -U+1d447 u1D447 2.23 (Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) 2.35 (Serif, Serif Condensed) 2.36 (Math TeX Gyre Regular) -U+1d448 u1D448 2.23 (Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) 2.35 (Serif, Serif Condensed) 2.36 (Math TeX Gyre Regular) -U+1d449 u1D449 2.23 (Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) 2.35 (Serif, Serif Condensed) 2.36 (Math TeX Gyre Regular) -U+1d44a u1D44A 2.23 (Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) 2.35 (Serif, Serif Condensed) 2.36 (Math TeX Gyre Regular) -U+1d44b u1D44B 2.23 (Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) 2.35 (Serif, Serif Condensed) 2.36 (Math TeX Gyre Regular) -U+1d44c u1D44C 2.23 (Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) 2.35 (Serif, Serif Condensed) 2.36 (Math TeX Gyre Regular) -U+1d44d u1D44D 2.23 (Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) 2.35 (Serif, Serif Condensed) 2.36 (Math TeX Gyre Regular) -U+1d44e u1D44E 2.23 (Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) 2.35 (Serif, Serif Condensed) 2.36 (Math TeX Gyre Regular) -U+1d44f u1D44F 2.23 (Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) 2.35 (Serif, Serif Condensed) 2.36 (Math TeX Gyre Regular) -U+1d450 u1D450 2.23 (Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) 2.35 (Serif, Serif Condensed) 2.36 (Math TeX Gyre Regular) -U+1d451 u1D451 2.23 (Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) 2.35 (Serif, Serif Condensed) 2.36 (Math TeX Gyre Regular) -U+1d452 u1D452 2.23 (Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) 2.35 (Serif, Serif Condensed) 2.36 (Math TeX Gyre Regular) -U+1d453 u1D453 2.23 (Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) 2.35 (Serif, Serif Condensed) 2.36 (Math TeX Gyre Regular) -U+1d454 u1D454 2.23 (Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) 2.35 (Serif, Serif Condensed) 2.36 (Math TeX Gyre Regular) -U+1d456 u1D456 2.23 (Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) 2.35 (Serif, Serif Condensed) 2.36 (Math TeX Gyre Regular) -U+1d457 u1D457 2.23 (Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) 2.35 (Serif, Serif Condensed) 2.36 (Math TeX Gyre Regular) -U+1d458 u1D458 2.23 (Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) 2.35 (Serif, Serif Condensed) 2.36 (Math TeX Gyre Regular) -U+1d459 u1D459 2.23 (Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) 2.35 (Serif, Serif Condensed) 2.36 (Math TeX Gyre Regular) -U+1d45a u1D45A 2.23 (Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) 2.35 (Serif, Serif Condensed) 2.36 (Math TeX Gyre Regular) -U+1d45b u1D45B 2.23 (Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) 2.35 (Serif, Serif Condensed) 2.36 (Math TeX Gyre Regular) -U+1d45c u1D45C 2.23 (Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) 2.35 (Serif, Serif Condensed) 2.36 (Math TeX Gyre Regular) -U+1d45d u1D45D 2.23 (Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) 2.35 (Serif, Serif Condensed) 2.36 (Math TeX Gyre Regular) -U+1d45e u1D45E 2.23 (Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) 2.35 (Serif, Serif Condensed) 2.36 (Math TeX Gyre Regular) -U+1d45f u1D45F 2.23 (Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) 2.35 (Serif, Serif Condensed) 2.36 (Math TeX Gyre Regular) -U+1d460 u1D460 2.23 (Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) 2.35 (Serif, Serif Condensed) 2.36 (Math TeX Gyre Regular) -U+1d461 u1D461 2.23 (Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) 2.35 (Serif, Serif Condensed) 2.36 (Math TeX Gyre Regular) -U+1d462 u1D462 2.23 (Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) 2.35 (Serif, Serif Condensed) 2.36 (Math TeX Gyre Regular) -U+1d463 u1D463 2.23 (Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) 2.35 (Serif, Serif Condensed) 2.36 (Math TeX Gyre Regular) -U+1d464 u1D464 2.23 (Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) 2.35 (Serif, Serif Condensed) 2.36 (Math TeX Gyre Regular) -U+1d465 u1D465 2.23 (Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) 2.35 (Serif, Serif Condensed) 2.36 (Math TeX Gyre Regular) -U+1d466 u1D466 2.23 (Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) 2.35 (Serif, Serif Condensed) 2.36 (Math TeX Gyre Regular) -U+1d467 u1D467 2.23 (Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) 2.35 (Serif, Serif Condensed) 2.36 (Math TeX Gyre Regular) -U+1d468 u1D468 2.23 (Serif Bold Italic, Serif Condensed Bold Italic) 2.36 (Math TeX Gyre Regular) -U+1d469 u1D469 2.23 (Serif Bold Italic, Serif Condensed Bold Italic) 2.36 (Math TeX Gyre Regular) -U+1d46a u1D46A 2.23 (Serif Bold Italic, Serif Condensed Bold Italic) 2.36 (Math TeX Gyre Regular) -U+1d46b u1D46B 2.23 (Serif Bold Italic, Serif Condensed Bold Italic) 2.36 (Math TeX Gyre Regular) -U+1d46c u1D46C 2.23 (Serif Bold Italic, Serif Condensed Bold Italic) 2.36 (Math TeX Gyre Regular) -U+1d46d u1D46D 2.23 (Serif Bold Italic, Serif Condensed Bold Italic) 2.36 (Math TeX Gyre Regular) -U+1d46e u1D46E 2.23 (Serif Bold Italic, Serif Condensed Bold Italic) 2.36 (Math TeX Gyre Regular) -U+1d46f u1D46F 2.23 (Serif Bold Italic, Serif Condensed Bold Italic) 2.36 (Math TeX Gyre Regular) -U+1d470 u1D470 2.23 (Serif Bold Italic, Serif Condensed Bold Italic) 2.36 (Math TeX Gyre Regular) -U+1d471 u1D471 2.23 (Serif Bold Italic, Serif Condensed Bold Italic) 2.36 (Math TeX Gyre Regular) -U+1d472 u1D472 2.23 (Serif Bold Italic, Serif Condensed Bold Italic) 2.36 (Math TeX Gyre Regular) -U+1d473 u1D473 2.23 (Serif Bold Italic, Serif Condensed Bold Italic) 2.36 (Math TeX Gyre Regular) -U+1d474 u1D474 2.23 (Serif Bold Italic, Serif Condensed Bold Italic) 2.36 (Math TeX Gyre Regular) -U+1d475 u1D475 2.23 (Serif Bold Italic, Serif Condensed Bold Italic) 2.36 (Math TeX Gyre Regular) -U+1d476 u1D476 2.23 (Serif Bold Italic, Serif Condensed Bold Italic) 2.36 (Math TeX Gyre Regular) -U+1d477 u1D477 2.23 (Serif Bold Italic, Serif Condensed Bold Italic) 2.36 (Math TeX Gyre Regular) -U+1d478 u1D478 2.23 (Serif Bold Italic, Serif Condensed Bold Italic) 2.36 (Math TeX Gyre Regular) -U+1d479 u1D479 2.23 (Serif Bold Italic, Serif Condensed Bold Italic) 2.36 (Math TeX Gyre Regular) -U+1d47a u1D47A 2.23 (Serif Bold Italic, Serif Condensed Bold Italic) 2.36 (Math TeX Gyre Regular) -U+1d47b u1D47B 2.23 (Serif Bold Italic, Serif Condensed Bold Italic) 2.36 (Math TeX Gyre Regular) -U+1d47c u1D47C 2.23 (Serif Bold Italic, Serif Condensed Bold Italic) 2.36 (Math TeX Gyre Regular) -U+1d47d u1D47D 2.23 (Serif Bold Italic, Serif Condensed Bold Italic) 2.36 (Math TeX Gyre Regular) -U+1d47e u1D47E 2.23 (Serif Bold Italic, Serif Condensed Bold Italic) 2.36 (Math TeX Gyre Regular) -U+1d47f u1D47F 2.23 (Serif Bold Italic, Serif Condensed Bold Italic) 2.36 (Math TeX Gyre Regular) -U+1d480 u1D480 2.23 (Serif Bold Italic, Serif Condensed Bold Italic) 2.36 (Math TeX Gyre Regular) -U+1d481 u1D481 2.23 (Serif Bold Italic, Serif Condensed Bold Italic) 2.36 (Math TeX Gyre Regular) -U+1d482 u1D482 2.23 (Serif Bold Italic, Serif Condensed Bold Italic) 2.36 (Math TeX Gyre Regular) -U+1d483 u1D483 2.23 (Serif Bold Italic, Serif Condensed Bold Italic) 2.36 (Math TeX Gyre Regular) -U+1d484 u1D484 2.23 (Serif Bold Italic, Serif Condensed Bold Italic) 2.36 (Math TeX Gyre Regular) -U+1d485 u1D485 2.23 (Serif Bold Italic, Serif Condensed Bold Italic) 2.36 (Math TeX Gyre Regular) -U+1d486 u1D486 2.23 (Serif Bold Italic, Serif Condensed Bold Italic) 2.36 (Math TeX Gyre Regular) -U+1d487 u1D487 2.23 (Serif Bold Italic, Serif Condensed Bold Italic) 2.36 (Math TeX Gyre Regular) -U+1d488 u1D488 2.23 (Serif Bold Italic, Serif Condensed Bold Italic) 2.36 (Math TeX Gyre Regular) -U+1d489 u1D489 2.23 (Serif Bold Italic, Serif Condensed Bold Italic) 2.36 (Math TeX Gyre Regular) -U+1d48a u1D48A 2.23 (Serif Bold Italic, Serif Condensed Bold Italic) 2.36 (Math TeX Gyre Regular) -U+1d48b u1D48B 2.23 (Serif Bold Italic, Serif Condensed Bold Italic) 2.36 (Math TeX Gyre Regular) -U+1d48c u1D48C 2.23 (Serif Bold Italic, Serif Condensed Bold Italic) 2.36 (Math TeX Gyre Regular) -U+1d48d u1D48D 2.23 (Serif Bold Italic, Serif Condensed Bold Italic) 2.36 (Math TeX Gyre Regular) -U+1d48e u1D48E 2.23 (Serif Bold Italic, Serif Condensed Bold Italic) 2.36 (Math TeX Gyre Regular) -U+1d48f u1D48F 2.23 (Serif Bold Italic, Serif Condensed Bold Italic) 2.36 (Math TeX Gyre Regular) -U+1d490 u1D490 2.23 (Serif Bold Italic, Serif Condensed Bold Italic) 2.36 (Math TeX Gyre Regular) -U+1d491 u1D491 2.23 (Serif Bold Italic, Serif Condensed Bold Italic) 2.36 (Math TeX Gyre Regular) -U+1d492 u1D492 2.23 (Serif Bold Italic, Serif Condensed Bold Italic) 2.36 (Math TeX Gyre Regular) -U+1d493 u1D493 2.23 (Serif Bold Italic, Serif Condensed Bold Italic) 2.36 (Math TeX Gyre Regular) -U+1d494 u1D494 2.23 (Serif Bold Italic, Serif Condensed Bold Italic) 2.36 (Math TeX Gyre Regular) -U+1d495 u1D495 2.23 (Serif Bold Italic, Serif Condensed Bold Italic) 2.36 (Math TeX Gyre Regular) -U+1d496 u1D496 2.23 (Serif Bold Italic, Serif Condensed Bold Italic) 2.36 (Math TeX Gyre Regular) -U+1d497 u1D497 2.23 (Serif Bold Italic, Serif Condensed Bold Italic) 2.36 (Math TeX Gyre Regular) -U+1d498 u1D498 2.23 (Serif Bold Italic, Serif Condensed Bold Italic) 2.36 (Math TeX Gyre Regular) -U+1d499 u1D499 2.23 (Serif Bold Italic, Serif Condensed Bold Italic) 2.36 (Math TeX Gyre Regular) -U+1d49a u1D49A 2.23 (Serif Bold Italic, Serif Condensed Bold Italic) 2.36 (Math TeX Gyre Regular) -U+1d49b u1D49B 2.23 (Serif Bold Italic, Serif Condensed Bold Italic) 2.36 (Math TeX Gyre Regular) -U+1d49c u1D49C 2.36 (Math TeX Gyre Regular) -U+1d49e u1D49E 2.36 (Math TeX Gyre Regular) -U+1d49f u1D49F 2.36 (Math TeX Gyre Regular) -U+1d4a2 u1D4A2 2.36 (Math TeX Gyre Regular) -U+1d4a5 u1D4A5 2.36 (Math TeX Gyre Regular) -U+1d4a6 u1D4A6 2.36 (Math TeX Gyre Regular) -U+1d4a9 u1D4A9 2.36 (Math TeX Gyre Regular) -U+1d4aa u1D4AA 2.36 (Math TeX Gyre Regular) -U+1d4ab u1D4AB 2.36 (Math TeX Gyre Regular) -U+1d4ac u1D4AC 2.36 (Math TeX Gyre Regular) -U+1d4ae u1D4AE 2.36 (Math TeX Gyre Regular) -U+1d4af u1D4AF 2.36 (Math TeX Gyre Regular) -U+1d4b0 u1D4B0 2.36 (Math TeX Gyre Regular) -U+1d4b1 u1D4B1 2.36 (Math TeX Gyre Regular) -U+1d4b2 u1D4B2 2.36 (Math TeX Gyre Regular) -U+1d4b3 u1D4B3 2.36 (Math TeX Gyre Regular) -U+1d4b4 u1D4B4 2.36 (Math TeX Gyre Regular) -U+1d4b5 u1D4B5 2.36 (Math TeX Gyre Regular) -U+1d4b6 u1D4B6 2.36 (Math TeX Gyre Regular) -U+1d4b7 u1D4B7 2.36 (Math TeX Gyre Regular) -U+1d4b8 u1D4B8 2.36 (Math TeX Gyre Regular) -U+1d4b9 u1D4B9 2.36 (Math TeX Gyre Regular) -U+1d4bb u1D4BB 2.36 (Math TeX Gyre Regular) -U+1d4bd u1D4BD 2.36 (Math TeX Gyre Regular) -U+1d4be u1D4BE 2.36 (Math TeX Gyre Regular) -U+1d4bf u1D4BF 2.36 (Math TeX Gyre Regular) -U+1d4c0 u1D4C0 2.36 (Math TeX Gyre Regular) -U+1d4c1 u1D4C1 2.36 (Math TeX Gyre Regular) -U+1d4c2 u1D4C2 2.36 (Math TeX Gyre Regular) -U+1d4c3 u1D4C3 2.36 (Math TeX Gyre Regular) -U+1d4c5 u1D4C5 2.36 (Math TeX Gyre Regular) -U+1d4c6 u1D4C6 2.36 (Math TeX Gyre Regular) -U+1d4c7 u1D4C7 2.36 (Math TeX Gyre Regular) -U+1d4c8 u1D4C8 2.36 (Math TeX Gyre Regular) -U+1d4c9 u1D4C9 2.36 (Math TeX Gyre Regular) -U+1d4ca u1D4CA 2.36 (Math TeX Gyre Regular) -U+1d4cb u1D4CB 2.36 (Math TeX Gyre Regular) -U+1d4cc u1D4CC 2.36 (Math TeX Gyre Regular) -U+1d4cd u1D4CD 2.36 (Math TeX Gyre Regular) -U+1d4ce u1D4CE 2.36 (Math TeX Gyre Regular) -U+1d4cf u1D4CF 2.36 (Math TeX Gyre Regular) -U+1d4d0 u1D4D0 2.36 (Math TeX Gyre Regular) -U+1d4d1 u1D4D1 2.36 (Math TeX Gyre Regular) -U+1d4d2 u1D4D2 2.36 (Math TeX Gyre Regular) -U+1d4d3 u1D4D3 2.36 (Math TeX Gyre Regular) -U+1d4d4 u1D4D4 2.36 (Math TeX Gyre Regular) -U+1d4d5 u1D4D5 2.36 (Math TeX Gyre Regular) -U+1d4d6 u1D4D6 2.36 (Math TeX Gyre Regular) -U+1d4d7 u1D4D7 2.36 (Math TeX Gyre Regular) -U+1d4d8 u1D4D8 2.36 (Math TeX Gyre Regular) -U+1d4d9 u1D4D9 2.36 (Math TeX Gyre Regular) -U+1d4da u1D4DA 2.36 (Math TeX Gyre Regular) -U+1d4db u1D4DB 2.36 (Math TeX Gyre Regular) -U+1d4dc u1D4DC 2.36 (Math TeX Gyre Regular) -U+1d4dd u1D4DD 2.36 (Math TeX Gyre Regular) -U+1d4de u1D4DE 2.36 (Math TeX Gyre Regular) -U+1d4df u1D4DF 2.36 (Math TeX Gyre Regular) -U+1d4e0 u1D4E0 2.36 (Math TeX Gyre Regular) -U+1d4e1 u1D4E1 2.36 (Math TeX Gyre Regular) -U+1d4e2 u1D4E2 2.36 (Math TeX Gyre Regular) -U+1d4e3 u1D4E3 2.36 (Math TeX Gyre Regular) -U+1d4e4 u1D4E4 2.36 (Math TeX Gyre Regular) -U+1d4e5 u1D4E5 2.36 (Math TeX Gyre Regular) -U+1d4e6 u1D4E6 2.36 (Math TeX Gyre Regular) -U+1d4e7 u1D4E7 2.36 (Math TeX Gyre Regular) -U+1d4e8 u1D4E8 2.36 (Math TeX Gyre Regular) -U+1d4e9 u1D4E9 2.36 (Math TeX Gyre Regular) -U+1d4ea u1D4EA 2.36 (Math TeX Gyre Regular) -U+1d4eb u1D4EB 2.36 (Math TeX Gyre Regular) -U+1d4ec u1D4EC 2.36 (Math TeX Gyre Regular) -U+1d4ed u1D4ED 2.36 (Math TeX Gyre Regular) -U+1d4ee u1D4EE 2.36 (Math TeX Gyre Regular) -U+1d4ef u1D4EF 2.36 (Math TeX Gyre Regular) -U+1d4f0 u1D4F0 2.36 (Math TeX Gyre Regular) -U+1d4f1 u1D4F1 2.36 (Math TeX Gyre Regular) -U+1d4f2 u1D4F2 2.36 (Math TeX Gyre Regular) -U+1d4f3 u1D4F3 2.36 (Math TeX Gyre Regular) -U+1d4f4 u1D4F4 2.36 (Math TeX Gyre Regular) -U+1d4f5 u1D4F5 2.36 (Math TeX Gyre Regular) -U+1d4f6 u1D4F6 2.36 (Math TeX Gyre Regular) -U+1d4f7 u1D4F7 2.36 (Math TeX Gyre Regular) -U+1d4f8 u1D4F8 2.36 (Math TeX Gyre Regular) -U+1d4f9 u1D4F9 2.36 (Math TeX Gyre Regular) -U+1d4fa u1D4FA 2.36 (Math TeX Gyre Regular) -U+1d4fb u1D4FB 2.36 (Math TeX Gyre Regular) -U+1d4fc u1D4FC 2.36 (Math TeX Gyre Regular) -U+1d4fd u1D4FD 2.36 (Math TeX Gyre Regular) -U+1d4fe u1D4FE 2.36 (Math TeX Gyre Regular) -U+1d4ff u1D4FF 2.36 (Math TeX Gyre Regular) -U+1d500 u1D500 2.36 (Math TeX Gyre Regular) -U+1d501 u1D501 2.36 (Math TeX Gyre Regular) -U+1d502 u1D502 2.36 (Math TeX Gyre Regular) -U+1d503 u1D503 2.36 (Math TeX Gyre Regular) -U+1d504 u1D504 2.36 (Math TeX Gyre Regular) -U+1d505 u1D505 2.36 (Math TeX Gyre Regular) -U+1d507 u1D507 2.36 (Math TeX Gyre Regular) -U+1d508 u1D508 2.36 (Math TeX Gyre Regular) -U+1d509 u1D509 2.36 (Math TeX Gyre Regular) -U+1d50a u1D50A 2.36 (Math TeX Gyre Regular) -U+1d50d u1D50D 2.36 (Math TeX Gyre Regular) -U+1d50e u1D50E 2.36 (Math TeX Gyre Regular) -U+1d50f u1D50F 2.36 (Math TeX Gyre Regular) -U+1d510 u1D510 2.36 (Math TeX Gyre Regular) -U+1d511 u1D511 2.36 (Math TeX Gyre Regular) -U+1d512 u1D512 2.36 (Math TeX Gyre Regular) -U+1d513 u1D513 2.36 (Math TeX Gyre Regular) -U+1d514 u1D514 2.36 (Math TeX Gyre Regular) -U+1d516 u1D516 2.36 (Math TeX Gyre Regular) -U+1d517 u1D517 2.36 (Math TeX Gyre Regular) -U+1d518 u1D518 2.36 (Math TeX Gyre Regular) -U+1d519 u1D519 2.36 (Math TeX Gyre Regular) -U+1d51a u1D51A 2.36 (Math TeX Gyre Regular) -U+1d51b u1D51B 2.36 (Math TeX Gyre Regular) -U+1d51c u1D51C 2.36 (Math TeX Gyre Regular) -U+1d51e u1D51E 2.36 (Math TeX Gyre Regular) -U+1d51f u1D51F 2.36 (Math TeX Gyre Regular) -U+1d520 u1D520 2.36 (Math TeX Gyre Regular) -U+1d521 u1D521 2.36 (Math TeX Gyre Regular) -U+1d522 u1D522 2.36 (Math TeX Gyre Regular) -U+1d523 u1D523 2.36 (Math TeX Gyre Regular) -U+1d524 u1D524 2.36 (Math TeX Gyre Regular) -U+1d525 u1D525 2.36 (Math TeX Gyre Regular) -U+1d526 u1D526 2.36 (Math TeX Gyre Regular) -U+1d527 u1D527 2.36 (Math TeX Gyre Regular) -U+1d528 u1D528 2.36 (Math TeX Gyre Regular) -U+1d529 u1D529 2.36 (Math TeX Gyre Regular) -U+1d52a u1D52A 2.36 (Math TeX Gyre Regular) -U+1d52b u1D52B 2.36 (Math TeX Gyre Regular) -U+1d52c u1D52C 2.36 (Math TeX Gyre Regular) -U+1d52d u1D52D 2.36 (Math TeX Gyre Regular) -U+1d52e u1D52E 2.36 (Math TeX Gyre Regular) -U+1d52f u1D52F 2.36 (Math TeX Gyre Regular) -U+1d530 u1D530 2.36 (Math TeX Gyre Regular) -U+1d531 u1D531 2.36 (Math TeX Gyre Regular) -U+1d532 u1D532 2.36 (Math TeX Gyre Regular) -U+1d533 u1D533 2.36 (Math TeX Gyre Regular) -U+1d534 u1D534 2.36 (Math TeX Gyre Regular) -U+1d535 u1D535 2.36 (Math TeX Gyre Regular) -U+1d536 u1D536 2.36 (Math TeX Gyre Regular) -U+1d537 u1D537 2.36 (Math TeX Gyre Regular) -U+1d538 u1D538 2.18 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.22 (Serif, Serif Condensed) 2.36 (Math TeX Gyre Regular) -U+1d539 u1D539 2.18 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.22 (Serif, Serif Condensed) 2.36 (Math TeX Gyre Regular) -U+1d53b u1D53B 2.18 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.22 (Serif, Serif Condensed) 2.36 (Math TeX Gyre Regular) -U+1d53c u1D53C 2.18 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.22 (Serif, Serif Condensed) 2.36 (Math TeX Gyre Regular) -U+1d53d u1D53D 2.18 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.22 (Serif, Serif Condensed) 2.36 (Math TeX Gyre Regular) -U+1d53e u1D53E 2.18 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.22 (Serif, Serif Condensed) 2.36 (Math TeX Gyre Regular) -U+1d540 u1D540 2.18 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.22 (Serif, Serif Condensed) 2.36 (Math TeX Gyre Regular) -U+1d541 u1D541 2.18 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.22 (Serif, Serif Condensed) 2.36 (Math TeX Gyre Regular) -U+1d542 u1D542 2.18 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.22 (Serif, Serif Condensed) 2.36 (Math TeX Gyre Regular) -U+1d543 u1D543 2.18 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.22 (Serif, Serif Condensed) 2.36 (Math TeX Gyre Regular) -U+1d544 u1D544 2.18 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.22 (Serif, Serif Condensed) 2.36 (Math TeX Gyre Regular) -U+1d546 u1D546 2.18 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.22 (Serif, Serif Condensed) 2.36 (Math TeX Gyre Regular) -U+1d54a u1D54A 2.18 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.22 (Serif, Serif Condensed) 2.36 (Math TeX Gyre Regular) -U+1d54b u1D54B 2.18 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.22 (Serif, Serif Condensed) 2.36 (Math TeX Gyre Regular) -U+1d54c u1D54C 2.18 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.22 (Serif, Serif Condensed) 2.36 (Math TeX Gyre Regular) -U+1d54d u1D54D 2.18 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.22 (Serif, Serif Condensed) 2.36 (Math TeX Gyre Regular) -U+1d54e u1D54E 2.18 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.22 (Serif, Serif Condensed) 2.36 (Math TeX Gyre Regular) -U+1d54f u1D54F 2.18 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.22 (Serif, Serif Condensed) 2.36 (Math TeX Gyre Regular) -U+1d550 u1D550 2.18 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.22 (Serif, Serif Condensed) 2.36 (Math TeX Gyre Regular) -U+1d552 u1D552 2.18 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.22 (Serif, Serif Condensed) 2.36 (Math TeX Gyre Regular) -U+1d553 u1D553 2.18 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.22 (Serif, Serif Condensed) 2.36 (Math TeX Gyre Regular) -U+1d554 u1D554 2.18 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.22 (Serif, Serif Condensed) 2.36 (Math TeX Gyre Regular) -U+1d555 u1D555 2.18 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.22 (Serif, Serif Condensed) 2.36 (Math TeX Gyre Regular) -U+1d556 u1D556 2.18 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.22 (Serif, Serif Condensed) 2.36 (Math TeX Gyre Regular) -U+1d557 u1D557 2.18 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.22 (Serif, Serif Condensed) 2.36 (Math TeX Gyre Regular) -U+1d558 u1D558 2.18 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.22 (Serif, Serif Condensed) 2.36 (Math TeX Gyre Regular) -U+1d559 u1D559 2.18 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.22 (Serif, Serif Condensed) 2.36 (Math TeX Gyre Regular) -U+1d55a u1D55A 2.18 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.22 (Serif, Serif Condensed) 2.34 (Sans Mono, Sans Mono Bold, Sans Mono Bold Oblique, Sans Mono Oblique) 2.36 (Math TeX Gyre Regular) -U+1d55b u1D55B 2.18 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.22 (Serif, Serif Condensed) 2.36 (Math TeX Gyre Regular) -U+1d55c u1D55C 2.18 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.22 (Serif, Serif Condensed) 2.36 (Math TeX Gyre Regular) -U+1d55d u1D55D 2.18 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.22 (Serif, Serif Condensed) 2.36 (Math TeX Gyre Regular) -U+1d55e u1D55E 2.18 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.22 (Serif, Serif Condensed) 2.36 (Math TeX Gyre Regular) -U+1d55f u1D55F 2.18 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.22 (Serif, Serif Condensed) 2.36 (Math TeX Gyre Regular) -U+1d560 u1D560 2.18 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.22 (Serif, Serif Condensed) 2.36 (Math TeX Gyre Regular) -U+1d561 u1D561 2.18 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.22 (Serif, Serif Condensed) 2.36 (Math TeX Gyre Regular) -U+1d562 u1D562 2.18 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.22 (Serif, Serif Condensed) 2.36 (Math TeX Gyre Regular) -U+1d563 u1D563 2.18 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.22 (Serif, Serif Condensed) 2.36 (Math TeX Gyre Regular) -U+1d564 u1D564 2.18 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.22 (Serif, Serif Condensed) 2.36 (Math TeX Gyre Regular) -U+1d565 u1D565 2.18 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.22 (Serif, Serif Condensed) 2.36 (Math TeX Gyre Regular) -U+1d566 u1D566 2.18 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.22 (Serif, Serif Condensed) 2.36 (Math TeX Gyre Regular) -U+1d567 u1D567 2.18 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.22 (Serif, Serif Condensed) 2.36 (Math TeX Gyre Regular) -U+1d568 u1D568 2.18 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.22 (Serif, Serif Condensed) 2.36 (Math TeX Gyre Regular) -U+1d569 u1D569 2.18 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.22 (Serif, Serif Condensed) 2.36 (Math TeX Gyre Regular) -U+1d56a u1D56A 2.18 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.22 (Serif, Serif Condensed) 2.36 (Math TeX Gyre Regular) -U+1d56b u1D56B 2.18 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.22 (Serif, Serif Condensed) 2.36 (Math TeX Gyre Regular) -U+1d56c u1D56C 2.36 (Math TeX Gyre Regular) -U+1d56d u1D56D 2.36 (Math TeX Gyre Regular) -U+1d56e u1D56E 2.36 (Math TeX Gyre Regular) -U+1d56f u1D56F 2.36 (Math TeX Gyre Regular) -U+1d570 u1D570 2.36 (Math TeX Gyre Regular) -U+1d571 u1D571 2.36 (Math TeX Gyre Regular) -U+1d572 u1D572 2.36 (Math TeX Gyre Regular) -U+1d573 u1D573 2.36 (Math TeX Gyre Regular) -U+1d574 u1D574 2.36 (Math TeX Gyre Regular) -U+1d575 u1D575 2.36 (Math TeX Gyre Regular) -U+1d576 u1D576 2.36 (Math TeX Gyre Regular) -U+1d577 u1D577 2.36 (Math TeX Gyre Regular) -U+1d578 u1D578 2.36 (Math TeX Gyre Regular) -U+1d579 u1D579 2.36 (Math TeX Gyre Regular) -U+1d57a u1D57A 2.36 (Math TeX Gyre Regular) -U+1d57b u1D57B 2.36 (Math TeX Gyre Regular) -U+1d57c u1D57C 2.36 (Math TeX Gyre Regular) -U+1d57d u1D57D 2.36 (Math TeX Gyre Regular) -U+1d57e u1D57E 2.36 (Math TeX Gyre Regular) -U+1d57f u1D57F 2.36 (Math TeX Gyre Regular) -U+1d580 u1D580 2.36 (Math TeX Gyre Regular) -U+1d581 u1D581 2.36 (Math TeX Gyre Regular) -U+1d582 u1D582 2.36 (Math TeX Gyre Regular) -U+1d583 u1D583 2.36 (Math TeX Gyre Regular) -U+1d584 u1D584 2.36 (Math TeX Gyre Regular) -U+1d585 u1D585 2.36 (Math TeX Gyre Regular) -U+1d586 u1D586 2.36 (Math TeX Gyre Regular) -U+1d587 u1D587 2.36 (Math TeX Gyre Regular) -U+1d588 u1D588 2.36 (Math TeX Gyre Regular) -U+1d589 u1D589 2.36 (Math TeX Gyre Regular) -U+1d58a u1D58A 2.36 (Math TeX Gyre Regular) -U+1d58b u1D58B 2.36 (Math TeX Gyre Regular) -U+1d58c u1D58C 2.36 (Math TeX Gyre Regular) -U+1d58d u1D58D 2.36 (Math TeX Gyre Regular) -U+1d58e u1D58E 2.36 (Math TeX Gyre Regular) -U+1d58f u1D58F 2.36 (Math TeX Gyre Regular) -U+1d590 u1D590 2.36 (Math TeX Gyre Regular) -U+1d591 u1D591 2.36 (Math TeX Gyre Regular) -U+1d592 u1D592 2.36 (Math TeX Gyre Regular) -U+1d593 u1D593 2.36 (Math TeX Gyre Regular) -U+1d594 u1D594 2.36 (Math TeX Gyre Regular) -U+1d595 u1D595 2.36 (Math TeX Gyre Regular) -U+1d596 u1D596 2.36 (Math TeX Gyre Regular) -U+1d597 u1D597 2.36 (Math TeX Gyre Regular) -U+1d598 u1D598 2.36 (Math TeX Gyre Regular) -U+1d599 u1D599 2.36 (Math TeX Gyre Regular) -U+1d59a u1D59A 2.36 (Math TeX Gyre Regular) -U+1d59b u1D59B 2.36 (Math TeX Gyre Regular) -U+1d59c u1D59C 2.36 (Math TeX Gyre Regular) -U+1d59d u1D59D 2.36 (Math TeX Gyre Regular) -U+1d59e u1D59E 2.36 (Math TeX Gyre Regular) -U+1d59f u1D59F 2.36 (Math TeX Gyre Regular) -U+1d5a0 u1D5A0 2.23 (Sans, Sans Condensed) 2.36 (Math TeX Gyre Regular) -U+1d5a1 u1D5A1 2.23 (Sans, Sans Condensed) 2.36 (Math TeX Gyre Regular) -U+1d5a2 u1D5A2 2.23 (Sans, Sans Condensed) 2.36 (Math TeX Gyre Regular) -U+1d5a3 u1D5A3 2.23 (Sans, Sans Condensed) 2.36 (Math TeX Gyre Regular) -U+1d5a4 u1D5A4 2.23 (Sans, Sans Condensed) 2.36 (Math TeX Gyre Regular) -U+1d5a5 u1D5A5 2.23 (Sans, Sans Condensed) 2.36 (Math TeX Gyre Regular) -U+1d5a6 u1D5A6 2.23 (Sans, Sans Condensed) 2.36 (Math TeX Gyre Regular) -U+1d5a7 u1D5A7 2.23 (Sans, Sans Condensed) 2.36 (Math TeX Gyre Regular) -U+1d5a8 u1D5A8 2.23 (Sans, Sans Condensed) 2.36 (Math TeX Gyre Regular) -U+1d5a9 u1D5A9 2.23 (Sans, Sans Condensed) 2.36 (Math TeX Gyre Regular) -U+1d5aa u1D5AA 2.23 (Sans, Sans Condensed) 2.36 (Math TeX Gyre Regular) -U+1d5ab u1D5AB 2.23 (Sans, Sans Condensed) 2.36 (Math TeX Gyre Regular) -U+1d5ac u1D5AC 2.23 (Sans, Sans Condensed) 2.36 (Math TeX Gyre Regular) -U+1d5ad u1D5AD 2.23 (Sans, Sans Condensed) 2.36 (Math TeX Gyre Regular) -U+1d5ae u1D5AE 2.23 (Sans, Sans Condensed) 2.36 (Math TeX Gyre Regular) -U+1d5af u1D5AF 2.23 (Sans, Sans Condensed) 2.36 (Math TeX Gyre Regular) -U+1d5b0 u1D5B0 2.23 (Sans, Sans Condensed) 2.36 (Math TeX Gyre Regular) -U+1d5b1 u1D5B1 2.23 (Sans, Sans Condensed) 2.36 (Math TeX Gyre Regular) -U+1d5b2 u1D5B2 2.23 (Sans, Sans Condensed) 2.36 (Math TeX Gyre Regular) -U+1d5b3 u1D5B3 2.23 (Sans, Sans Condensed) 2.36 (Math TeX Gyre Regular) -U+1d5b4 u1D5B4 2.23 (Sans, Sans Condensed) 2.36 (Math TeX Gyre Regular) -U+1d5b5 u1D5B5 2.23 (Sans, Sans Condensed) 2.36 (Math TeX Gyre Regular) -U+1d5b6 u1D5B6 2.23 (Sans, Sans Condensed) 2.36 (Math TeX Gyre Regular) -U+1d5b7 u1D5B7 2.23 (Sans, Sans Condensed) 2.36 (Math TeX Gyre Regular) -U+1d5b8 u1D5B8 2.23 (Sans, Sans Condensed) 2.36 (Math TeX Gyre Regular) -U+1d5b9 u1D5B9 2.23 (Sans, Sans Condensed) 2.36 (Math TeX Gyre Regular) -U+1d5ba u1D5BA 2.23 (Sans, Sans Condensed) 2.36 (Math TeX Gyre Regular) -U+1d5bb u1D5BB 2.23 (Sans, Sans Condensed) 2.36 (Math TeX Gyre Regular) -U+1d5bc u1D5BC 2.23 (Sans, Sans Condensed) 2.36 (Math TeX Gyre Regular) -U+1d5bd u1D5BD 2.23 (Sans, Sans Condensed) 2.36 (Math TeX Gyre Regular) -U+1d5be u1D5BE 2.23 (Sans, Sans Condensed) 2.36 (Math TeX Gyre Regular) -U+1d5bf u1D5BF 2.23 (Sans, Sans Condensed) 2.36 (Math TeX Gyre Regular) -U+1d5c0 u1D5C0 2.23 (Sans, Sans Condensed) 2.36 (Math TeX Gyre Regular) -U+1d5c1 u1D5C1 2.23 (Sans, Sans Condensed) 2.36 (Math TeX Gyre Regular) -U+1d5c2 u1D5C2 2.23 (Sans, Sans Condensed) 2.36 (Math TeX Gyre Regular) -U+1d5c3 u1D5C3 2.23 (Sans, Sans Condensed) 2.36 (Math TeX Gyre Regular) -U+1d5c4 u1D5C4 2.23 (Sans, Sans Condensed) 2.36 (Math TeX Gyre Regular) -U+1d5c5 u1D5C5 2.23 (Sans, Sans Condensed) 2.36 (Math TeX Gyre Regular) -U+1d5c6 u1D5C6 2.23 (Sans, Sans Condensed) 2.36 (Math TeX Gyre Regular) -U+1d5c7 u1D5C7 2.23 (Sans, Sans Condensed) 2.36 (Math TeX Gyre Regular) -U+1d5c8 u1D5C8 2.23 (Sans, Sans Condensed) 2.36 (Math TeX Gyre Regular) -U+1d5c9 u1D5C9 2.23 (Sans, Sans Condensed) 2.36 (Math TeX Gyre Regular) -U+1d5ca u1D5CA 2.23 (Sans, Sans Condensed) 2.36 (Math TeX Gyre Regular) -U+1d5cb u1D5CB 2.23 (Sans, Sans Condensed) 2.36 (Math TeX Gyre Regular) -U+1d5cc u1D5CC 2.23 (Sans, Sans Condensed) 2.36 (Math TeX Gyre Regular) -U+1d5cd u1D5CD 2.23 (Sans, Sans Condensed) 2.36 (Math TeX Gyre Regular) -U+1d5ce u1D5CE 2.23 (Sans, Sans Condensed) 2.36 (Math TeX Gyre Regular) -U+1d5cf u1D5CF 2.23 (Sans, Sans Condensed) 2.36 (Math TeX Gyre Regular) -U+1d5d0 u1D5D0 2.23 (Sans, Sans Condensed) 2.36 (Math TeX Gyre Regular) -U+1d5d1 u1D5D1 2.23 (Sans, Sans Condensed) 2.36 (Math TeX Gyre Regular) -U+1d5d2 u1D5D2 2.23 (Sans, Sans Condensed) 2.36 (Math TeX Gyre Regular) -U+1d5d3 u1D5D3 2.23 (Sans, Sans Condensed) 2.36 (Math TeX Gyre Regular) -U+1d5d4 u1D5D4 2.23 (Sans Bold, Sans Condensed Bold) 2.36 (Math TeX Gyre Regular) -U+1d5d5 u1D5D5 2.23 (Sans Bold, Sans Condensed Bold) 2.36 (Math TeX Gyre Regular) -U+1d5d6 u1D5D6 2.23 (Sans Bold, Sans Condensed Bold) 2.36 (Math TeX Gyre Regular) -U+1d5d7 u1D5D7 2.23 (Sans Bold, Sans Condensed Bold) 2.36 (Math TeX Gyre Regular) -U+1d5d8 u1D5D8 2.23 (Sans Bold, Sans Condensed Bold) 2.36 (Math TeX Gyre Regular) -U+1d5d9 u1D5D9 2.23 (Sans Bold, Sans Condensed Bold) 2.36 (Math TeX Gyre Regular) -U+1d5da u1D5DA 2.23 (Sans Bold, Sans Condensed Bold) 2.36 (Math TeX Gyre Regular) -U+1d5db u1D5DB 2.23 (Sans Bold, Sans Condensed Bold) 2.36 (Math TeX Gyre Regular) -U+1d5dc u1D5DC 2.23 (Sans Bold, Sans Condensed Bold) 2.36 (Math TeX Gyre Regular) -U+1d5dd u1D5DD 2.23 (Sans Bold, Sans Condensed Bold) 2.36 (Math TeX Gyre Regular) -U+1d5de u1D5DE 2.23 (Sans Bold, Sans Condensed Bold) 2.36 (Math TeX Gyre Regular) -U+1d5df u1D5DF 2.23 (Sans Bold, Sans Condensed Bold) 2.36 (Math TeX Gyre Regular) -U+1d5e0 u1D5E0 2.23 (Sans Bold, Sans Condensed Bold) 2.36 (Math TeX Gyre Regular) -U+1d5e1 u1D5E1 2.23 (Sans Bold, Sans Condensed Bold) 2.36 (Math TeX Gyre Regular) -U+1d5e2 u1D5E2 2.23 (Sans Bold, Sans Condensed Bold) 2.36 (Math TeX Gyre Regular) -U+1d5e3 u1D5E3 2.23 (Sans Bold, Sans Condensed Bold) 2.36 (Math TeX Gyre Regular) -U+1d5e4 u1D5E4 2.23 (Sans Bold, Sans Condensed Bold) 2.36 (Math TeX Gyre Regular) -U+1d5e5 u1D5E5 2.23 (Sans Bold, Sans Condensed Bold) 2.36 (Math TeX Gyre Regular) -U+1d5e6 u1D5E6 2.23 (Sans Bold, Sans Condensed Bold) 2.36 (Math TeX Gyre Regular) -U+1d5e7 u1D5E7 2.23 (Sans Bold, Sans Condensed Bold) 2.36 (Math TeX Gyre Regular) -U+1d5e8 u1D5E8 2.23 (Sans Bold, Sans Condensed Bold) 2.36 (Math TeX Gyre Regular) -U+1d5e9 u1D5E9 2.23 (Sans Bold, Sans Condensed Bold) 2.36 (Math TeX Gyre Regular) -U+1d5ea u1D5EA 2.23 (Sans Bold, Sans Condensed Bold) 2.36 (Math TeX Gyre Regular) -U+1d5eb u1D5EB 2.23 (Sans Bold, Sans Condensed Bold) 2.36 (Math TeX Gyre Regular) -U+1d5ec u1D5EC 2.23 (Sans Bold, Sans Condensed Bold) 2.36 (Math TeX Gyre Regular) -U+1d5ed u1D5ED 2.23 (Sans Bold, Sans Condensed Bold) 2.36 (Math TeX Gyre Regular) -U+1d5ee u1D5EE 2.23 (Sans Bold, Sans Condensed Bold) 2.36 (Math TeX Gyre Regular) -U+1d5ef u1D5EF 2.23 (Sans Bold, Sans Condensed Bold) 2.36 (Math TeX Gyre Regular) -U+1d5f0 u1D5F0 2.23 (Sans Bold, Sans Condensed Bold) 2.36 (Math TeX Gyre Regular) -U+1d5f1 u1D5F1 2.23 (Sans Bold, Sans Condensed Bold) 2.36 (Math TeX Gyre Regular) -U+1d5f2 u1D5F2 2.23 (Sans Bold, Sans Condensed Bold) 2.36 (Math TeX Gyre Regular) -U+1d5f3 u1D5F3 2.23 (Sans Bold, Sans Condensed Bold) 2.36 (Math TeX Gyre Regular) -U+1d5f4 u1D5F4 2.23 (Sans Bold, Sans Condensed Bold) 2.36 (Math TeX Gyre Regular) -U+1d5f5 u1D5F5 2.23 (Sans Bold, Sans Condensed Bold) 2.36 (Math TeX Gyre Regular) -U+1d5f6 u1D5F6 2.23 (Sans Bold, Sans Condensed Bold) 2.36 (Math TeX Gyre Regular) -U+1d5f7 u1D5F7 2.23 (Sans Bold, Sans Condensed Bold) 2.36 (Math TeX Gyre Regular) -U+1d5f8 u1D5F8 2.23 (Sans Bold, Sans Condensed Bold) 2.36 (Math TeX Gyre Regular) -U+1d5f9 u1D5F9 2.23 (Sans Bold, Sans Condensed Bold) 2.36 (Math TeX Gyre Regular) -U+1d5fa u1D5FA 2.23 (Sans Bold, Sans Condensed Bold) 2.36 (Math TeX Gyre Regular) -U+1d5fb u1D5FB 2.23 (Sans Bold, Sans Condensed Bold) 2.36 (Math TeX Gyre Regular) -U+1d5fc u1D5FC 2.23 (Sans Bold, Sans Condensed Bold) 2.36 (Math TeX Gyre Regular) -U+1d5fd u1D5FD 2.23 (Sans Bold, Sans Condensed Bold) 2.36 (Math TeX Gyre Regular) -U+1d5fe u1D5FE 2.23 (Sans Bold, Sans Condensed Bold) 2.36 (Math TeX Gyre Regular) -U+1d5ff u1D5FF 2.23 (Sans Bold, Sans Condensed Bold) 2.36 (Math TeX Gyre Regular) -U+1d600 u1D600 2.23 (Sans Bold, Sans Condensed Bold) 2.36 (Math TeX Gyre Regular) -U+1d601 u1D601 2.23 (Sans Bold, Sans Condensed Bold) 2.36 (Math TeX Gyre Regular) -U+1d602 u1D602 2.23 (Sans Bold, Sans Condensed Bold) 2.36 (Math TeX Gyre Regular) -U+1d603 u1D603 2.23 (Sans Bold, Sans Condensed Bold) 2.36 (Math TeX Gyre Regular) -U+1d604 u1D604 2.23 (Sans Bold, Sans Condensed Bold) 2.36 (Math TeX Gyre Regular) -U+1d605 u1D605 2.23 (Sans Bold, Sans Condensed Bold) 2.36 (Math TeX Gyre Regular) -U+1d606 u1D606 2.23 (Sans Bold, Sans Condensed Bold) 2.36 (Math TeX Gyre Regular) -U+1d607 u1D607 2.23 (Sans Bold, Sans Condensed Bold) 2.36 (Math TeX Gyre Regular) -U+1d608 u1D608 2.23 (Sans Condensed Oblique, Sans Oblique) 2.36 (Math TeX Gyre Regular) -U+1d609 u1D609 2.23 (Sans Condensed Oblique, Sans Oblique) 2.36 (Math TeX Gyre Regular) -U+1d60a u1D60A 2.23 (Sans Condensed Oblique, Sans Oblique) 2.36 (Math TeX Gyre Regular) -U+1d60b u1D60B 2.23 (Sans Condensed Oblique, Sans Oblique) 2.36 (Math TeX Gyre Regular) -U+1d60c u1D60C 2.23 (Sans Condensed Oblique, Sans Oblique) 2.36 (Math TeX Gyre Regular) -U+1d60d u1D60D 2.23 (Sans Condensed Oblique, Sans Oblique) 2.36 (Math TeX Gyre Regular) -U+1d60e u1D60E 2.23 (Sans Condensed Oblique, Sans Oblique) 2.36 (Math TeX Gyre Regular) -U+1d60f u1D60F 2.23 (Sans Condensed Oblique, Sans Oblique) 2.36 (Math TeX Gyre Regular) -U+1d610 u1D610 2.23 (Sans Condensed Oblique, Sans Oblique) 2.36 (Math TeX Gyre Regular) -U+1d611 u1D611 2.23 (Sans Condensed Oblique, Sans Oblique) 2.36 (Math TeX Gyre Regular) -U+1d612 u1D612 2.23 (Sans Condensed Oblique, Sans Oblique) 2.36 (Math TeX Gyre Regular) -U+1d613 u1D613 2.23 (Sans Condensed Oblique, Sans Oblique) 2.36 (Math TeX Gyre Regular) -U+1d614 u1D614 2.23 (Sans Condensed Oblique, Sans Oblique) 2.36 (Math TeX Gyre Regular) -U+1d615 u1D615 2.23 (Sans Condensed Oblique, Sans Oblique) 2.36 (Math TeX Gyre Regular) -U+1d616 u1D616 2.23 (Sans Condensed Oblique, Sans Oblique) 2.36 (Math TeX Gyre Regular) -U+1d617 u1D617 2.23 (Sans Condensed Oblique, Sans Oblique) 2.36 (Math TeX Gyre Regular) -U+1d618 u1D618 2.23 (Sans Condensed Oblique, Sans Oblique) 2.36 (Math TeX Gyre Regular) -U+1d619 u1D619 2.23 (Sans Condensed Oblique, Sans Oblique) 2.36 (Math TeX Gyre Regular) -U+1d61a u1D61A 2.23 (Sans Condensed Oblique, Sans Oblique) 2.36 (Math TeX Gyre Regular) -U+1d61b u1D61B 2.23 (Sans Condensed Oblique, Sans Oblique) 2.36 (Math TeX Gyre Regular) -U+1d61c u1D61C 2.23 (Sans Condensed Oblique, Sans Oblique) 2.36 (Math TeX Gyre Regular) -U+1d61d u1D61D 2.23 (Sans Condensed Oblique, Sans Oblique) 2.36 (Math TeX Gyre Regular) -U+1d61e u1D61E 2.23 (Sans Condensed Oblique, Sans Oblique) 2.36 (Math TeX Gyre Regular) -U+1d61f u1D61F 2.23 (Sans Condensed Oblique, Sans Oblique) 2.36 (Math TeX Gyre Regular) -U+1d620 u1D620 2.23 (Sans Condensed Oblique, Sans Oblique) 2.36 (Math TeX Gyre Regular) -U+1d621 u1D621 2.23 (Sans Condensed Oblique, Sans Oblique) 2.36 (Math TeX Gyre Regular) -U+1d622 u1D622 2.23 (Sans Condensed Oblique, Sans Oblique) 2.36 (Math TeX Gyre Regular) -U+1d623 u1D623 2.23 (Sans Condensed Oblique, Sans Oblique) 2.36 (Math TeX Gyre Regular) -U+1d624 u1D624 2.23 (Sans Condensed Oblique, Sans Oblique) 2.36 (Math TeX Gyre Regular) -U+1d625 u1D625 2.23 (Sans Condensed Oblique, Sans Oblique) 2.36 (Math TeX Gyre Regular) -U+1d626 u1D626 2.23 (Sans Condensed Oblique, Sans Oblique) 2.36 (Math TeX Gyre Regular) -U+1d627 u1D627 2.23 (Sans Condensed Oblique, Sans Oblique) 2.36 (Math TeX Gyre Regular) -U+1d628 u1D628 2.23 (Sans Condensed Oblique, Sans Oblique) 2.36 (Math TeX Gyre Regular) -U+1d629 u1D629 2.23 (Sans Condensed Oblique, Sans Oblique) 2.36 (Math TeX Gyre Regular) -U+1d62a u1D62A 2.23 (Sans Condensed Oblique, Sans Oblique) 2.36 (Math TeX Gyre Regular) -U+1d62b u1D62B 2.23 (Sans Condensed Oblique, Sans Oblique) 2.36 (Math TeX Gyre Regular) -U+1d62c u1D62C 2.23 (Sans Condensed Oblique, Sans Oblique) 2.36 (Math TeX Gyre Regular) -U+1d62d u1D62D 2.23 (Sans Condensed Oblique, Sans Oblique) 2.36 (Math TeX Gyre Regular) -U+1d62e u1D62E 2.23 (Sans Condensed Oblique, Sans Oblique) 2.36 (Math TeX Gyre Regular) -U+1d62f u1D62F 2.23 (Sans Condensed Oblique, Sans Oblique) 2.36 (Math TeX Gyre Regular) -U+1d630 u1D630 2.23 (Sans Condensed Oblique, Sans Oblique) 2.36 (Math TeX Gyre Regular) -U+1d631 u1D631 2.23 (Sans Condensed Oblique, Sans Oblique) 2.36 (Math TeX Gyre Regular) -U+1d632 u1D632 2.23 (Sans Condensed Oblique, Sans Oblique) 2.36 (Math TeX Gyre Regular) -U+1d633 u1D633 2.23 (Sans Condensed Oblique, Sans Oblique) 2.36 (Math TeX Gyre Regular) -U+1d634 u1D634 2.23 (Sans Condensed Oblique, Sans Oblique) 2.36 (Math TeX Gyre Regular) -U+1d635 u1D635 2.23 (Sans Condensed Oblique, Sans Oblique) 2.36 (Math TeX Gyre Regular) -U+1d636 u1D636 2.23 (Sans Condensed Oblique, Sans Oblique) 2.36 (Math TeX Gyre Regular) -U+1d637 u1D637 2.23 (Sans Condensed Oblique, Sans Oblique) 2.36 (Math TeX Gyre Regular) -U+1d638 u1D638 2.23 (Sans Condensed Oblique, Sans Oblique) 2.36 (Math TeX Gyre Regular) -U+1d639 u1D639 2.23 (Sans Condensed Oblique, Sans Oblique) 2.36 (Math TeX Gyre Regular) -U+1d63a u1D63A 2.23 (Sans Condensed Oblique, Sans Oblique) 2.36 (Math TeX Gyre Regular) -U+1d63b u1D63B 2.23 (Sans Condensed Oblique, Sans Oblique) 2.36 (Math TeX Gyre Regular) -U+1d63c u1D63C 2.23 (Sans Bold Oblique, Sans Condensed Bold Oblique) 2.36 (Math TeX Gyre Regular) -U+1d63d u1D63D 2.23 (Sans Bold Oblique, Sans Condensed Bold Oblique) 2.36 (Math TeX Gyre Regular) -U+1d63e u1D63E 2.23 (Sans Bold Oblique, Sans Condensed Bold Oblique) 2.36 (Math TeX Gyre Regular) -U+1d63f u1D63F 2.23 (Sans Bold Oblique, Sans Condensed Bold Oblique) 2.36 (Math TeX Gyre Regular) -U+1d640 u1D640 2.23 (Sans Bold Oblique, Sans Condensed Bold Oblique) 2.36 (Math TeX Gyre Regular) -U+1d641 u1D641 2.23 (Sans Bold Oblique, Sans Condensed Bold Oblique) 2.36 (Math TeX Gyre Regular) -U+1d642 u1D642 2.23 (Sans Bold Oblique, Sans Condensed Bold Oblique) 2.36 (Math TeX Gyre Regular) -U+1d643 u1D643 2.23 (Sans Bold Oblique, Sans Condensed Bold Oblique) 2.36 (Math TeX Gyre Regular) -U+1d644 u1D644 2.23 (Sans Bold Oblique, Sans Condensed Bold Oblique) 2.36 (Math TeX Gyre Regular) -U+1d645 u1D645 2.23 (Sans Bold Oblique, Sans Condensed Bold Oblique) 2.36 (Math TeX Gyre Regular) -U+1d646 u1D646 2.23 (Sans Bold Oblique, Sans Condensed Bold Oblique) 2.36 (Math TeX Gyre Regular) -U+1d647 u1D647 2.23 (Sans Bold Oblique, Sans Condensed Bold Oblique) 2.36 (Math TeX Gyre Regular) -U+1d648 u1D648 2.23 (Sans Bold Oblique, Sans Condensed Bold Oblique) 2.36 (Math TeX Gyre Regular) -U+1d649 u1D649 2.23 (Sans Bold Oblique, Sans Condensed Bold Oblique) 2.36 (Math TeX Gyre Regular) -U+1d64a u1D64A 2.23 (Sans Bold Oblique, Sans Condensed Bold Oblique) 2.36 (Math TeX Gyre Regular) -U+1d64b u1D64B 2.23 (Sans Bold Oblique, Sans Condensed Bold Oblique) 2.36 (Math TeX Gyre Regular) -U+1d64c u1D64C 2.23 (Sans Bold Oblique, Sans Condensed Bold Oblique) 2.36 (Math TeX Gyre Regular) -U+1d64d u1D64D 2.23 (Sans Bold Oblique, Sans Condensed Bold Oblique) 2.36 (Math TeX Gyre Regular) -U+1d64e u1D64E 2.23 (Sans Bold Oblique, Sans Condensed Bold Oblique) 2.36 (Math TeX Gyre Regular) -U+1d64f u1D64F 2.23 (Sans Bold Oblique, Sans Condensed Bold Oblique) 2.36 (Math TeX Gyre Regular) -U+1d650 u1D650 2.23 (Sans Bold Oblique, Sans Condensed Bold Oblique) 2.36 (Math TeX Gyre Regular) -U+1d651 u1D651 2.23 (Sans Bold Oblique, Sans Condensed Bold Oblique) 2.36 (Math TeX Gyre Regular) -U+1d652 u1D652 2.23 (Sans Bold Oblique, Sans Condensed Bold Oblique) 2.36 (Math TeX Gyre Regular) -U+1d653 u1D653 2.23 (Sans Bold Oblique, Sans Condensed Bold Oblique) 2.36 (Math TeX Gyre Regular) -U+1d654 u1D654 2.23 (Sans Bold Oblique, Sans Condensed Bold Oblique) 2.36 (Math TeX Gyre Regular) -U+1d655 u1D655 2.23 (Sans Bold Oblique, Sans Condensed Bold Oblique) 2.36 (Math TeX Gyre Regular) -U+1d656 u1D656 2.23 (Sans Bold Oblique, Sans Condensed Bold Oblique) 2.36 (Math TeX Gyre Regular) -U+1d657 u1D657 2.23 (Sans Bold Oblique, Sans Condensed Bold Oblique) 2.36 (Math TeX Gyre Regular) -U+1d658 u1D658 2.23 (Sans Bold Oblique, Sans Condensed Bold Oblique) 2.36 (Math TeX Gyre Regular) -U+1d659 u1D659 2.23 (Sans Bold Oblique, Sans Condensed Bold Oblique) 2.36 (Math TeX Gyre Regular) -U+1d65a u1D65A 2.23 (Sans Bold Oblique, Sans Condensed Bold Oblique) 2.36 (Math TeX Gyre Regular) -U+1d65b u1D65B 2.23 (Sans Bold Oblique, Sans Condensed Bold Oblique) 2.36 (Math TeX Gyre Regular) -U+1d65c u1D65C 2.23 (Sans Bold Oblique, Sans Condensed Bold Oblique) 2.36 (Math TeX Gyre Regular) -U+1d65d u1D65D 2.23 (Sans Bold Oblique, Sans Condensed Bold Oblique) 2.36 (Math TeX Gyre Regular) -U+1d65e u1D65E 2.23 (Sans Bold Oblique, Sans Condensed Bold Oblique) 2.36 (Math TeX Gyre Regular) -U+1d65f u1D65F 2.23 (Sans Bold Oblique, Sans Condensed Bold Oblique) 2.36 (Math TeX Gyre Regular) -U+1d660 u1D660 2.23 (Sans Bold Oblique, Sans Condensed Bold Oblique) 2.36 (Math TeX Gyre Regular) -U+1d661 u1D661 2.23 (Sans Bold Oblique, Sans Condensed Bold Oblique) 2.36 (Math TeX Gyre Regular) -U+1d662 u1D662 2.23 (Sans Bold Oblique, Sans Condensed Bold Oblique) 2.36 (Math TeX Gyre Regular) -U+1d663 u1D663 2.23 (Sans Bold Oblique, Sans Condensed Bold Oblique) 2.36 (Math TeX Gyre Regular) -U+1d664 u1D664 2.23 (Sans Bold Oblique, Sans Condensed Bold Oblique) 2.36 (Math TeX Gyre Regular) -U+1d665 u1D665 2.23 (Sans Bold Oblique, Sans Condensed Bold Oblique) 2.36 (Math TeX Gyre Regular) -U+1d666 u1D666 2.23 (Sans Bold Oblique, Sans Condensed Bold Oblique) 2.36 (Math TeX Gyre Regular) -U+1d667 u1D667 2.23 (Sans Bold Oblique, Sans Condensed Bold Oblique) 2.36 (Math TeX Gyre Regular) -U+1d668 u1D668 2.23 (Sans Bold Oblique, Sans Condensed Bold Oblique) 2.36 (Math TeX Gyre Regular) -U+1d669 u1D669 2.23 (Sans Bold Oblique, Sans Condensed Bold Oblique) 2.36 (Math TeX Gyre Regular) -U+1d66a u1D66A 2.23 (Sans Bold Oblique, Sans Condensed Bold Oblique) 2.36 (Math TeX Gyre Regular) -U+1d66b u1D66B 2.23 (Sans Bold Oblique, Sans Condensed Bold Oblique) 2.36 (Math TeX Gyre Regular) -U+1d66c u1D66C 2.23 (Sans Bold Oblique, Sans Condensed Bold Oblique) 2.36 (Math TeX Gyre Regular) -U+1d66d u1D66D 2.23 (Sans Bold Oblique, Sans Condensed Bold Oblique) 2.36 (Math TeX Gyre Regular) -U+1d66e u1D66E 2.23 (Sans Bold Oblique, Sans Condensed Bold Oblique) 2.36 (Math TeX Gyre Regular) -U+1d66f u1D66F 2.23 (Sans Bold Oblique, Sans Condensed Bold Oblique) 2.36 (Math TeX Gyre Regular) -U+1d670 u1D670 2.23 (Sans Mono) 2.36 (Math TeX Gyre Regular) -U+1d671 u1D671 2.23 (Sans Mono) 2.36 (Math TeX Gyre Regular) -U+1d672 u1D672 2.23 (Sans Mono) 2.36 (Math TeX Gyre Regular) -U+1d673 u1D673 2.23 (Sans Mono) 2.36 (Math TeX Gyre Regular) -U+1d674 u1D674 2.23 (Sans Mono) 2.36 (Math TeX Gyre Regular) -U+1d675 u1D675 2.23 (Sans Mono) 2.36 (Math TeX Gyre Regular) -U+1d676 u1D676 2.23 (Sans Mono) 2.36 (Math TeX Gyre Regular) -U+1d677 u1D677 2.23 (Sans Mono) 2.36 (Math TeX Gyre Regular) -U+1d678 u1D678 2.23 (Sans Mono) 2.36 (Math TeX Gyre Regular) -U+1d679 u1D679 2.23 (Sans Mono) 2.36 (Math TeX Gyre Regular) -U+1d67a u1D67A 2.23 (Sans Mono) 2.36 (Math TeX Gyre Regular) -U+1d67b u1D67B 2.23 (Sans Mono) 2.36 (Math TeX Gyre Regular) -U+1d67c u1D67C 2.23 (Sans Mono) 2.36 (Math TeX Gyre Regular) -U+1d67d u1D67D 2.23 (Sans Mono) 2.36 (Math TeX Gyre Regular) -U+1d67e u1D67E 2.23 (Sans Mono) 2.36 (Math TeX Gyre Regular) -U+1d67f u1D67F 2.23 (Sans Mono) 2.36 (Math TeX Gyre Regular) -U+1d680 u1D680 2.23 (Sans Mono) 2.36 (Math TeX Gyre Regular) -U+1d681 u1D681 2.23 (Sans Mono) 2.36 (Math TeX Gyre Regular) -U+1d682 u1D682 2.23 (Sans Mono) 2.36 (Math TeX Gyre Regular) -U+1d683 u1D683 2.23 (Sans Mono) 2.36 (Math TeX Gyre Regular) -U+1d684 u1D684 2.23 (Sans Mono) 2.36 (Math TeX Gyre Regular) -U+1d685 u1D685 2.23 (Sans Mono) 2.36 (Math TeX Gyre Regular) -U+1d686 u1D686 2.23 (Sans Mono) 2.36 (Math TeX Gyre Regular) -U+1d687 u1D687 2.23 (Sans Mono) 2.36 (Math TeX Gyre Regular) -U+1d688 u1D688 2.23 (Sans Mono) 2.36 (Math TeX Gyre Regular) -U+1d689 u1D689 2.23 (Sans Mono) 2.36 (Math TeX Gyre Regular) -U+1d68a u1D68A 2.23 (Sans Mono) 2.36 (Math TeX Gyre Regular) -U+1d68b u1D68B 2.23 (Sans Mono) 2.36 (Math TeX Gyre Regular) -U+1d68c u1D68C 2.23 (Sans Mono) 2.36 (Math TeX Gyre Regular) -U+1d68d u1D68D 2.23 (Sans Mono) 2.36 (Math TeX Gyre Regular) -U+1d68e u1D68E 2.23 (Sans Mono) 2.36 (Math TeX Gyre Regular) -U+1d68f u1D68F 2.23 (Sans Mono) 2.36 (Math TeX Gyre Regular) -U+1d690 u1D690 2.23 (Sans Mono) 2.36 (Math TeX Gyre Regular) -U+1d691 u1D691 2.23 (Sans Mono) 2.36 (Math TeX Gyre Regular) -U+1d692 u1D692 2.23 (Sans Mono) 2.36 (Math TeX Gyre Regular) -U+1d693 u1D693 2.23 (Sans Mono) 2.36 (Math TeX Gyre Regular) -U+1d694 u1D694 2.23 (Sans Mono) 2.36 (Math TeX Gyre Regular) -U+1d695 u1D695 2.23 (Sans Mono) 2.36 (Math TeX Gyre Regular) -U+1d696 u1D696 2.23 (Sans Mono) 2.36 (Math TeX Gyre Regular) -U+1d697 u1D697 2.23 (Sans Mono) 2.36 (Math TeX Gyre Regular) -U+1d698 u1D698 2.23 (Sans Mono) 2.36 (Math TeX Gyre Regular) -U+1d699 u1D699 2.23 (Sans Mono) 2.36 (Math TeX Gyre Regular) -U+1d69a u1D69A 2.23 (Sans Mono) 2.36 (Math TeX Gyre Regular) -U+1d69b u1D69B 2.23 (Sans Mono) 2.36 (Math TeX Gyre Regular) -U+1d69c u1D69C 2.23 (Sans Mono) 2.36 (Math TeX Gyre Regular) -U+1d69d u1D69D 2.23 (Sans Mono) 2.36 (Math TeX Gyre Regular) -U+1d69e u1D69E 2.23 (Sans Mono) 2.36 (Math TeX Gyre Regular) -U+1d69f u1D69F 2.23 (Sans Mono) 2.36 (Math TeX Gyre Regular) -U+1d6a0 u1D6A0 2.23 (Sans Mono) 2.36 (Math TeX Gyre Regular) -U+1d6a1 u1D6A1 2.23 (Sans Mono) 2.36 (Math TeX Gyre Regular) -U+1d6a2 u1D6A2 2.23 (Sans Mono) 2.36 (Math TeX Gyre Regular) -U+1d6a3 u1D6A3 2.23 (Sans Mono) 2.36 (Math TeX Gyre Regular) -U+1d6a4 u1D6A4 2.23 (Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) 2.35 (Serif, Serif Condensed) 2.36 (Math TeX Gyre Regular) -U+1d6a5 u1D6A5 2.23 (Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) 2.35 (Serif, Serif Condensed) 2.36 (Math TeX Gyre Regular) -U+1d6a8 u1D6A8 2.23 (Serif Bold, Serif Condensed Bold) 2.36 (Math TeX Gyre Regular) -U+1d6a9 u1D6A9 2.23 (Serif Bold, Serif Condensed Bold) 2.36 (Math TeX Gyre Regular) -U+1d6aa u1D6AA 2.23 (Serif Bold, Serif Condensed Bold) 2.36 (Math TeX Gyre Regular) -U+1d6ab u1D6AB 2.23 (Serif Bold, Serif Condensed Bold) 2.36 (Math TeX Gyre Regular) -U+1d6ac u1D6AC 2.23 (Serif Bold, Serif Condensed Bold) 2.36 (Math TeX Gyre Regular) -U+1d6ad u1D6AD 2.23 (Serif Bold, Serif Condensed Bold) 2.36 (Math TeX Gyre Regular) -U+1d6ae u1D6AE 2.23 (Serif Bold, Serif Condensed Bold) 2.36 (Math TeX Gyre Regular) -U+1d6af u1D6AF 2.23 (Serif Bold, Serif Condensed Bold) 2.36 (Math TeX Gyre Regular) -U+1d6b0 u1D6B0 2.23 (Serif Bold, Serif Condensed Bold) 2.36 (Math TeX Gyre Regular) -U+1d6b1 u1D6B1 2.23 (Serif Bold, Serif Condensed Bold) 2.36 (Math TeX Gyre Regular) -U+1d6b2 u1D6B2 2.23 (Serif Bold, Serif Condensed Bold) 2.36 (Math TeX Gyre Regular) -U+1d6b3 u1D6B3 2.23 (Serif Bold, Serif Condensed Bold) 2.36 (Math TeX Gyre Regular) -U+1d6b4 u1D6B4 2.23 (Serif Bold, Serif Condensed Bold) 2.36 (Math TeX Gyre Regular) -U+1d6b5 u1D6B5 2.23 (Serif Bold, Serif Condensed Bold) 2.36 (Math TeX Gyre Regular) -U+1d6b6 u1D6B6 2.23 (Serif Bold, Serif Condensed Bold) 2.36 (Math TeX Gyre Regular) -U+1d6b7 u1D6B7 2.23 (Serif Bold, Serif Condensed Bold) 2.36 (Math TeX Gyre Regular) -U+1d6b8 u1D6B8 2.23 (Serif Bold, Serif Condensed Bold) 2.36 (Math TeX Gyre Regular) -U+1d6b9 u1D6B9 2.23 (Serif Bold, Serif Condensed Bold) 2.36 (Math TeX Gyre Regular) -U+1d6ba u1D6BA 2.23 (Serif Bold, Serif Condensed Bold) 2.36 (Math TeX Gyre Regular) -U+1d6bb u1D6BB 2.23 (Serif Bold, Serif Condensed Bold) 2.36 (Math TeX Gyre Regular) -U+1d6bc u1D6BC 2.23 (Serif Bold, Serif Condensed Bold) 2.36 (Math TeX Gyre Regular) -U+1d6bd u1D6BD 2.23 (Serif Bold, Serif Condensed Bold) 2.36 (Math TeX Gyre Regular) -U+1d6be u1D6BE 2.23 (Serif Bold, Serif Condensed Bold) 2.36 (Math TeX Gyre Regular) -U+1d6bf u1D6BF 2.23 (Serif Bold, Serif Condensed Bold) 2.36 (Math TeX Gyre Regular) -U+1d6c0 u1D6C0 2.23 (Serif Bold, Serif Condensed Bold) 2.36 (Math TeX Gyre Regular) -U+1d6c1 u1D6C1 2.23 (Serif Bold, Serif Condensed Bold) 2.36 (Math TeX Gyre Regular) -U+1d6c2 u1D6C2 2.23 (Serif Bold, Serif Condensed Bold) 2.36 (Math TeX Gyre Regular) -U+1d6c3 u1D6C3 2.23 (Serif Bold, Serif Condensed Bold) 2.36 (Math TeX Gyre Regular) -U+1d6c4 u1D6C4 2.23 (Serif Bold, Serif Condensed Bold) 2.36 (Math TeX Gyre Regular) -U+1d6c5 u1D6C5 2.23 (Serif Bold, Serif Condensed Bold) 2.36 (Math TeX Gyre Regular) -U+1d6c6 u1D6C6 2.23 (Serif Bold, Serif Condensed Bold) 2.36 (Math TeX Gyre Regular) -U+1d6c7 u1D6C7 2.23 (Serif Bold, Serif Condensed Bold) 2.36 (Math TeX Gyre Regular) -U+1d6c8 u1D6C8 2.23 (Serif Bold, Serif Condensed Bold) 2.36 (Math TeX Gyre Regular) -U+1d6c9 u1D6C9 2.23 (Serif Bold, Serif Condensed Bold) 2.36 (Math TeX Gyre Regular) -U+1d6ca u1D6CA 2.23 (Serif Bold, Serif Condensed Bold) 2.36 (Math TeX Gyre Regular) -U+1d6cb u1D6CB 2.23 (Serif Bold, Serif Condensed Bold) 2.36 (Math TeX Gyre Regular) -U+1d6cc u1D6CC 2.23 (Serif Bold, Serif Condensed Bold) 2.36 (Math TeX Gyre Regular) -U+1d6cd u1D6CD 2.23 (Serif Bold, Serif Condensed Bold) 2.36 (Math TeX Gyre Regular) -U+1d6ce u1D6CE 2.23 (Serif Bold, Serif Condensed Bold) 2.36 (Math TeX Gyre Regular) -U+1d6cf u1D6CF 2.23 (Serif Bold, Serif Condensed Bold) 2.36 (Math TeX Gyre Regular) -U+1d6d0 u1D6D0 2.23 (Serif Bold, Serif Condensed Bold) 2.36 (Math TeX Gyre Regular) -U+1d6d1 u1D6D1 2.23 (Serif Bold, Serif Condensed Bold) 2.36 (Math TeX Gyre Regular) -U+1d6d2 u1D6D2 2.23 (Serif Bold, Serif Condensed Bold) 2.36 (Math TeX Gyre Regular) -U+1d6d3 u1D6D3 2.23 (Serif Bold, Serif Condensed Bold) 2.36 (Math TeX Gyre Regular) -U+1d6d4 u1D6D4 2.23 (Serif Bold, Serif Condensed Bold) 2.36 (Math TeX Gyre Regular) -U+1d6d5 u1D6D5 2.23 (Serif Bold, Serif Condensed Bold) 2.36 (Math TeX Gyre Regular) -U+1d6d6 u1D6D6 2.23 (Serif Bold, Serif Condensed Bold) 2.36 (Math TeX Gyre Regular) -U+1d6d7 u1D6D7 2.23 (Serif Bold, Serif Condensed Bold) 2.36 (Math TeX Gyre Regular) -U+1d6d8 u1D6D8 2.23 (Serif Bold, Serif Condensed Bold) 2.36 (Math TeX Gyre Regular) -U+1d6d9 u1D6D9 2.23 (Serif Bold, Serif Condensed Bold) 2.36 (Math TeX Gyre Regular) -U+1d6da u1D6DA 2.23 (Serif Bold, Serif Condensed Bold) 2.36 (Math TeX Gyre Regular) -U+1d6db u1D6DB 2.23 (Serif Bold, Serif Condensed Bold) 2.36 (Math TeX Gyre Regular) -U+1d6dc u1D6DC 2.23 (Serif Bold, Serif Condensed Bold) 2.36 (Math TeX Gyre Regular) -U+1d6dd u1D6DD 2.23 (Serif Bold, Serif Condensed Bold) 2.36 (Math TeX Gyre Regular) -U+1d6de u1D6DE 2.23 (Serif Bold, Serif Condensed Bold) 2.36 (Math TeX Gyre Regular) -U+1d6df u1D6DF 2.23 (Serif Bold, Serif Condensed Bold) 2.36 (Math TeX Gyre Regular) -U+1d6e0 u1D6E0 2.23 (Serif Bold, Serif Condensed Bold) 2.36 (Math TeX Gyre Regular) -U+1d6e1 u1D6E1 2.23 (Serif Bold, Serif Condensed Bold) 2.36 (Math TeX Gyre Regular) -U+1d6e2 u1D6E2 2.23 (Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) 2.36 (Math TeX Gyre Regular) -U+1d6e3 u1D6E3 2.23 (Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) 2.36 (Math TeX Gyre Regular) -U+1d6e4 u1D6E4 2.23 (Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) 2.36 (Math TeX Gyre Regular) -U+1d6e5 u1D6E5 2.23 (Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) 2.36 (Math TeX Gyre Regular) -U+1d6e6 u1D6E6 2.23 (Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) 2.36 (Math TeX Gyre Regular) -U+1d6e7 u1D6E7 2.23 (Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) 2.36 (Math TeX Gyre Regular) -U+1d6e8 u1D6E8 2.23 (Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) 2.36 (Math TeX Gyre Regular) -U+1d6e9 u1D6E9 2.23 (Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) 2.36 (Math TeX Gyre Regular) -U+1d6ea u1D6EA 2.23 (Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) 2.36 (Math TeX Gyre Regular) -U+1d6eb u1D6EB 2.23 (Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) 2.36 (Math TeX Gyre Regular) -U+1d6ec u1D6EC 2.23 (Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) 2.36 (Math TeX Gyre Regular) -U+1d6ed u1D6ED 2.23 (Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) 2.36 (Math TeX Gyre Regular) -U+1d6ee u1D6EE 2.23 (Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) 2.36 (Math TeX Gyre Regular) -U+1d6ef u1D6EF 2.23 (Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) 2.36 (Math TeX Gyre Regular) -U+1d6f0 u1D6F0 2.23 (Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) 2.36 (Math TeX Gyre Regular) -U+1d6f1 u1D6F1 2.23 (Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) 2.36 (Math TeX Gyre Regular) -U+1d6f2 u1D6F2 2.23 (Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) 2.36 (Math TeX Gyre Regular) -U+1d6f3 u1D6F3 2.23 (Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) 2.36 (Math TeX Gyre Regular) -U+1d6f4 u1D6F4 2.23 (Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) 2.36 (Math TeX Gyre Regular) -U+1d6f5 u1D6F5 2.23 (Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) 2.36 (Math TeX Gyre Regular) -U+1d6f6 u1D6F6 2.23 (Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) 2.36 (Math TeX Gyre Regular) -U+1d6f7 u1D6F7 2.23 (Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) 2.36 (Math TeX Gyre Regular) -U+1d6f8 u1D6F8 2.23 (Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) 2.36 (Math TeX Gyre Regular) -U+1d6f9 u1D6F9 2.23 (Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) 2.36 (Math TeX Gyre Regular) -U+1d6fa u1D6FA 2.23 (Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) 2.36 (Math TeX Gyre Regular) -U+1d6fb u1D6FB 2.23 (Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) 2.36 (Math TeX Gyre Regular) -U+1d6fc u1D6FC 2.23 (Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) 2.36 (Math TeX Gyre Regular) -U+1d6fd u1D6FD 2.23 (Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) 2.36 (Math TeX Gyre Regular) -U+1d6fe u1D6FE 2.23 (Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) 2.36 (Math TeX Gyre Regular) -U+1d6ff u1D6FF 2.23 (Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) 2.36 (Math TeX Gyre Regular) -U+1d700 u1D700 2.23 (Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) 2.36 (Math TeX Gyre Regular) -U+1d701 u1D701 2.23 (Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) 2.36 (Math TeX Gyre Regular) -U+1d702 u1D702 2.23 (Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) 2.36 (Math TeX Gyre Regular) -U+1d703 u1D703 2.23 (Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) 2.36 (Math TeX Gyre Regular) -U+1d704 u1D704 2.23 (Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) 2.36 (Math TeX Gyre Regular) -U+1d705 u1D705 2.23 (Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) 2.36 (Math TeX Gyre Regular) -U+1d706 u1D706 2.23 (Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) 2.36 (Math TeX Gyre Regular) -U+1d707 u1D707 2.23 (Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) 2.36 (Math TeX Gyre Regular) -U+1d708 u1D708 2.23 (Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) 2.36 (Math TeX Gyre Regular) -U+1d709 u1D709 2.23 (Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) 2.36 (Math TeX Gyre Regular) -U+1d70a u1D70A 2.23 (Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) 2.36 (Math TeX Gyre Regular) -U+1d70b u1D70B 2.23 (Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) 2.36 (Math TeX Gyre Regular) -U+1d70c u1D70C 2.23 (Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) 2.36 (Math TeX Gyre Regular) -U+1d70d u1D70D 2.23 (Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) 2.36 (Math TeX Gyre Regular) -U+1d70e u1D70E 2.23 (Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) 2.36 (Math TeX Gyre Regular) -U+1d70f u1D70F 2.23 (Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) 2.36 (Math TeX Gyre Regular) -U+1d710 u1D710 2.23 (Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) 2.36 (Math TeX Gyre Regular) -U+1d711 u1D711 2.23 (Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) 2.36 (Math TeX Gyre Regular) -U+1d712 u1D712 2.23 (Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) 2.36 (Math TeX Gyre Regular) -U+1d713 u1D713 2.23 (Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) 2.36 (Math TeX Gyre Regular) -U+1d714 u1D714 2.23 (Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) 2.36 (Math TeX Gyre Regular) -U+1d715 u1D715 2.23 (Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) 2.36 (Math TeX Gyre Regular) -U+1d716 u1D716 2.23 (Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) 2.36 (Math TeX Gyre Regular) -U+1d717 u1D717 2.23 (Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) 2.36 (Math TeX Gyre Regular) -U+1d718 u1D718 2.23 (Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) 2.36 (Math TeX Gyre Regular) -U+1d719 u1D719 2.23 (Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) 2.36 (Math TeX Gyre Regular) -U+1d71a u1D71A 2.23 (Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) 2.36 (Math TeX Gyre Regular) -U+1d71b u1D71B 2.23 (Serif Italic, Serif Italic Condensed) 2.31 (Serif Condensed Italic) 2.36 (Math TeX Gyre Regular) -U+1d71c u1D71C 2.23 (Serif Bold Italic, Serif Condensed Bold Italic) 2.36 (Math TeX Gyre Regular) -U+1d71d u1D71D 2.23 (Serif Bold Italic, Serif Condensed Bold Italic) 2.36 (Math TeX Gyre Regular) -U+1d71e u1D71E 2.23 (Serif Bold Italic, Serif Condensed Bold Italic) 2.36 (Math TeX Gyre Regular) -U+1d71f u1D71F 2.23 (Serif Bold Italic, Serif Condensed Bold Italic) 2.36 (Math TeX Gyre Regular) -U+1d720 u1D720 2.23 (Serif Bold Italic, Serif Condensed Bold Italic) 2.36 (Math TeX Gyre Regular) -U+1d721 u1D721 2.23 (Serif Bold Italic, Serif Condensed Bold Italic) 2.36 (Math TeX Gyre Regular) -U+1d722 u1D722 2.23 (Serif Bold Italic, Serif Condensed Bold Italic) 2.36 (Math TeX Gyre Regular) -U+1d723 u1D723 2.23 (Serif Bold Italic, Serif Condensed Bold Italic) 2.36 (Math TeX Gyre Regular) -U+1d724 u1D724 2.23 (Serif Bold Italic, Serif Condensed Bold Italic) 2.36 (Math TeX Gyre Regular) -U+1d725 u1D725 2.23 (Serif Bold Italic, Serif Condensed Bold Italic) 2.36 (Math TeX Gyre Regular) -U+1d726 u1D726 2.23 (Serif Bold Italic, Serif Condensed Bold Italic) 2.36 (Math TeX Gyre Regular) -U+1d727 u1D727 2.23 (Serif Bold Italic, Serif Condensed Bold Italic) 2.36 (Math TeX Gyre Regular) -U+1d728 u1D728 2.23 (Serif Bold Italic, Serif Condensed Bold Italic) 2.36 (Math TeX Gyre Regular) -U+1d729 u1D729 2.23 (Serif Bold Italic, Serif Condensed Bold Italic) 2.36 (Math TeX Gyre Regular) -U+1d72a u1D72A 2.23 (Serif Bold Italic, Serif Condensed Bold Italic) 2.36 (Math TeX Gyre Regular) -U+1d72b u1D72B 2.23 (Serif Bold Italic, Serif Condensed Bold Italic) 2.36 (Math TeX Gyre Regular) -U+1d72c u1D72C 2.23 (Serif Bold Italic, Serif Condensed Bold Italic) 2.36 (Math TeX Gyre Regular) -U+1d72d u1D72D 2.23 (Serif Bold Italic, Serif Condensed Bold Italic) 2.36 (Math TeX Gyre Regular) -U+1d72e u1D72E 2.23 (Serif Bold Italic, Serif Condensed Bold Italic) 2.36 (Math TeX Gyre Regular) -U+1d72f u1D72F 2.23 (Serif Bold Italic, Serif Condensed Bold Italic) 2.36 (Math TeX Gyre Regular) -U+1d730 u1D730 2.23 (Serif Bold Italic, Serif Condensed Bold Italic) 2.36 (Math TeX Gyre Regular) -U+1d731 u1D731 2.23 (Serif Bold Italic, Serif Condensed Bold Italic) 2.36 (Math TeX Gyre Regular) -U+1d732 u1D732 2.23 (Serif Bold Italic, Serif Condensed Bold Italic) 2.36 (Math TeX Gyre Regular) -U+1d733 u1D733 2.23 (Serif Bold Italic, Serif Condensed Bold Italic) 2.36 (Math TeX Gyre Regular) -U+1d734 u1D734 2.23 (Serif Bold Italic, Serif Condensed Bold Italic) 2.36 (Math TeX Gyre Regular) -U+1d735 u1D735 2.23 (Serif Bold Italic, Serif Condensed Bold Italic) 2.36 (Math TeX Gyre Regular) -U+1d736 u1D736 2.23 (Serif Bold Italic, Serif Condensed Bold Italic) 2.36 (Math TeX Gyre Regular) -U+1d737 u1D737 2.23 (Serif Bold Italic, Serif Condensed Bold Italic) 2.36 (Math TeX Gyre Regular) -U+1d738 u1D738 2.23 (Serif Bold Italic, Serif Condensed Bold Italic) 2.36 (Math TeX Gyre Regular) -U+1d739 u1D739 2.23 (Serif Bold Italic, Serif Condensed Bold Italic) 2.36 (Math TeX Gyre Regular) -U+1d73a u1D73A 2.23 (Serif Bold Italic, Serif Condensed Bold Italic) 2.36 (Math TeX Gyre Regular) -U+1d73b u1D73B 2.23 (Serif Bold Italic, Serif Condensed Bold Italic) 2.36 (Math TeX Gyre Regular) -U+1d73c u1D73C 2.23 (Serif Bold Italic, Serif Condensed Bold Italic) 2.36 (Math TeX Gyre Regular) -U+1d73d u1D73D 2.23 (Serif Bold Italic, Serif Condensed Bold Italic) 2.36 (Math TeX Gyre Regular) -U+1d73e u1D73E 2.23 (Serif Bold Italic, Serif Condensed Bold Italic) 2.36 (Math TeX Gyre Regular) -U+1d73f u1D73F 2.23 (Serif Bold Italic, Serif Condensed Bold Italic) 2.36 (Math TeX Gyre Regular) -U+1d740 u1D740 2.23 (Serif Bold Italic, Serif Condensed Bold Italic) 2.36 (Math TeX Gyre Regular) -U+1d741 u1D741 2.23 (Serif Bold Italic, Serif Condensed Bold Italic) 2.36 (Math TeX Gyre Regular) -U+1d742 u1D742 2.23 (Serif Bold Italic, Serif Condensed Bold Italic) 2.36 (Math TeX Gyre Regular) -U+1d743 u1D743 2.23 (Serif Bold Italic, Serif Condensed Bold Italic) 2.36 (Math TeX Gyre Regular) -U+1d744 u1D744 2.23 (Serif Bold Italic, Serif Condensed Bold Italic) 2.36 (Math TeX Gyre Regular) -U+1d745 u1D745 2.23 (Serif Bold Italic, Serif Condensed Bold Italic) 2.36 (Math TeX Gyre Regular) -U+1d746 u1D746 2.23 (Serif Bold Italic, Serif Condensed Bold Italic) 2.36 (Math TeX Gyre Regular) -U+1d747 u1D747 2.23 (Serif Bold Italic, Serif Condensed Bold Italic) 2.36 (Math TeX Gyre Regular) -U+1d748 u1D748 2.23 (Serif Bold Italic, Serif Condensed Bold Italic) 2.36 (Math TeX Gyre Regular) -U+1d749 u1D749 2.23 (Serif Bold Italic, Serif Condensed Bold Italic) 2.36 (Math TeX Gyre Regular) -U+1d74a u1D74A 2.23 (Serif Bold Italic, Serif Condensed Bold Italic) 2.36 (Math TeX Gyre Regular) -U+1d74b u1D74B 2.23 (Serif Bold Italic, Serif Condensed Bold Italic) 2.36 (Math TeX Gyre Regular) -U+1d74c u1D74C 2.23 (Serif Bold Italic, Serif Condensed Bold Italic) 2.36 (Math TeX Gyre Regular) -U+1d74d u1D74D 2.23 (Serif Bold Italic, Serif Condensed Bold Italic) 2.36 (Math TeX Gyre Regular) -U+1d74e u1D74E 2.23 (Serif Bold Italic, Serif Condensed Bold Italic) 2.36 (Math TeX Gyre Regular) -U+1d74f u1D74F 2.23 (Serif Bold Italic, Serif Condensed Bold Italic) 2.36 (Math TeX Gyre Regular) -U+1d750 u1D750 2.23 (Serif Bold Italic, Serif Condensed Bold Italic) 2.36 (Math TeX Gyre Regular) -U+1d751 u1D751 2.23 (Serif Bold Italic, Serif Condensed Bold Italic) 2.36 (Math TeX Gyre Regular) -U+1d752 u1D752 2.23 (Serif Bold Italic, Serif Condensed Bold Italic) 2.36 (Math TeX Gyre Regular) -U+1d753 u1D753 2.23 (Serif Bold Italic, Serif Condensed Bold Italic) 2.36 (Math TeX Gyre Regular) -U+1d754 u1D754 2.23 (Serif Bold Italic, Serif Condensed Bold Italic) 2.36 (Math TeX Gyre Regular) -U+1d755 u1D755 2.23 (Serif Bold Italic, Serif Condensed Bold Italic) 2.36 (Math TeX Gyre Regular) -U+1d756 u1D756 2.23 (Sans Bold, Sans Condensed Bold) 2.36 (Math TeX Gyre Regular) -U+1d757 u1D757 2.23 (Sans Bold, Sans Condensed Bold) 2.36 (Math TeX Gyre Regular) -U+1d758 u1D758 2.23 (Sans Bold, Sans Condensed Bold) 2.36 (Math TeX Gyre Regular) -U+1d759 u1D759 2.23 (Sans Bold, Sans Condensed Bold) 2.36 (Math TeX Gyre Regular) -U+1d75a u1D75A 2.23 (Sans Bold, Sans Condensed Bold) 2.36 (Math TeX Gyre Regular) -U+1d75b u1D75B 2.23 (Sans Bold, Sans Condensed Bold) 2.36 (Math TeX Gyre Regular) -U+1d75c u1D75C 2.23 (Sans Bold, Sans Condensed Bold) 2.36 (Math TeX Gyre Regular) -U+1d75d u1D75D 2.23 (Sans Bold, Sans Condensed Bold) 2.36 (Math TeX Gyre Regular) -U+1d75e u1D75E 2.23 (Sans Bold, Sans Condensed Bold) 2.36 (Math TeX Gyre Regular) -U+1d75f u1D75F 2.23 (Sans Bold, Sans Condensed Bold) 2.36 (Math TeX Gyre Regular) -U+1d760 u1D760 2.23 (Sans Bold, Sans Condensed Bold) 2.36 (Math TeX Gyre Regular) -U+1d761 u1D761 2.23 (Sans Bold, Sans Condensed Bold) 2.36 (Math TeX Gyre Regular) -U+1d762 u1D762 2.23 (Sans Bold, Sans Condensed Bold) 2.36 (Math TeX Gyre Regular) -U+1d763 u1D763 2.23 (Sans Bold, Sans Condensed Bold) 2.36 (Math TeX Gyre Regular) -U+1d764 u1D764 2.23 (Sans Bold, Sans Condensed Bold) 2.36 (Math TeX Gyre Regular) -U+1d765 u1D765 2.23 (Sans Bold, Sans Condensed Bold) 2.36 (Math TeX Gyre Regular) -U+1d766 u1D766 2.23 (Sans Bold, Sans Condensed Bold) 2.36 (Math TeX Gyre Regular) -U+1d767 u1D767 2.23 (Sans Bold, Sans Condensed Bold) 2.36 (Math TeX Gyre Regular) -U+1d768 u1D768 2.23 (Sans Bold, Sans Condensed Bold) 2.36 (Math TeX Gyre Regular) -U+1d769 u1D769 2.23 (Sans Bold, Sans Condensed Bold) 2.36 (Math TeX Gyre Regular) -U+1d76a u1D76A 2.23 (Sans Bold, Sans Condensed Bold) 2.36 (Math TeX Gyre Regular) -U+1d76b u1D76B 2.23 (Sans Bold, Sans Condensed Bold) 2.36 (Math TeX Gyre Regular) -U+1d76c u1D76C 2.23 (Sans Bold, Sans Condensed Bold) 2.36 (Math TeX Gyre Regular) -U+1d76d u1D76D 2.23 (Sans Bold, Sans Condensed Bold) 2.36 (Math TeX Gyre Regular) -U+1d76e u1D76E 2.23 (Sans Bold, Sans Condensed Bold) 2.36 (Math TeX Gyre Regular) -U+1d76f u1D76F 2.23 (Sans Bold, Sans Condensed Bold) 2.36 (Math TeX Gyre Regular) -U+1d770 u1D770 2.23 (Sans Bold, Sans Condensed Bold) 2.36 (Math TeX Gyre Regular) -U+1d771 u1D771 2.23 (Sans Bold, Sans Condensed Bold) 2.36 (Math TeX Gyre Regular) -U+1d772 u1D772 2.23 (Sans Bold, Sans Condensed Bold) 2.36 (Math TeX Gyre Regular) -U+1d773 u1D773 2.23 (Sans Bold, Sans Condensed Bold) 2.36 (Math TeX Gyre Regular) -U+1d774 u1D774 2.23 (Sans Bold, Sans Condensed Bold) 2.36 (Math TeX Gyre Regular) -U+1d775 u1D775 2.23 (Sans Bold, Sans Condensed Bold) 2.36 (Math TeX Gyre Regular) -U+1d776 u1D776 2.23 (Sans Bold, Sans Condensed Bold) 2.36 (Math TeX Gyre Regular) -U+1d777 u1D777 2.23 (Sans Bold, Sans Condensed Bold) 2.36 (Math TeX Gyre Regular) -U+1d778 u1D778 2.23 (Sans Bold, Sans Condensed Bold) 2.36 (Math TeX Gyre Regular) -U+1d779 u1D779 2.23 (Sans Bold, Sans Condensed Bold) 2.36 (Math TeX Gyre Regular) -U+1d77a u1D77A 2.23 (Sans Bold, Sans Condensed Bold) 2.36 (Math TeX Gyre Regular) -U+1d77b u1D77B 2.23 (Sans Bold, Sans Condensed Bold) 2.36 (Math TeX Gyre Regular) -U+1d77c u1D77C 2.23 (Sans Bold, Sans Condensed Bold) 2.36 (Math TeX Gyre Regular) -U+1d77d u1D77D 2.23 (Sans Bold, Sans Condensed Bold) 2.36 (Math TeX Gyre Regular) -U+1d77e u1D77E 2.23 (Sans Bold, Sans Condensed Bold) 2.36 (Math TeX Gyre Regular) -U+1d77f u1D77F 2.23 (Sans Bold, Sans Condensed Bold) 2.36 (Math TeX Gyre Regular) -U+1d780 u1D780 2.23 (Sans Bold, Sans Condensed Bold) 2.36 (Math TeX Gyre Regular) -U+1d781 u1D781 2.23 (Sans Bold, Sans Condensed Bold) 2.36 (Math TeX Gyre Regular) -U+1d782 u1D782 2.23 (Sans Bold, Sans Condensed Bold) 2.36 (Math TeX Gyre Regular) -U+1d783 u1D783 2.23 (Sans Bold, Sans Condensed Bold) 2.36 (Math TeX Gyre Regular) -U+1d784 u1D784 2.23 (Sans Bold, Sans Condensed Bold) 2.36 (Math TeX Gyre Regular) -U+1d785 u1D785 2.23 (Sans Bold, Sans Condensed Bold) 2.36 (Math TeX Gyre Regular) -U+1d786 u1D786 2.23 (Sans Bold, Sans Condensed Bold) 2.36 (Math TeX Gyre Regular) -U+1d787 u1D787 2.23 (Sans Bold, Sans Condensed Bold) 2.36 (Math TeX Gyre Regular) -U+1d788 u1D788 2.23 (Sans Bold, Sans Condensed Bold) 2.36 (Math TeX Gyre Regular) -U+1d789 u1D789 2.23 (Sans Bold, Sans Condensed Bold) 2.36 (Math TeX Gyre Regular) -U+1d78a u1D78A 2.23 (Sans Bold, Sans Condensed Bold) 2.36 (Math TeX Gyre Regular) -U+1d78b u1D78B 2.23 (Sans Bold, Sans Condensed Bold) 2.36 (Math TeX Gyre Regular) -U+1d78c u1D78C 2.23 (Sans Bold, Sans Condensed Bold) 2.36 (Math TeX Gyre Regular) -U+1d78d u1D78D 2.23 (Sans Bold, Sans Condensed Bold) 2.36 (Math TeX Gyre Regular) -U+1d78e u1D78E 2.23 (Sans Bold, Sans Condensed Bold) 2.36 (Math TeX Gyre Regular) -U+1d78f u1D78F 2.23 (Sans Bold, Sans Condensed Bold) 2.36 (Math TeX Gyre Regular) -U+1d790 u1D790 2.23 (Sans Bold Oblique, Sans Condensed Bold Oblique) 2.36 (Math TeX Gyre Regular) -U+1d791 u1D791 2.23 (Sans Bold Oblique, Sans Condensed Bold Oblique) 2.36 (Math TeX Gyre Regular) -U+1d792 u1D792 2.23 (Sans Bold Oblique, Sans Condensed Bold Oblique) 2.36 (Math TeX Gyre Regular) -U+1d793 u1D793 2.23 (Sans Bold Oblique, Sans Condensed Bold Oblique) 2.36 (Math TeX Gyre Regular) -U+1d794 u1D794 2.23 (Sans Bold Oblique, Sans Condensed Bold Oblique) 2.36 (Math TeX Gyre Regular) -U+1d795 u1D795 2.23 (Sans Bold Oblique, Sans Condensed Bold Oblique) 2.36 (Math TeX Gyre Regular) -U+1d796 u1D796 2.23 (Sans Bold Oblique, Sans Condensed Bold Oblique) 2.36 (Math TeX Gyre Regular) -U+1d797 u1D797 2.23 (Sans Bold Oblique, Sans Condensed Bold Oblique) 2.36 (Math TeX Gyre Regular) -U+1d798 u1D798 2.23 (Sans Bold Oblique, Sans Condensed Bold Oblique) 2.36 (Math TeX Gyre Regular) -U+1d799 u1D799 2.23 (Sans Bold Oblique, Sans Condensed Bold Oblique) 2.36 (Math TeX Gyre Regular) -U+1d79a u1D79A 2.23 (Sans Bold Oblique, Sans Condensed Bold Oblique) 2.36 (Math TeX Gyre Regular) -U+1d79b u1D79B 2.23 (Sans Bold Oblique, Sans Condensed Bold Oblique) 2.36 (Math TeX Gyre Regular) -U+1d79c u1D79C 2.23 (Sans Bold Oblique, Sans Condensed Bold Oblique) 2.36 (Math TeX Gyre Regular) -U+1d79d u1D79D 2.23 (Sans Bold Oblique, Sans Condensed Bold Oblique) 2.36 (Math TeX Gyre Regular) -U+1d79e u1D79E 2.23 (Sans Bold Oblique, Sans Condensed Bold Oblique) 2.36 (Math TeX Gyre Regular) -U+1d79f u1D79F 2.23 (Sans Bold Oblique, Sans Condensed Bold Oblique) 2.36 (Math TeX Gyre Regular) -U+1d7a0 u1D7A0 2.23 (Sans Bold Oblique, Sans Condensed Bold Oblique) 2.36 (Math TeX Gyre Regular) -U+1d7a1 u1D7A1 2.23 (Sans Bold Oblique, Sans Condensed Bold Oblique) 2.36 (Math TeX Gyre Regular) -U+1d7a2 u1D7A2 2.23 (Sans Bold Oblique, Sans Condensed Bold Oblique) 2.36 (Math TeX Gyre Regular) -U+1d7a3 u1D7A3 2.23 (Sans Bold Oblique, Sans Condensed Bold Oblique) 2.36 (Math TeX Gyre Regular) -U+1d7a4 u1D7A4 2.23 (Sans Bold Oblique, Sans Condensed Bold Oblique) 2.36 (Math TeX Gyre Regular) -U+1d7a5 u1D7A5 2.23 (Sans Bold Oblique, Sans Condensed Bold Oblique) 2.36 (Math TeX Gyre Regular) -U+1d7a6 u1D7A6 2.23 (Sans Bold Oblique, Sans Condensed Bold Oblique) 2.36 (Math TeX Gyre Regular) -U+1d7a7 u1D7A7 2.23 (Sans Bold Oblique, Sans Condensed Bold Oblique) 2.36 (Math TeX Gyre Regular) -U+1d7a8 u1D7A8 2.23 (Sans Bold Oblique, Sans Condensed Bold Oblique) 2.36 (Math TeX Gyre Regular) -U+1d7a9 u1D7A9 2.23 (Sans Bold Oblique, Sans Condensed Bold Oblique) 2.36 (Math TeX Gyre Regular) -U+1d7aa u1D7AA 2.23 (Sans Bold Oblique, Sans Condensed Bold Oblique) 2.36 (Math TeX Gyre Regular) -U+1d7ab u1D7AB 2.23 (Sans Bold Oblique, Sans Condensed Bold Oblique) 2.36 (Math TeX Gyre Regular) -U+1d7ac u1D7AC 2.23 (Sans Bold Oblique, Sans Condensed Bold Oblique) 2.36 (Math TeX Gyre Regular) -U+1d7ad u1D7AD 2.23 (Sans Bold Oblique, Sans Condensed Bold Oblique) 2.36 (Math TeX Gyre Regular) -U+1d7ae u1D7AE 2.23 (Sans Bold Oblique, Sans Condensed Bold Oblique) 2.36 (Math TeX Gyre Regular) -U+1d7af u1D7AF 2.23 (Sans Bold Oblique, Sans Condensed Bold Oblique) 2.36 (Math TeX Gyre Regular) -U+1d7b0 u1D7B0 2.23 (Sans Bold Oblique, Sans Condensed Bold Oblique) 2.36 (Math TeX Gyre Regular) -U+1d7b1 u1D7B1 2.23 (Sans Bold Oblique, Sans Condensed Bold Oblique) 2.36 (Math TeX Gyre Regular) -U+1d7b2 u1D7B2 2.23 (Sans Bold Oblique, Sans Condensed Bold Oblique) 2.36 (Math TeX Gyre Regular) -U+1d7b3 u1D7B3 2.23 (Sans Bold Oblique, Sans Condensed Bold Oblique) 2.36 (Math TeX Gyre Regular) -U+1d7b4 u1D7B4 2.23 (Sans Bold Oblique, Sans Condensed Bold Oblique) 2.36 (Math TeX Gyre Regular) -U+1d7b5 u1D7B5 2.23 (Sans Bold Oblique, Sans Condensed Bold Oblique) 2.36 (Math TeX Gyre Regular) -U+1d7b6 u1D7B6 2.23 (Sans Bold Oblique, Sans Condensed Bold Oblique) 2.36 (Math TeX Gyre Regular) -U+1d7b7 u1D7B7 2.23 (Sans Bold Oblique, Sans Condensed Bold Oblique) 2.36 (Math TeX Gyre Regular) -U+1d7b8 u1D7B8 2.23 (Sans Bold Oblique, Sans Condensed Bold Oblique) 2.36 (Math TeX Gyre Regular) -U+1d7b9 u1D7B9 2.23 (Sans Bold Oblique, Sans Condensed Bold Oblique) 2.36 (Math TeX Gyre Regular) -U+1d7ba u1D7BA 2.23 (Sans Bold Oblique, Sans Condensed Bold Oblique) 2.36 (Math TeX Gyre Regular) -U+1d7bb u1D7BB 2.23 (Sans Bold Oblique, Sans Condensed Bold Oblique) 2.36 (Math TeX Gyre Regular) -U+1d7bc u1D7BC 2.23 (Sans Bold Oblique, Sans Condensed Bold Oblique) 2.36 (Math TeX Gyre Regular) -U+1d7bd u1D7BD 2.23 (Sans Bold Oblique, Sans Condensed Bold Oblique) 2.36 (Math TeX Gyre Regular) -U+1d7be u1D7BE 2.23 (Sans Bold Oblique, Sans Condensed Bold Oblique) 2.36 (Math TeX Gyre Regular) -U+1d7bf u1D7BF 2.23 (Sans Bold Oblique, Sans Condensed Bold Oblique) 2.36 (Math TeX Gyre Regular) -U+1d7c0 u1D7C0 2.23 (Sans Bold Oblique, Sans Condensed Bold Oblique) 2.36 (Math TeX Gyre Regular) -U+1d7c1 u1D7C1 2.23 (Sans Bold Oblique, Sans Condensed Bold Oblique) 2.36 (Math TeX Gyre Regular) -U+1d7c2 u1D7C2 2.23 (Sans Bold Oblique, Sans Condensed Bold Oblique) 2.36 (Math TeX Gyre Regular) -U+1d7c3 u1D7C3 2.23 (Sans Bold Oblique, Sans Condensed Bold Oblique) 2.36 (Math TeX Gyre Regular) -U+1d7c4 u1D7C4 2.23 (Sans Bold Oblique, Sans Condensed Bold Oblique) 2.36 (Math TeX Gyre Regular) -U+1d7c5 u1D7C5 2.23 (Sans Bold Oblique, Sans Condensed Bold Oblique) 2.36 (Math TeX Gyre Regular) -U+1d7c6 u1D7C6 2.23 (Sans Bold Oblique, Sans Condensed Bold Oblique) 2.36 (Math TeX Gyre Regular) -U+1d7c7 u1D7C7 2.23 (Sans Bold Oblique, Sans Condensed Bold Oblique) 2.36 (Math TeX Gyre Regular) -U+1d7c8 u1D7C8 2.23 (Sans Bold Oblique, Sans Condensed Bold Oblique) 2.36 (Math TeX Gyre Regular) -U+1d7c9 u1D7C9 2.23 (Sans Bold Oblique, Sans Condensed Bold Oblique) 2.36 (Math TeX Gyre Regular) -U+1d7ca u1D7CA 2.23 (Serif Bold, Serif Condensed Bold) -U+1d7cb u1D7CB 2.23 (Serif Bold, Serif Condensed Bold) -U+1d7ce u1D7CE 2.23 (Serif Bold, Serif Condensed Bold) 2.36 (Math TeX Gyre Regular) -U+1d7cf u1D7CF 2.23 (Serif Bold, Serif Condensed Bold) 2.36 (Math TeX Gyre Regular) -U+1d7d0 u1D7D0 2.23 (Serif Bold, Serif Condensed Bold) 2.36 (Math TeX Gyre Regular) -U+1d7d1 u1D7D1 2.23 (Serif Bold, Serif Condensed Bold) 2.36 (Math TeX Gyre Regular) -U+1d7d2 u1D7D2 2.23 (Serif Bold, Serif Condensed Bold) 2.36 (Math TeX Gyre Regular) -U+1d7d3 u1D7D3 2.23 (Serif Bold, Serif Condensed Bold) 2.36 (Math TeX Gyre Regular) -U+1d7d4 u1D7D4 2.23 (Serif Bold, Serif Condensed Bold) 2.36 (Math TeX Gyre Regular) -U+1d7d5 u1D7D5 2.23 (Serif Bold, Serif Condensed Bold) 2.36 (Math TeX Gyre Regular) -U+1d7d6 u1D7D6 2.23 (Serif Bold, Serif Condensed Bold) 2.36 (Math TeX Gyre Regular) -U+1d7d7 u1D7D7 2.23 (Serif Bold, Serif Condensed Bold) 2.36 (Math TeX Gyre Regular) -U+1d7d8 u1D7D8 2.22 (Serif, Serif Condensed) 2.29 (Sans, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.30 (Sans Bold) 2.36 (Math TeX Gyre Regular) -U+1d7d9 u1D7D9 2.22 (Serif, Serif Condensed) 2.29 (Sans, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.30 (Sans Bold) 2.36 (Math TeX Gyre Regular) -U+1d7da u1D7DA 2.22 (Serif, Serif Condensed) 2.29 (Sans, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.30 (Sans Bold) 2.36 (Math TeX Gyre Regular) -U+1d7db u1D7DB 2.22 (Serif, Serif Condensed) 2.29 (Sans, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.30 (Sans Bold) 2.36 (Math TeX Gyre Regular) -U+1d7dc u1D7DC 2.22 (Serif, Serif Condensed) 2.29 (Sans, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.30 (Sans Bold) 2.36 (Math TeX Gyre Regular) -U+1d7dd u1D7DD 2.22 (Serif, Serif Condensed) 2.29 (Sans, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.30 (Sans Bold) 2.36 (Math TeX Gyre Regular) -U+1d7de u1D7DE 2.22 (Serif, Serif Condensed) 2.29 (Sans, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.30 (Sans Bold) 2.36 (Math TeX Gyre Regular) -U+1d7df u1D7DF 2.22 (Serif, Serif Condensed) 2.29 (Sans, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.30 (Sans Bold) 2.36 (Math TeX Gyre Regular) -U+1d7e0 u1D7E0 2.22 (Serif, Serif Condensed) 2.29 (Sans, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.30 (Sans Bold) 2.36 (Math TeX Gyre Regular) -U+1d7e1 u1D7E1 2.22 (Serif, Serif Condensed) 2.29 (Sans, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) 2.30 (Sans Bold) 2.36 (Math TeX Gyre Regular) -U+1d7e2 u1D7E2 2.23 (Sans, Sans Condensed) 2.36 (Math TeX Gyre Regular) -U+1d7e3 u1D7E3 2.23 (Sans, Sans Condensed) 2.36 (Math TeX Gyre Regular) -U+1d7e4 u1D7E4 2.23 (Sans, Sans Condensed) 2.36 (Math TeX Gyre Regular) -U+1d7e5 u1D7E5 2.23 (Sans, Sans Condensed) 2.36 (Math TeX Gyre Regular) -U+1d7e6 u1D7E6 2.23 (Sans, Sans Condensed) 2.36 (Math TeX Gyre Regular) -U+1d7e7 u1D7E7 2.23 (Sans, Sans Condensed) 2.36 (Math TeX Gyre Regular) -U+1d7e8 u1D7E8 2.23 (Sans, Sans Condensed) 2.36 (Math TeX Gyre Regular) -U+1d7e9 u1D7E9 2.23 (Sans, Sans Condensed) 2.36 (Math TeX Gyre Regular) -U+1d7ea u1D7EA 2.23 (Sans, Sans Condensed) 2.36 (Math TeX Gyre Regular) -U+1d7eb u1D7EB 2.23 (Sans, Sans Condensed) 2.36 (Math TeX Gyre Regular) -U+1d7ec u1D7EC 2.23 (Sans Bold, Sans Condensed Bold) 2.36 (Math TeX Gyre Regular) -U+1d7ed u1D7ED 2.23 (Sans Bold, Sans Condensed Bold) 2.36 (Math TeX Gyre Regular) -U+1d7ee u1D7EE 2.23 (Sans Bold, Sans Condensed Bold) 2.36 (Math TeX Gyre Regular) -U+1d7ef u1D7EF 2.23 (Sans Bold, Sans Condensed Bold) 2.36 (Math TeX Gyre Regular) -U+1d7f0 u1D7F0 2.23 (Sans Bold, Sans Condensed Bold) 2.36 (Math TeX Gyre Regular) -U+1d7f1 u1D7F1 2.23 (Sans Bold, Sans Condensed Bold) 2.36 (Math TeX Gyre Regular) -U+1d7f2 u1D7F2 2.23 (Sans Bold, Sans Condensed Bold) 2.36 (Math TeX Gyre Regular) -U+1d7f3 u1D7F3 2.23 (Sans Bold, Sans Condensed Bold) 2.36 (Math TeX Gyre Regular) -U+1d7f4 u1D7F4 2.23 (Sans Bold, Sans Condensed Bold) 2.36 (Math TeX Gyre Regular) -U+1d7f5 u1D7F5 2.23 (Sans Bold, Sans Condensed Bold) 2.36 (Math TeX Gyre Regular) -U+1d7f6 u1D7F6 2.23 (Sans Mono) 2.36 (Math TeX Gyre Regular) -U+1d7f7 u1D7F7 2.23 (Sans Mono) 2.36 (Math TeX Gyre Regular) -U+1d7f8 u1D7F8 2.23 (Sans Mono) 2.36 (Math TeX Gyre Regular) -U+1d7f9 u1D7F9 2.23 (Sans Mono) 2.36 (Math TeX Gyre Regular) -U+1d7fa u1D7FA 2.23 (Sans Mono) 2.36 (Math TeX Gyre Regular) -U+1d7fb u1D7FB 2.23 (Sans Mono) 2.36 (Math TeX Gyre Regular) -U+1d7fc u1D7FC 2.23 (Sans Mono) 2.36 (Math TeX Gyre Regular) -U+1d7fd u1D7FD 2.23 (Sans Mono) 2.36 (Math TeX Gyre Regular) -U+1d7fe u1D7FE 2.23 (Sans Mono) 2.36 (Math TeX Gyre Regular) -U+1d7ff u1D7FF 2.23 (Sans Mono) 2.36 (Math TeX Gyre Regular) -U+1ee00 u1EE00 2.35 (Sans, Sans Condensed) -U+1ee01 u1EE01 2.35 (Sans, Sans Condensed) -U+1ee02 u1EE02 2.35 (Sans, Sans Condensed) -U+1ee03 u1EE03 2.35 (Sans, Sans Condensed) -U+1ee05 u1EE05 2.35 (Sans, Sans Condensed) -U+1ee06 u1EE06 2.35 (Sans, Sans Condensed) -U+1ee07 u1EE07 2.35 (Sans, Sans Condensed) -U+1ee08 u1EE08 2.35 (Sans, Sans Condensed) -U+1ee09 u1EE09 2.35 (Sans, Sans Condensed) -U+1ee0a u1EE0A 2.35 (Sans, Sans Condensed) -U+1ee0b u1EE0B 2.35 (Sans, Sans Condensed) -U+1ee0c u1EE0C 2.35 (Sans, Sans Condensed) -U+1ee0d u1EE0D 2.35 (Sans, Sans Condensed) -U+1ee0e u1EE0E 2.35 (Sans, Sans Condensed) -U+1ee0f u1EE0F 2.35 (Sans, Sans Condensed) -U+1ee10 u1EE10 2.35 (Sans, Sans Condensed) -U+1ee11 u1EE11 2.35 (Sans, Sans Condensed) -U+1ee12 u1EE12 2.35 (Sans, Sans Condensed) -U+1ee13 u1EE13 2.35 (Sans, Sans Condensed) -U+1ee14 u1EE14 2.35 (Sans, Sans Condensed) -U+1ee15 u1EE15 2.35 (Sans, Sans Condensed) -U+1ee16 u1EE16 2.35 (Sans, Sans Condensed) -U+1ee17 u1EE17 2.35 (Sans, Sans Condensed) -U+1ee18 u1EE18 2.35 (Sans, Sans Condensed) -U+1ee19 u1EE19 2.35 (Sans, Sans Condensed) -U+1ee1a u1EE1A 2.35 (Sans, Sans Condensed) -U+1ee1b u1EE1B 2.35 (Sans, Sans Condensed) -U+1ee1c u1EE1C 2.35 (Sans, Sans Condensed) -U+1ee1d u1EE1D 2.35 (Sans, Sans Condensed) -U+1ee1e u1EE1E 2.35 (Sans, Sans Condensed) -U+1ee1f u1EE1F 2.35 (Sans, Sans Condensed) -U+1ee21 u1EE21 2.35 (Sans, Sans Condensed) -U+1ee22 u1EE22 2.35 (Sans, Sans Condensed) -U+1ee24 u1EE24 2.35 (Sans, Sans Condensed) -U+1ee27 u1EE27 2.35 (Sans, Sans Condensed) -U+1ee29 u1EE29 2.35 (Sans, Sans Condensed) -U+1ee2a u1EE2A 2.35 (Sans, Sans Condensed) -U+1ee2b u1EE2B 2.35 (Sans, Sans Condensed) -U+1ee2c u1EE2C 2.35 (Sans, Sans Condensed) -U+1ee2d u1EE2D 2.35 (Sans, Sans Condensed) -U+1ee2e u1EE2E 2.35 (Sans, Sans Condensed) -U+1ee2f u1EE2F 2.35 (Sans, Sans Condensed) -U+1ee30 u1EE30 2.35 (Sans, Sans Condensed) -U+1ee31 u1EE31 2.35 (Sans, Sans Condensed) -U+1ee32 u1EE32 2.35 (Sans, Sans Condensed) -U+1ee34 u1EE34 2.35 (Sans, Sans Condensed) -U+1ee35 u1EE35 2.35 (Sans, Sans Condensed) -U+1ee36 u1EE36 2.35 (Sans, Sans Condensed) -U+1ee37 u1EE37 2.35 (Sans, Sans Condensed) -U+1ee39 u1EE39 2.35 (Sans, Sans Condensed) -U+1ee3b u1EE3B 2.35 (Sans, Sans Condensed) -U+1ee61 u1EE61 2.35 (Sans, Sans Condensed) -U+1ee62 u1EE62 2.35 (Sans, Sans Condensed) -U+1ee64 u1EE64 2.35 (Sans, Sans Condensed) -U+1ee67 u1EE67 2.35 (Sans, Sans Condensed) -U+1ee68 u1EE68 2.35 (Sans, Sans Condensed) -U+1ee69 u1EE69 2.35 (Sans, Sans Condensed) -U+1ee6a u1EE6A 2.35 (Sans, Sans Condensed) -U+1ee6c u1EE6C 2.35 (Sans, Sans Condensed) -U+1ee6d u1EE6D 2.35 (Sans, Sans Condensed) -U+1ee6e u1EE6E 2.35 (Sans, Sans Condensed) -U+1ee6f u1EE6F 2.35 (Sans, Sans Condensed) -U+1ee70 u1EE70 2.35 (Sans, Sans Condensed) -U+1ee71 u1EE71 2.35 (Sans, Sans Condensed) -U+1ee72 u1EE72 2.35 (Sans, Sans Condensed) -U+1ee74 u1EE74 2.35 (Sans, Sans Condensed) -U+1ee75 u1EE75 2.35 (Sans, Sans Condensed) -U+1ee76 u1EE76 2.35 (Sans, Sans Condensed) -U+1ee77 u1EE77 2.35 (Sans, Sans Condensed) -U+1ee79 u1EE79 2.35 (Sans, Sans Condensed) -U+1ee7a u1EE7A 2.35 (Sans, Sans Condensed) -U+1ee7b u1EE7B 2.35 (Sans, Sans Condensed) -U+1ee7c u1EE7C 2.35 (Sans, Sans Condensed) -U+1ee7e u1EE7E 2.35 (Sans, Sans Condensed) -U+1f030 u1F030 2.32 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1f031 u1F031 2.32 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1f032 u1F032 2.32 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1f033 u1F033 2.32 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1f034 u1F034 2.32 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1f035 u1F035 2.32 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1f036 u1F036 2.32 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1f037 u1F037 2.32 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1f038 u1F038 2.32 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1f039 u1F039 2.32 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1f03a u1F03A 2.32 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1f03b u1F03B 2.32 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1f03c u1F03C 2.32 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1f03d u1F03D 2.32 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1f03e u1F03E 2.32 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1f03f u1F03F 2.32 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1f040 u1F040 2.32 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1f041 u1F041 2.32 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1f042 u1F042 2.32 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1f043 u1F043 2.32 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1f044 u1F044 2.32 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1f045 u1F045 2.32 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1f046 u1F046 2.32 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1f047 u1F047 2.32 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1f048 u1F048 2.32 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1f049 u1F049 2.32 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1f04a u1F04A 2.32 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1f04b u1F04B 2.32 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1f04c u1F04C 2.32 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1f04d u1F04D 2.32 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1f04e u1F04E 2.32 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1f04f u1F04F 2.32 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1f050 u1F050 2.32 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1f051 u1F051 2.32 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1f052 u1F052 2.32 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1f053 u1F053 2.32 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1f054 u1F054 2.32 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1f055 u1F055 2.32 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1f056 u1F056 2.32 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1f057 u1F057 2.32 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1f058 u1F058 2.32 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1f059 u1F059 2.32 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1f05a u1F05A 2.32 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1f05b u1F05B 2.32 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1f05c u1F05C 2.32 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1f05d u1F05D 2.32 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1f05e u1F05E 2.32 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1f05f u1F05F 2.32 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1f060 u1F060 2.32 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1f061 u1F061 2.32 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1f062 u1F062 2.32 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1f063 u1F063 2.32 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1f064 u1F064 2.32 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1f065 u1F065 2.32 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1f066 u1F066 2.32 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1f067 u1F067 2.32 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1f068 u1F068 2.32 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1f069 u1F069 2.32 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1f06a u1F06A 2.32 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1f06b u1F06B 2.32 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1f06c u1F06C 2.32 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1f06d u1F06D 2.32 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1f06e u1F06E 2.32 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1f06f u1F06F 2.32 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1f070 u1F070 2.32 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1f071 u1F071 2.32 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1f072 u1F072 2.32 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1f073 u1F073 2.32 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1f074 u1F074 2.32 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1f075 u1F075 2.32 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1f076 u1F076 2.32 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1f077 u1F077 2.32 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1f078 u1F078 2.32 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1f079 u1F079 2.32 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1f07a u1F07A 2.32 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1f07b u1F07B 2.32 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1f07c u1F07C 2.32 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1f07d u1F07D 2.32 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1f07e u1F07E 2.32 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1f07f u1F07F 2.32 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1f080 u1F080 2.32 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1f081 u1F081 2.32 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1f082 u1F082 2.32 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1f083 u1F083 2.32 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1f084 u1F084 2.32 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1f085 u1F085 2.32 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1f086 u1F086 2.32 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1f087 u1F087 2.32 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1f088 u1F088 2.32 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1f089 u1F089 2.32 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1f08a u1F08A 2.32 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1f08b u1F08B 2.32 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1f08c u1F08C 2.32 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1f08d u1F08D 2.32 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1f08e u1F08E 2.32 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1f08f u1F08F 2.32 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1f090 u1F090 2.32 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1f091 u1F091 2.32 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1f092 u1F092 2.32 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1f093 u1F093 2.32 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1f0a0 u1F0A0 2.33 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1f0a1 u1F0A1 2.33 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1f0a2 u1F0A2 2.33 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1f0a3 u1F0A3 2.33 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1f0a4 u1F0A4 2.33 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1f0a5 u1F0A5 2.33 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1f0a6 u1F0A6 2.33 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1f0a7 u1F0A7 2.33 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1f0a8 u1F0A8 2.33 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1f0a9 u1F0A9 2.33 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1f0aa u1F0AA 2.33 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1f0ab u1F0AB 2.33 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1f0ac u1F0AC 2.33 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1f0ad u1F0AD 2.33 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1f0ae u1F0AE 2.33 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1f0b1 u1F0B1 2.33 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1f0b2 u1F0B2 2.33 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1f0b3 u1F0B3 2.33 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1f0b4 u1F0B4 2.33 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1f0b5 u1F0B5 2.33 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1f0b6 u1F0B6 2.33 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1f0b7 u1F0B7 2.33 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1f0b8 u1F0B8 2.33 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1f0b9 u1F0B9 2.33 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1f0ba u1F0BA 2.33 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1f0bb u1F0BB 2.33 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1f0bc u1F0BC 2.33 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1f0bd u1F0BD 2.33 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1f0be u1F0BE 2.33 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1f0c1 u1F0C1 2.33 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1f0c2 u1F0C2 2.33 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1f0c3 u1F0C3 2.33 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1f0c4 u1F0C4 2.33 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1f0c5 u1F0C5 2.33 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1f0c6 u1F0C6 2.33 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1f0c7 u1F0C7 2.33 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1f0c8 u1F0C8 2.33 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1f0c9 u1F0C9 2.33 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1f0ca u1F0CA 2.33 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1f0cb u1F0CB 2.33 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1f0cc u1F0CC 2.33 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1f0cd u1F0CD 2.33 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1f0ce u1F0CE 2.33 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1f0cf u1F0CF 2.33 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1f0d1 u1F0D1 2.33 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1f0d2 u1F0D2 2.33 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1f0d3 u1F0D3 2.33 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1f0d4 u1F0D4 2.33 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1f0d5 u1F0D5 2.33 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1f0d6 u1F0D6 2.33 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1f0d7 u1F0D7 2.33 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1f0d8 u1F0D8 2.33 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1f0d9 u1F0D9 2.33 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1f0da u1F0DA 2.33 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1f0db u1F0DB 2.33 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1f0dc u1F0DC 2.33 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1f0dd u1F0DD 2.33 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1f0de u1F0DE 2.33 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1f0df u1F0DF 2.33 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1f311 u1F311 2.36 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1f312 u1F312 2.36 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1f313 u1F313 2.36 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1f314 u1F314 2.36 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1f315 u1F315 2.36 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1f316 u1F316 2.36 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1f317 u1F317 2.36 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1f318 u1F318 2.36 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1f42d u1F42D 2.33 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1f42e u1F42E 2.33 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1f431 u1F431 2.33 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1f435 u1F435 2.33 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1f600 u1F600 2.34 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1f601 u1F601 2.33 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1f602 u1F602 2.33 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1f603 u1F603 2.33 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1f604 u1F604 2.33 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1f605 u1F605 2.33 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1f606 u1F606 2.33 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1f607 u1F607 2.33 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1f608 u1F608 2.33 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1f609 u1F609 2.33 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1f60a u1F60A 2.33 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1f60b u1F60B 2.33 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1f60c u1F60C 2.33 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1f60d u1F60D 2.33 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1f60e u1F60E 2.33 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1f60f u1F60F 2.33 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1f610 u1F610 2.33 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1f611 u1F611 2.34 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1f612 u1F612 2.33 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1f613 u1F613 2.33 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1f614 u1F614 2.33 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1f615 u1F615 2.34 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1f616 u1F616 2.33 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1f617 u1F617 2.34 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1f618 u1F618 2.33 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1f619 u1F619 2.34 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1f61a u1F61A 2.33 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1f61b u1F61B 2.34 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1f61c u1F61C 2.33 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1f61d u1F61D 2.33 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1f61e u1F61E 2.33 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1f61f u1F61F 2.34 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1f620 u1F620 2.33 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1f621 u1F621 2.33 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1f622 u1F622 2.33 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1f623 u1F623 2.33 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1f625 u1F625 2.33 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1f626 u1F626 2.34 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1f627 u1F627 2.34 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1f628 u1F628 2.33 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1f629 u1F629 2.33 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1f62a u1F62A 2.33 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1f62b u1F62B 2.33 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1f62d u1F62D 2.33 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1f62e u1F62E 2.34 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1f62f u1F62F 2.34 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1f630 u1F630 2.33 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1f631 u1F631 2.33 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1f632 u1F632 2.33 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1f633 u1F633 2.33 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1f634 u1F634 2.34 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1f635 u1F635 2.33 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1f636 u1F636 2.33 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1f637 u1F637 2.33 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1f638 u1F638 2.33 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1f639 u1F639 2.33 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1f63a u1F63A 2.33 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1f63b u1F63B 2.33 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1f63c u1F63C 2.33 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1f63d u1F63D 2.33 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1f63e u1F63E 2.33 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1f63f u1F63F 2.33 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1f640 u1F640 2.33 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) -U+1f643 u1F643 2.36 (Sans, Sans Bold, Sans Bold Oblique, Sans Condensed, Sans Condensed Bold, Sans Condensed Bold Oblique, Sans Condensed Oblique, Sans Oblique) diff --git a/servo/components/gfx/tests/support/dejavu-fonts-ttf-2.37/ttf/DejaVuMathTeXGyre.ttf b/servo/components/gfx/tests/support/dejavu-fonts-ttf-2.37/ttf/DejaVuMathTeXGyre.ttf deleted file mode 100644 index 8a24f06400e6..000000000000 Binary files a/servo/components/gfx/tests/support/dejavu-fonts-ttf-2.37/ttf/DejaVuMathTeXGyre.ttf and /dev/null differ diff --git a/servo/components/gfx/tests/support/dejavu-fonts-ttf-2.37/ttf/DejaVuSans-Bold.ttf b/servo/components/gfx/tests/support/dejavu-fonts-ttf-2.37/ttf/DejaVuSans-Bold.ttf deleted file mode 100644 index 6d65fa7dc41a..000000000000 Binary files a/servo/components/gfx/tests/support/dejavu-fonts-ttf-2.37/ttf/DejaVuSans-Bold.ttf and /dev/null differ diff --git a/servo/components/gfx/tests/support/dejavu-fonts-ttf-2.37/ttf/DejaVuSans-BoldOblique.ttf b/servo/components/gfx/tests/support/dejavu-fonts-ttf-2.37/ttf/DejaVuSans-BoldOblique.ttf deleted file mode 100644 index 753f2d80b1f9..000000000000 Binary files a/servo/components/gfx/tests/support/dejavu-fonts-ttf-2.37/ttf/DejaVuSans-BoldOblique.ttf and /dev/null differ diff --git a/servo/components/gfx/tests/support/dejavu-fonts-ttf-2.37/ttf/DejaVuSans-ExtraLight.ttf b/servo/components/gfx/tests/support/dejavu-fonts-ttf-2.37/ttf/DejaVuSans-ExtraLight.ttf deleted file mode 100644 index b09f32d7d6a9..000000000000 Binary files a/servo/components/gfx/tests/support/dejavu-fonts-ttf-2.37/ttf/DejaVuSans-ExtraLight.ttf and /dev/null differ diff --git a/servo/components/gfx/tests/support/dejavu-fonts-ttf-2.37/ttf/DejaVuSans-Oblique.ttf b/servo/components/gfx/tests/support/dejavu-fonts-ttf-2.37/ttf/DejaVuSans-Oblique.ttf deleted file mode 100644 index 999bac771413..000000000000 Binary files a/servo/components/gfx/tests/support/dejavu-fonts-ttf-2.37/ttf/DejaVuSans-Oblique.ttf and /dev/null differ diff --git a/servo/components/gfx/tests/support/dejavu-fonts-ttf-2.37/ttf/DejaVuSans.ttf b/servo/components/gfx/tests/support/dejavu-fonts-ttf-2.37/ttf/DejaVuSans.ttf deleted file mode 100644 index e5f7eecce43b..000000000000 Binary files a/servo/components/gfx/tests/support/dejavu-fonts-ttf-2.37/ttf/DejaVuSans.ttf and /dev/null differ diff --git a/servo/components/gfx/tests/support/dejavu-fonts-ttf-2.37/ttf/DejaVuSansCondensed-Bold.ttf b/servo/components/gfx/tests/support/dejavu-fonts-ttf-2.37/ttf/DejaVuSansCondensed-Bold.ttf deleted file mode 100644 index 22987c62d930..000000000000 Binary files a/servo/components/gfx/tests/support/dejavu-fonts-ttf-2.37/ttf/DejaVuSansCondensed-Bold.ttf and /dev/null differ diff --git a/servo/components/gfx/tests/support/dejavu-fonts-ttf-2.37/ttf/DejaVuSansCondensed-BoldOblique.ttf b/servo/components/gfx/tests/support/dejavu-fonts-ttf-2.37/ttf/DejaVuSansCondensed-BoldOblique.ttf deleted file mode 100644 index f5fa0ca26f40..000000000000 Binary files a/servo/components/gfx/tests/support/dejavu-fonts-ttf-2.37/ttf/DejaVuSansCondensed-BoldOblique.ttf and /dev/null differ diff --git a/servo/components/gfx/tests/support/dejavu-fonts-ttf-2.37/ttf/DejaVuSansCondensed-Oblique.ttf b/servo/components/gfx/tests/support/dejavu-fonts-ttf-2.37/ttf/DejaVuSansCondensed-Oblique.ttf deleted file mode 100644 index 7fde90789409..000000000000 Binary files a/servo/components/gfx/tests/support/dejavu-fonts-ttf-2.37/ttf/DejaVuSansCondensed-Oblique.ttf and /dev/null differ diff --git a/servo/components/gfx/tests/support/dejavu-fonts-ttf-2.37/ttf/DejaVuSansCondensed.ttf b/servo/components/gfx/tests/support/dejavu-fonts-ttf-2.37/ttf/DejaVuSansCondensed.ttf deleted file mode 100644 index 3259bc21ae08..000000000000 Binary files a/servo/components/gfx/tests/support/dejavu-fonts-ttf-2.37/ttf/DejaVuSansCondensed.ttf and /dev/null differ diff --git a/servo/components/gfx/tests/support/dejavu-fonts-ttf-2.37/ttf/DejaVuSansMono-Bold.ttf b/servo/components/gfx/tests/support/dejavu-fonts-ttf-2.37/ttf/DejaVuSansMono-Bold.ttf deleted file mode 100644 index 8184ced8cf85..000000000000 Binary files a/servo/components/gfx/tests/support/dejavu-fonts-ttf-2.37/ttf/DejaVuSansMono-Bold.ttf and /dev/null differ diff --git a/servo/components/gfx/tests/support/dejavu-fonts-ttf-2.37/ttf/DejaVuSansMono-BoldOblique.ttf b/servo/components/gfx/tests/support/dejavu-fonts-ttf-2.37/ttf/DejaVuSansMono-BoldOblique.ttf deleted file mode 100644 index 754dca7325de..000000000000 Binary files a/servo/components/gfx/tests/support/dejavu-fonts-ttf-2.37/ttf/DejaVuSansMono-BoldOblique.ttf and /dev/null differ diff --git a/servo/components/gfx/tests/support/dejavu-fonts-ttf-2.37/ttf/DejaVuSansMono-Oblique.ttf b/servo/components/gfx/tests/support/dejavu-fonts-ttf-2.37/ttf/DejaVuSansMono-Oblique.ttf deleted file mode 100644 index 4c858d401ad7..000000000000 Binary files a/servo/components/gfx/tests/support/dejavu-fonts-ttf-2.37/ttf/DejaVuSansMono-Oblique.ttf and /dev/null differ diff --git a/servo/components/gfx/tests/support/dejavu-fonts-ttf-2.37/ttf/DejaVuSansMono.ttf b/servo/components/gfx/tests/support/dejavu-fonts-ttf-2.37/ttf/DejaVuSansMono.ttf deleted file mode 100644 index f5786022f182..000000000000 Binary files a/servo/components/gfx/tests/support/dejavu-fonts-ttf-2.37/ttf/DejaVuSansMono.ttf and /dev/null differ diff --git a/servo/components/gfx/tests/support/dejavu-fonts-ttf-2.37/ttf/DejaVuSerif-Bold.ttf b/servo/components/gfx/tests/support/dejavu-fonts-ttf-2.37/ttf/DejaVuSerif-Bold.ttf deleted file mode 100644 index 3bb755fa1eab..000000000000 Binary files a/servo/components/gfx/tests/support/dejavu-fonts-ttf-2.37/ttf/DejaVuSerif-Bold.ttf and /dev/null differ diff --git a/servo/components/gfx/tests/support/dejavu-fonts-ttf-2.37/ttf/DejaVuSerif-BoldItalic.ttf b/servo/components/gfx/tests/support/dejavu-fonts-ttf-2.37/ttf/DejaVuSerif-BoldItalic.ttf deleted file mode 100644 index a36dd4b70a83..000000000000 Binary files a/servo/components/gfx/tests/support/dejavu-fonts-ttf-2.37/ttf/DejaVuSerif-BoldItalic.ttf and /dev/null differ diff --git a/servo/components/gfx/tests/support/dejavu-fonts-ttf-2.37/ttf/DejaVuSerif-Italic.ttf b/servo/components/gfx/tests/support/dejavu-fonts-ttf-2.37/ttf/DejaVuSerif-Italic.ttf deleted file mode 100644 index 805daf2228b9..000000000000 Binary files a/servo/components/gfx/tests/support/dejavu-fonts-ttf-2.37/ttf/DejaVuSerif-Italic.ttf and /dev/null differ diff --git a/servo/components/gfx/tests/support/dejavu-fonts-ttf-2.37/ttf/DejaVuSerif.ttf b/servo/components/gfx/tests/support/dejavu-fonts-ttf-2.37/ttf/DejaVuSerif.ttf deleted file mode 100644 index 0b803d206c1a..000000000000 Binary files a/servo/components/gfx/tests/support/dejavu-fonts-ttf-2.37/ttf/DejaVuSerif.ttf and /dev/null differ diff --git a/servo/components/gfx/tests/support/dejavu-fonts-ttf-2.37/ttf/DejaVuSerifCondensed-Bold.ttf b/servo/components/gfx/tests/support/dejavu-fonts-ttf-2.37/ttf/DejaVuSerifCondensed-Bold.ttf deleted file mode 100644 index 222bf134bcab..000000000000 Binary files a/servo/components/gfx/tests/support/dejavu-fonts-ttf-2.37/ttf/DejaVuSerifCondensed-Bold.ttf and /dev/null differ diff --git a/servo/components/gfx/tests/support/dejavu-fonts-ttf-2.37/ttf/DejaVuSerifCondensed-BoldItalic.ttf b/servo/components/gfx/tests/support/dejavu-fonts-ttf-2.37/ttf/DejaVuSerifCondensed-BoldItalic.ttf deleted file mode 100644 index e44663695d50..000000000000 Binary files a/servo/components/gfx/tests/support/dejavu-fonts-ttf-2.37/ttf/DejaVuSerifCondensed-BoldItalic.ttf and /dev/null differ diff --git a/servo/components/gfx/tests/support/dejavu-fonts-ttf-2.37/ttf/DejaVuSerifCondensed-Italic.ttf b/servo/components/gfx/tests/support/dejavu-fonts-ttf-2.37/ttf/DejaVuSerifCondensed-Italic.ttf deleted file mode 100644 index c529df31bff6..000000000000 Binary files a/servo/components/gfx/tests/support/dejavu-fonts-ttf-2.37/ttf/DejaVuSerifCondensed-Italic.ttf and /dev/null differ diff --git a/servo/components/gfx/tests/support/dejavu-fonts-ttf-2.37/ttf/DejaVuSerifCondensed.ttf b/servo/components/gfx/tests/support/dejavu-fonts-ttf-2.37/ttf/DejaVuSerifCondensed.ttf deleted file mode 100644 index d3959b32286a..000000000000 Binary files a/servo/components/gfx/tests/support/dejavu-fonts-ttf-2.37/ttf/DejaVuSerifCondensed.ttf and /dev/null differ diff --git a/servo/components/gfx/tests/support/dejavu-fonts-ttf-2.37/unicover.txt b/servo/components/gfx/tests/support/dejavu-fonts-ttf-2.37/unicover.txt deleted file mode 100644 index fc05f99b430d..000000000000 --- a/servo/components/gfx/tests/support/dejavu-fonts-ttf-2.37/unicover.txt +++ /dev/null @@ -1,279 +0,0 @@ -This is the Unicode coverage file for DejaVu fonts -($Id$) - -Control and similar characters are discounted from totals. - - Sans Serif Sans Mono -U+0000 Basic Latin 100% (95/95) 100% (95/95) 100% (95/95) -U+0080 Latin-1 Supplement 100% (96/96) 100% (96/96) 100% (96/96) -U+0100 Latin Extended-A 100% (128/128) 100% (128/128) 100% (128/128) -U+0180 Latin Extended-B 100% (208/208) 100% (208/208) 86% (180/208) -U+0250 IPA Extensions 100% (96/96) 100% (96/96) 100% (96/96) -U+02b0 Spacing Modifier Letters 78% (63/80) 73% (59/80) 62% (50/80) -U+0300 Combining Diacritical Marks 83% (93/112) 61% (69/112) 59% (67/112) -U+0370 Greek and Coptic 100% (135/135) 89% (121/135) 85% (116/135) -U+0400 Cyrillic 100% (256/256) 79% (204/256) 70% (180/256) -U+0500 Cyrillic Supplement 79% (38/48) 20% (10/48) 12% (6/48) -U+0530 Armenian 96% (86/89) 96% (86/89) 96% (86/89) -U+0590 Hebrew 62% (54/87) (0/87) (0/87) -U+0600 Arabic 64% (165/255) (0/255) 38% (99/255) -U+0700 Syriac (0/77) (0/77) (0/77) -U+0750 Arabic Supplement (0/48) (0/48) (0/48) -U+0780 Thaana (0/50) (0/50) (0/50) -U+07c0 NKo 91% (54/59) (0/59) (0/59) -U+0800 Samaritan (0/61) (0/61) (0/61) -U+0840 Mandaic (0/29) (0/29) (0/29) -U+08a0 Arabic Extended-A (0/73) (0/73) (0/73) -U+0900 Devanagari (0/128) (0/128) (0/128) -U+0980 Bengali (0/93) (0/93) (0/93) -U+0a00 Gurmukhi (0/79) (0/79) (0/79) -U+0a80 Gujarati (0/85) (0/85) (0/85) -U+0b00 Oriya (0/90) (0/90) (0/90) -U+0b80 Tamil (0/72) (0/72) (0/72) -U+0c00 Telugu (0/96) (0/96) (0/96) -U+0c80 Kannada (0/88) (0/88) (0/88) -U+0d00 Malayalam (0/114) (0/114) (0/114) -U+0d80 Sinhala (0/90) (0/90) (0/90) -U+0e00 Thai 1% (1/87) 1% (1/87) 1% (1/87) -U+0e80 Lao 97% (65/67) (0/67) 68% (46/67) -U+0f00 Tibetan (0/211) (0/211) (0/211) -U+1000 Myanmar (0/160) (0/160) (0/160) -U+10a0 Georgian 94% (83/88) 94% (83/88) 51% (45/88) -U+1100 Hangul Jamo (0/256) (0/256) (0/256) -U+1200 Ethiopic (0/358) (0/358) (0/358) -U+1380 Ethiopic Supplement (0/26) (0/26) (0/26) -U+13a0 Cherokee (0/92) (0/92) (0/92) -U+1400 Unified Canadian Aboriginal Syllabics 63% (404/640) (0/640) (0/640) -U+1680 Ogham 100% (29/29) (0/29) (0/29) -U+16a0 Runic (0/89) (0/89) (0/89) -U+1700 Tagalog (0/20) (0/20) (0/20) -U+1720 Hanunoo (0/23) (0/23) (0/23) -U+1740 Buhid (0/20) (0/20) (0/20) -U+1760 Tagbanwa (0/18) (0/18) (0/18) -U+1780 Khmer (0/114) (0/114) (0/114) -U+1800 Mongolian (0/156) (0/156) (0/156) -U+18b0 Unified Canadian Aboriginal Syllabics Extended (0/70) (0/70) (0/70) -U+1900 Limbu (0/68) (0/68) (0/68) -U+1950 Tai Le (0/35) (0/35) (0/35) -U+1980 New Tai Lue (0/83) (0/83) (0/83) -U+19e0 Khmer Symbols (0/32) (0/32) (0/32) -U+1a00 Buginese (0/30) (0/30) (0/30) -U+1a20 Tai Tham (0/127) (0/127) (0/127) -U+1ab0 Combining Diacritical Marks Extended (0/15) (0/15) (0/15) -U+1b00 Balinese (0/121) (0/121) (0/121) -U+1b80 Sundanese (0/64) (0/64) (0/64) -U+1bc0 Batak (0/56) (0/56) (0/56) -U+1c00 Lepcha (0/74) (0/74) (0/74) -U+1c50 Ol Chiki (0/48) (0/48) (0/48) -U+1c80 Cyrillic Extended-C (0/9) (0/9) (0/9) -U+1cc0 Sundanese Supplement (0/8) (0/8) (0/8) -U+1cd0 Vedic Extensions (0/41) (0/41) (0/41) -U+1d00 Phonetic Extensions 82% (106/128) 89% (115/128) 48% (62/128) -U+1d80 Phonetic Extensions Supplement 59% (38/64) 59% (38/64) 57% (37/64) -U+1dc0 Combining Diacritical Marks Supplement 10% (6/59) 10% (6/59) (0/59) -U+1e00 Latin Extended Additional 98% (252/256) 98% (252/256) 71% (182/256) -U+1f00 Greek Extended 100% (233/233) 100% (233/233) 100% (233/233) -U+2000 General Punctuation 96% (107/111) 78% (87/111) 48% (54/111) -U+2070 Superscripts and Subscripts 100% (42/42) 100% (42/42) 100% (42/42) -U+20a0 Currency Symbols 83% (26/31) 32% (10/31) 83% (26/31) -U+20d0 Combining Diacritical Marks for Symbols 21% (7/33) (0/33) (0/33) -U+2100 Letterlike Symbols 93% (75/80) 42% (34/80) 22% (18/80) -U+2150 Number Forms 91% (55/60) 91% (55/60) 26% (16/60) -U+2190 Arrows 100% (112/112) 100% (112/112) 100% (112/112) -U+2200 Mathematical Operators 100% (256/256) 39% (101/256) 69% (178/256) -U+2300 Miscellaneous Technical 25% (65/255) 14% (36/255) 53% (136/255) -U+2400 Control Pictures 5% (2/39) 2% (1/39) 2% (1/39) -U+2440 Optical Character Recognition (0/11) (0/11) (0/11) -U+2460 Enclosed Alphanumerics 6% (10/160) (0/160) (0/160) -U+2500 Box Drawing 100% (128/128) 100% (128/128) 100% (128/128) -U+2580 Block Elements 100% (32/32) 100% (32/32) 100% (32/32) -U+25a0 Geometric Shapes 100% (96/96) 100% (96/96) 100% (96/96) -U+2600 Miscellaneous Symbols 73% (189/256) 11% (30/256) 58% (149/256) -U+2700 Dingbats 90% (174/192) 0% (1/192) 75% (144/192) -U+27c0 Miscellaneous Mathematical Symbols-A 18% (9/48) 10% (5/48) 22% (11/48) -U+27f0 Supplemental Arrows-A 100% (16/16) 100% (16/16) 18% (3/16) -U+2800 Braille Patterns 100% (256/256) 100% (256/256) (0/256) -U+2900 Supplemental Arrows-B 4% (6/128) 100% (128/128) (0/128) -U+2980 Miscellaneous Mathematical Symbols-B 10% (13/128) 0% (1/128) 5% (7/128) -U+2a00 Supplemental Mathematical Operators 28% (74/256) 2% (6/256) 1% (4/256) -U+2b00 Miscellaneous Symbols and Arrows 16% (35/206) 13% (27/206) 8% (18/206) -U+2c00 Glagolitic (0/94) (0/94) (0/94) -U+2c60 Latin Extended-C 96% (31/32) 84% (27/32) 43% (14/32) -U+2c80 Coptic (0/123) (0/123) (0/123) -U+2d00 Georgian Supplement 95% (38/40) 95% (38/40) (0/40) -U+2d30 Tifinagh 93% (55/59) (0/59) (0/59) -U+2d80 Ethiopic Extended (0/79) (0/79) (0/79) -U+2de0 Cyrillic Extended-A (0/32) (0/32) (0/32) -U+2e00 Supplemental Punctuation 10% (7/69) 10% (7/69) 10% (7/69) -U+2e80 CJK Radicals Supplement (0/115) (0/115) (0/115) -U+2f00 Kangxi Radicals (0/214) (0/214) (0/214) -U+2ff0 Ideographic Description Characters (0/12) (0/12) (0/12) -U+3000 CJK Symbols and Punctuation (0/64) (0/64) (0/64) -U+3040 Hiragana (0/93) (0/93) (0/93) -U+30a0 Katakana (0/96) (0/96) (0/96) -U+3100 Bopomofo (0/41) (0/41) (0/41) -U+3130 Hangul Compatibility Jamo (0/94) (0/94) (0/94) -U+3190 Kanbun (0/16) (0/16) (0/16) -U+31a0 Bopomofo Extended (0/27) (0/27) (0/27) -U+31c0 CJK Strokes (0/36) (0/36) (0/36) -U+31f0 Katakana Phonetic Extensions (0/16) (0/16) (0/16) -U+3200 Enclosed CJK Letters and Months (0/254) (0/254) (0/254) -U+3300 CJK Compatibility (0/256) (0/256) (0/256) -U+3400 CJK Unified Ideographs Extension A (0/0) (0/0) (0/0) -U+4dc0 Yijing Hexagram Symbols 100% (64/64) (0/64) (0/64) -U+4e00 CJK Unified Ideographs (0/0) (0/0) (0/0) -U+a000 Yi Syllables (0/1165) (0/1165) (0/1165) -U+a490 Yi Radicals (0/55) (0/55) (0/55) -U+a4d0 Lisu 100% (48/48) (0/48) (0/48) -U+a500 Vai (0/300) (0/300) (0/300) -U+a640 Cyrillic Extended-B 34% (33/96) 12% (12/96) (0/96) -U+a6a0 Bamum (0/88) (0/88) (0/88) -U+a700 Modifier Tone Letters 62% (20/32) 62% (20/32) 62% (20/32) -U+a720 Latin Extended-D 48% (77/160) 37% (60/160) 10% (17/160) -U+a800 Syloti Nagri (0/44) (0/44) (0/44) -U+a830 Common Indic Number Forms (0/10) (0/10) (0/10) -U+a840 Phags-pa (0/56) (0/56) (0/56) -U+a880 Saurashtra (0/82) (0/82) (0/82) -U+a8e0 Devanagari Extended (0/30) (0/30) (0/30) -U+a900 Kayah Li (0/48) (0/48) (0/48) -U+a930 Rejang (0/37) (0/37) (0/37) -U+a960 Hangul Jamo Extended-A (0/29) (0/29) (0/29) -U+a980 Javanese (0/91) (0/91) (0/91) -U+a9e0 Myanmar Extended-B (0/31) (0/31) (0/31) -U+aa00 Cham (0/83) (0/83) (0/83) -U+aa60 Myanmar Extended-A (0/32) (0/32) (0/32) -U+aa80 Tai Viet (0/72) (0/72) (0/72) -U+aae0 Meetei Mayek Extensions (0/23) (0/23) (0/23) -U+ab00 Ethiopic Extended-A (0/32) (0/32) (0/32) -U+ab30 Latin Extended-E (0/54) (0/54) (0/54) -U+ab70 Cherokee Supplement (0/80) (0/80) (0/80) -U+abc0 Meetei Mayek (0/56) (0/56) (0/56) -U+ac00 Hangul Syllables (0/0) (0/0) (0/0) -U+d7b0 Hangul Jamo Extended-B (0/72) (0/72) (0/72) -U+d800 High Surrogates (0/0) (0/0) (0/0) -U+db80 High Private Use Surrogates (0/0) (0/0) (0/0) -U+dc00 Low Surrogates (0/0) (0/0) (0/0) -U+e000 Private Use Area (0/0) (0/0) (0/0) -U+f900 CJK Compatibility Ideographs (0/472) (0/472) (0/472) -U+fb00 Alphabetic Presentation Forms 100% (58/58) 12% (7/58) 3% (2/58) -U+fb50 Arabic Presentation Forms-A 17% (108/611) (0/611) 11% (72/611) -U+fe00 Variation Selectors 100% (16/16) 100% (16/16) (0/16) -U+fe10 Vertical Forms (0/10) (0/10) (0/10) -U+fe20 Combining Half Marks 25% (4/16) (0/16) (0/16) -U+fe30 CJK Compatibility Forms (0/32) (0/32) (0/32) -U+fe50 Small Form Variants (0/26) (0/26) (0/26) -U+fe70 Arabic Presentation Forms-B 100% (141/141) (0/141) 100% (141/141) -U+ff00 Halfwidth and Fullwidth Forms (0/225) (0/225) (0/225) -U+fff0 Specials 100% (5/5) 100% (5/5) 100% (5/5) -U+10000 Linear B Syllabary (0/88) (0/88) (0/88) -U+10080 Linear B Ideograms (0/123) (0/123) (0/123) -U+10100 Aegean Numbers (0/57) (0/57) (0/57) -U+10140 Ancient Greek Numbers (0/79) (0/79) (0/79) -U+10190 Ancient Symbols (0/13) (0/13) (0/13) -U+101d0 Phaistos Disc (0/46) (0/46) (0/46) -U+10280 Lycian (0/29) (0/29) (0/29) -U+102a0 Carian (0/49) (0/49) (0/49) -U+102e0 Coptic Epact Numbers (0/28) (0/28) (0/28) -U+10300 Old Italic 97% (35/36) (0/36) (0/36) -U+10330 Gothic (0/27) (0/27) (0/27) -U+10350 Old Permic (0/43) (0/43) (0/43) -U+10380 Ugaritic (0/31) (0/31) (0/31) -U+103a0 Old Persian (0/50) (0/50) (0/50) -U+10400 Deseret (0/80) (0/80) (0/80) -U+10450 Shavian (0/48) (0/48) (0/48) -U+10480 Osmanya (0/40) (0/40) (0/40) -U+104b0 Osage (0/72) (0/72) (0/72) -U+10500 Elbasan (0/40) (0/40) (0/40) -U+10530 Caucasian Albanian (0/53) (0/53) (0/53) -U+10600 Linear A (0/341) (0/341) (0/341) -U+10800 Cypriot Syllabary (0/55) (0/55) (0/55) -U+10840 Imperial Aramaic (0/31) (0/31) (0/31) -U+10860 Palmyrene (0/32) (0/32) (0/32) -U+10880 Nabataean (0/40) (0/40) (0/40) -U+108e0 Hatran (0/26) (0/26) (0/26) -U+10900 Phoenician (0/29) (0/29) (0/29) -U+10920 Lydian (0/27) (0/27) (0/27) -U+10980 Meroitic Hieroglyphs (0/32) (0/32) (0/32) -U+109a0 Meroitic Cursive (0/90) (0/90) (0/90) -U+10a00 Kharoshthi (0/65) (0/65) (0/65) -U+10a60 Old South Arabian (0/32) (0/32) (0/32) -U+10a80 Old North Arabian (0/32) (0/32) (0/32) -U+10ac0 Manichaean (0/51) (0/51) (0/51) -U+10b00 Avestan (0/61) (0/61) (0/61) -U+10b40 Inscriptional Parthian (0/30) (0/30) (0/30) -U+10b60 Inscriptional Pahlavi (0/27) (0/27) (0/27) -U+10b80 Psalter Pahlavi (0/29) (0/29) (0/29) -U+10c00 Old Turkic (0/73) (0/73) (0/73) -U+10c80 Old Hungarian (0/108) (0/108) (0/108) -U+10e60 Rumi Numeral Symbols (0/31) (0/31) (0/31) -U+11000 Brahmi (0/109) (0/109) (0/109) -U+11080 Kaithi (0/66) (0/66) (0/66) -U+110d0 Sora Sompeng (0/35) (0/35) (0/35) -U+11100 Chakma (0/67) (0/67) (0/67) -U+11150 Mahajani (0/39) (0/39) (0/39) -U+11180 Sharada (0/94) (0/94) (0/94) -U+111e0 Sinhala Archaic Numbers (0/20) (0/20) (0/20) -U+11200 Khojki (0/62) (0/62) (0/62) -U+11280 Multani (0/38) (0/38) (0/38) -U+112b0 Khudawadi (0/69) (0/69) (0/69) -U+11300 Grantha (0/85) (0/85) (0/85) -U+11400 Newa (0/92) (0/92) (0/92) -U+11480 Tirhuta (0/82) (0/82) (0/82) -U+11580 Siddham (0/92) (0/92) (0/92) -U+11600 Modi (0/79) (0/79) (0/79) -U+11660 Mongolian Supplement (0/13) (0/13) (0/13) -U+11680 Takri (0/66) (0/66) (0/66) -U+11700 Ahom (0/57) (0/57) (0/57) -U+118a0 Warang Citi (0/84) (0/84) (0/84) -U+11ac0 Pau Cin Hau (0/57) (0/57) (0/57) -U+11c00 Bhaiksuki (0/97) (0/97) (0/97) -U+11c70 Marchen (0/68) (0/68) (0/68) -U+12000 Cuneiform (0/922) (0/922) (0/922) -U+12400 Cuneiform Numbers and Punctuation (0/116) (0/116) (0/116) -U+12480 Early Dynastic Cuneiform (0/196) (0/196) (0/196) -U+13000 Egyptian Hieroglyphs (0/1071) (0/1071) (0/1071) -U+14400 Anatolian Hieroglyphs (0/583) (0/583) (0/583) -U+16800 Bamum Supplement (0/569) (0/569) (0/569) -U+16a40 Mro (0/43) (0/43) (0/43) -U+16ad0 Bassa Vah (0/36) (0/36) (0/36) -U+16b00 Pahawh Hmong (0/127) (0/127) (0/127) -U+16f00 Miao (0/133) (0/133) (0/133) -U+16fe0 Ideographic Symbols and Punctuation (0/1) (0/1) (0/1) -U+17000 Tangut (0/0) (0/0) (0/0) -U+18800 Tangut Components (0/755) (0/755) (0/755) -U+1b000 Kana Supplement (0/2) (0/2) (0/2) -U+1bc00 Duployan (0/143) (0/143) (0/143) -U+1bca0 Shorthand Format Controls (0/4) (0/4) (0/4) -U+1d000 Byzantine Musical Symbols (0/246) (0/246) (0/246) -U+1d100 Musical Symbols (0/231) (0/231) (0/231) -U+1d200 Ancient Greek Musical Notation (0/70) (0/70) (0/70) -U+1d300 Tai Xuan Jing Symbols 100% (87/87) (0/87) (0/87) -U+1d360 Counting Rod Numerals (0/18) (0/18) (0/18) -U+1d400 Mathematical Alphanumeric Symbols 11% (117/996) 10% (108/996) 6% (63/996) -U+1d800 Sutton SignWriting (0/672) (0/672) (0/672) -U+1e000 Glagolitic Supplement (0/38) (0/38) (0/38) -U+1e800 Mende Kikakui (0/213) (0/213) (0/213) -U+1e900 Adlam (0/87) (0/87) (0/87) -U+1ee00 Arabic Mathematical Alphabetic Symbols 51% (74/143) (0/143) (0/143) -U+1f000 Mahjong Tiles (0/44) (0/44) (0/44) -U+1f030 Domino Tiles 100% (100/100) (0/100) (0/100) -U+1f0a0 Playing Cards 71% (59/82) (0/82) (0/82) -U+1f100 Enclosed Alphanumeric Supplement (0/191) (0/191) (0/191) -U+1f200 Enclosed Ideographic Supplement (0/58) (0/58) (0/58) -U+1f300 Miscellaneous Symbols and Pictographs 1% (12/768) (0/768) (0/768) -U+1f600 Emoticons 80% (64/80) (0/80) (0/80) -U+1f650 Ornamental Dingbats (0/48) (0/48) (0/48) -U+1f680 Transport and Map Symbols (0/103) (0/103) (0/103) -U+1f700 Alchemical Symbols (0/116) (0/116) (0/116) -U+1f780 Geometric Shapes Extended (0/85) (0/85) (0/85) -U+1f800 Supplemental Arrows-C (0/148) (0/148) (0/148) -U+1f900 Supplemental Symbols and Pictographs (0/82) (0/82) (0/82) -U+20000 CJK Unified Ideographs Extension B (0/0) (0/0) (0/0) -U+2a700 CJK Unified Ideographs Extension C (0/0) (0/0) (0/0) -U+2b740 CJK Unified Ideographs Extension D (0/0) (0/0) (0/0) -U+2b820 CJK Unified Ideographs Extension E (0/0) (0/0) (0/0) -U+2f800 CJK Compatibility Ideographs Supplement (0/542) (0/542) (0/542) -U+e0000 Tags (0/98) (0/98) (0/98) -U+e0100 Variation Selectors Supplement (0/240) (0/240) (0/240) -U+f0000 Supplementary Private Use Area-A (0/0) (0/0) (0/0) -U+100000 Supplementary Private Use Area-B (0/0) (0/0) (0/0) diff --git a/servo/components/gfx/tests/text_util.rs b/servo/components/gfx/tests/text_util.rs deleted file mode 100644 index 7729a6f78a7f..000000000000 --- a/servo/components/gfx/tests/text_util.rs +++ /dev/null @@ -1,162 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -extern crate gfx; - -use gfx::text::util::{CompressionMode, transform_text}; - -#[test] -fn test_transform_compress_none() { - let test_strs = [ - " foo bar", - "foo bar ", - "foo\n bar", - "foo \nbar", - " foo bar \nbaz", - "foo bar baz", - "foobarbaz\n\n", - ]; - - let mode = CompressionMode::CompressNone; - for &test in test_strs.iter() { - let mut trimmed_str = String::new(); - transform_text(test, mode, true, &mut trimmed_str); - assert_eq!(trimmed_str, test) - } -} - -#[test] -fn test_transform_discard_newline() { - let test_strs = [ - (" foo bar", - " foo bar"), - - ("foo bar ", - "foo bar "), - - ("foo\n bar", - "foo bar"), - - ("foo \nbar", - "foo bar"), - - (" foo bar \nbaz", - " foo bar baz"), - - ("foo bar baz", - "foo bar baz"), - - ("foobarbaz\n\n", - "foobarbaz"), - ]; - - let mode = CompressionMode::DiscardNewline; - for &(test, oracle) in test_strs.iter() { - let mut trimmed_str = String::new(); - transform_text(test, mode, true, &mut trimmed_str); - assert_eq!(trimmed_str, oracle) - } -} - -#[test] -fn test_transform_compress_whitespace() { - let test_strs = [ - (" foo bar", - "foo bar"), - - ("foo bar ", - "foo bar "), - - ("foo\n bar", - "foo\n bar"), - - ("foo \nbar", - "foo \nbar"), - - (" foo bar \nbaz", - "foo bar \nbaz"), - - ("foo bar baz", - "foo bar baz"), - - ("foobarbaz\n\n", - "foobarbaz\n\n"), - ]; - - let mode = CompressionMode::CompressWhitespace; - for &(test, oracle) in test_strs.iter() { - let mut trimmed_str = String::new(); - transform_text(test, mode, true, &mut trimmed_str); - assert_eq!(&*trimmed_str, oracle) - } -} - -#[test] -fn test_transform_compress_whitespace_newline() { - let test_strs = vec![ - (" foo bar", - "foo bar"), - - ("foo bar ", - "foo bar "), - - ("foo\n bar", - "foo bar"), - - ("foo \nbar", - "foo bar"), - - (" foo bar \nbaz", - "foo bar baz"), - - ("foo bar baz", - "foo bar baz"), - - ("foobarbaz\n\n", - "foobarbaz "), - ]; - - let mode = CompressionMode::CompressWhitespaceNewline; - for &(test, oracle) in test_strs.iter() { - let mut trimmed_str = String::new(); - transform_text(test, mode, true, &mut trimmed_str); - assert_eq!(&*trimmed_str, oracle) - } -} - -#[test] -fn test_transform_compress_whitespace_newline_no_incoming() { - let test_strs = [ - (" foo bar", - " foo bar"), - - ("\nfoo bar", - " foo bar"), - - ("foo bar ", - "foo bar "), - - ("foo\n bar", - "foo bar"), - - ("foo \nbar", - "foo bar"), - - (" foo bar \nbaz", - " foo bar baz"), - - ("foo bar baz", - "foo bar baz"), - - ("foobarbaz\n\n", - "foobarbaz "), - ]; - - let mode = CompressionMode::CompressWhitespaceNewline; - for &(test, oracle) in test_strs.iter() { - let mut trimmed_str = String::new(); - transform_text(test, mode, false, &mut trimmed_str); - assert_eq!(trimmed_str, oracle) - } -} diff --git a/servo/components/gfx/text/glyph.rs b/servo/components/gfx/text/glyph.rs deleted file mode 100644 index 0c3386aca7dd..000000000000 --- a/servo/components/gfx/text/glyph.rs +++ /dev/null @@ -1,765 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -use app_units::Au; -use euclid::Point2D; -use range::{self, EachIndex, Range, RangeIndex}; -#[cfg(all(feature = "unstable", any(target_feature = "sse2", target_feature = "neon")))] -use simd::u32x4; -use std::{fmt, mem, u16}; -use std::cmp::{Ordering, PartialOrd}; -use std::vec::Vec; - -pub use gfx_traits::ByteIndex; - -/// GlyphEntry is a port of Gecko's CompressedGlyph scheme for storing glyph data compactly. -/// -/// In the common case (reasonable glyph advances, no offsets from the font em-box, and one glyph -/// per character), we pack glyph advance, glyph id, and some flags into a single u32. -/// -/// In the uncommon case (multiple glyphs per unicode character, large glyph index/advance, or -/// glyph offsets), we pack the glyph count into GlyphEntry, and store the other glyph information -/// in DetailedGlyphStore. -#[derive(Clone, Copy, Debug, Deserialize, PartialEq, Serialize)] -pub struct GlyphEntry { - value: u32, -} - -impl GlyphEntry { - fn new(value: u32) -> GlyphEntry { - GlyphEntry { - value: value, - } - } - - fn initial() -> GlyphEntry { - GlyphEntry::new(0) - } - - // Creates a GlyphEntry for the common case - fn simple(id: GlyphId, advance: Au) -> GlyphEntry { - assert!(is_simple_glyph_id(id)); - assert!(is_simple_advance(advance)); - - let id_mask = id as u32; - let Au(advance) = advance; - let advance_mask = (advance as u32) << GLYPH_ADVANCE_SHIFT; - - GlyphEntry::new(id_mask | advance_mask | FLAG_IS_SIMPLE_GLYPH) - } - - // Create a GlyphEntry for uncommon case; should be accompanied by - // initialization of the actual DetailedGlyph data in DetailedGlyphStore - fn complex(starts_cluster: bool, starts_ligature: bool, glyph_count: usize) -> GlyphEntry { - assert!(glyph_count <= u16::MAX as usize); - - debug!("creating complex glyph entry: starts_cluster={}, starts_ligature={}, \ - glyph_count={}", - starts_cluster, - starts_ligature, - glyph_count); - - GlyphEntry::new(glyph_count as u32) - } - - fn is_initial(&self) -> bool { - *self == GlyphEntry::initial() - } -} - -/// The id of a particular glyph within a font -pub type GlyphId = u32; - -// TODO: make this more type-safe. - -const FLAG_CHAR_IS_SPACE: u32 = 0x40000000; -#[cfg(feature = "unstable")] -#[cfg(any(target_feature = "sse2", target_feature = "neon"))] -const FLAG_CHAR_IS_SPACE_SHIFT: u32 = 30; -const FLAG_IS_SIMPLE_GLYPH: u32 = 0x80000000; - -// glyph advance; in Au's. -const GLYPH_ADVANCE_MASK: u32 = 0x3FFF0000; -const GLYPH_ADVANCE_SHIFT: u32 = 16; -const GLYPH_ID_MASK: u32 = 0x0000FFFF; - -// Non-simple glyphs (more than one glyph per char; missing glyph, -// newline, tab, large advance, or nonzero x/y offsets) may have one -// or more detailed glyphs associated with them. They are stored in a -// side array so that there is a 1:1 mapping of GlyphEntry to -// unicode char. - -// The number of detailed glyphs for this char. -const GLYPH_COUNT_MASK: u32 = 0x0000FFFF; - -fn is_simple_glyph_id(id: GlyphId) -> bool { - ((id as u32) & GLYPH_ID_MASK) == id -} - -fn is_simple_advance(advance: Au) -> bool { - advance >= Au(0) && { - let unsigned_au = advance.0 as u32; - (unsigned_au & (GLYPH_ADVANCE_MASK >> GLYPH_ADVANCE_SHIFT)) == unsigned_au - } -} - -pub type DetailedGlyphCount = u16; - -// Getters and setters for GlyphEntry. Setter methods are functional, -// because GlyphEntry is immutable and only a u32 in size. -impl GlyphEntry { - #[inline(always)] - fn advance(&self) -> Au { - Au::new(((self.value & GLYPH_ADVANCE_MASK) >> GLYPH_ADVANCE_SHIFT) as i32) - } - - #[inline] - fn id(&self) -> GlyphId { - self.value & GLYPH_ID_MASK - } - - /// True if original char was normal (U+0020) space. Other chars may - /// map to space glyph, but this does not account for them. - fn char_is_space(&self) -> bool { - self.has_flag(FLAG_CHAR_IS_SPACE) - } - - #[inline(always)] - fn set_char_is_space(&mut self) { - self.value |= FLAG_CHAR_IS_SPACE; - } - - fn glyph_count(&self) -> u16 { - assert!(!self.is_simple()); - (self.value & GLYPH_COUNT_MASK) as u16 - } - - #[inline(always)] - fn is_simple(&self) -> bool { - self.has_flag(FLAG_IS_SIMPLE_GLYPH) - } - - #[inline(always)] - fn has_flag(&self, flag: u32) -> bool { - (self.value & flag) != 0 - } -} - -// Stores data for a detailed glyph, in the case that several glyphs -// correspond to one character, or the glyph's data couldn't be packed. -#[derive(Clone, Copy, Debug, Deserialize, Serialize)] -struct DetailedGlyph { - id: GlyphId, - // glyph's advance, in the text's direction (LTR or RTL) - advance: Au, - // glyph's offset from the font's em-box (from top-left) - offset: Point2D, -} - -impl DetailedGlyph { - fn new(id: GlyphId, advance: Au, offset: Point2D) -> DetailedGlyph { - DetailedGlyph { - id: id, - advance: advance, - offset: offset, - } - } -} - -#[derive(Clone, Copy, Debug, Deserialize, Eq, PartialEq, Serialize)] -struct DetailedGlyphRecord { - // source string offset/GlyphEntry offset in the TextRun - entry_offset: ByteIndex, - // offset into the detailed glyphs buffer - detail_offset: usize, -} - -impl PartialOrd for DetailedGlyphRecord { - fn partial_cmp(&self, other: &DetailedGlyphRecord) -> Option { - self.entry_offset.partial_cmp(&other.entry_offset) - } -} - -impl Ord for DetailedGlyphRecord { - fn cmp(&self, other: &DetailedGlyphRecord) -> Ordering { - self.entry_offset.cmp(&other.entry_offset) - } -} - -// Manages the lookup table for detailed glyphs. Sorting is deferred -// until a lookup is actually performed; this matches the expected -// usage pattern of setting/appending all the detailed glyphs, and -// then querying without setting. -#[derive(Clone, Deserialize, Serialize)] -struct DetailedGlyphStore { - // TODO(pcwalton): Allocation of this buffer is expensive. Consider a small-vector - // optimization. - detail_buffer: Vec, - // TODO(pcwalton): Allocation of this buffer is expensive. Consider a small-vector - // optimization. - detail_lookup: Vec, - lookup_is_sorted: bool, -} - -impl<'a> DetailedGlyphStore { - fn new() -> DetailedGlyphStore { - DetailedGlyphStore { - detail_buffer: vec!(), // TODO: default size? - detail_lookup: vec!(), - lookup_is_sorted: false, - } - } - - fn add_detailed_glyphs_for_entry(&mut self, entry_offset: ByteIndex, glyphs: &[DetailedGlyph]) { - let entry = DetailedGlyphRecord { - entry_offset: entry_offset, - detail_offset: self.detail_buffer.len(), - }; - - debug!("Adding entry[off={:?}] for detailed glyphs: {:?}", entry_offset, glyphs); - - /* TODO: don't actually assert this until asserts are compiled - in/out based on severity, debug/release, etc. This assertion - would wreck the complexity of the lookup. - - See Rust Issue #3647, #2228, #3627 for related information. - - do self.detail_lookup.borrow |arr| { - assert !arr.contains(entry) - } - */ - - self.detail_lookup.push(entry); - self.detail_buffer.extend_from_slice(glyphs); - self.lookup_is_sorted = false; - } - - fn detailed_glyphs_for_entry(&'a self, entry_offset: ByteIndex, count: u16) - -> &'a [DetailedGlyph] { - debug!("Requesting detailed glyphs[n={}] for entry[off={:?}]", count, entry_offset); - - // FIXME: Is this right? --pcwalton - // TODO: should fix this somewhere else - if count == 0 { - return &self.detail_buffer[0..0]; - } - - assert!((count as usize) <= self.detail_buffer.len()); - assert!(self.lookup_is_sorted); - - let key = DetailedGlyphRecord { - entry_offset: entry_offset, - detail_offset: 0, // unused - }; - - let i = self.detail_lookup.binary_search(&key) - .expect("Invalid index not found in detailed glyph lookup table!"); - let main_detail_offset = self.detail_lookup[i].detail_offset; - assert!(main_detail_offset + (count as usize) <= self.detail_buffer.len()); - // return a slice into the buffer - &self.detail_buffer[main_detail_offset .. main_detail_offset + count as usize] - } - - fn detailed_glyph_with_index(&'a self, - entry_offset: ByteIndex, - detail_offset: u16) - -> &'a DetailedGlyph { - assert!((detail_offset as usize) <= self.detail_buffer.len()); - assert!(self.lookup_is_sorted); - - let key = DetailedGlyphRecord { - entry_offset: entry_offset, - detail_offset: 0, // unused - }; - - let i = self.detail_lookup.binary_search(&key) - .expect("Invalid index not found in detailed glyph lookup table!"); - let main_detail_offset = self.detail_lookup[i].detail_offset; - assert!(main_detail_offset + (detail_offset as usize) < self.detail_buffer.len()); - &self.detail_buffer[main_detail_offset + (detail_offset as usize)] - } - - fn ensure_sorted(&mut self) { - if self.lookup_is_sorted { - return; - } - - // Sorting a unique vector is surprisingly hard. The following - // code is a good argument for using DVecs, but they require - // immutable locations thus don't play well with freezing. - - // Thar be dragons here. You have been warned. (Tips accepted.) - let mut unsorted_records: Vec = vec!(); - mem::swap(&mut self.detail_lookup, &mut unsorted_records); - let mut mut_records: Vec = unsorted_records; - mut_records.sort_by(|a, b| { - if a < b { - Ordering::Less - } else { - Ordering::Greater - } - }); - let mut sorted_records = mut_records; - mem::swap(&mut self.detail_lookup, &mut sorted_records); - - self.lookup_is_sorted = true; - } -} - -// This struct is used by GlyphStore clients to provide new glyph data. -// It should be allocated on the stack and passed by reference to GlyphStore. -#[derive(Clone, Copy)] -pub struct GlyphData { - id: GlyphId, - advance: Au, - offset: Point2D, - cluster_start: bool, - ligature_start: bool, -} - -impl GlyphData { - /// Creates a new entry for one glyph. - pub fn new(id: GlyphId, - advance: Au, - offset: Option>, - cluster_start: bool, - ligature_start: bool) - -> GlyphData { - GlyphData { - id: id, - advance: advance, - offset: offset.unwrap_or(Point2D::zero()), - cluster_start: cluster_start, - ligature_start: ligature_start, - } - } -} - -// This enum is a proxy that's provided to GlyphStore clients when iterating -// through glyphs (either for a particular TextRun offset, or all glyphs). -// Rather than eagerly assembling and copying glyph data, it only retrieves -// values as they are needed from the GlyphStore, using provided offsets. -#[derive(Clone, Copy)] -pub enum GlyphInfo<'a> { - Simple(&'a GlyphStore, ByteIndex), - Detail(&'a GlyphStore, ByteIndex, u16), -} - -impl<'a> GlyphInfo<'a> { - pub fn id(self) -> GlyphId { - match self { - GlyphInfo::Simple(store, entry_i) => store.entry_buffer[entry_i.to_usize()].id(), - GlyphInfo::Detail(store, entry_i, detail_j) => { - store.detail_store.detailed_glyph_with_index(entry_i, detail_j).id - } - } - } - - #[inline(always)] - // FIXME: Resolution conflicts with IteratorUtil trait so adding trailing _ - pub fn advance(self) -> Au { - match self { - GlyphInfo::Simple(store, entry_i) => store.entry_buffer[entry_i.to_usize()].advance(), - GlyphInfo::Detail(store, entry_i, detail_j) => { - store.detail_store.detailed_glyph_with_index(entry_i, detail_j).advance - } - } - } - - #[inline] - pub fn offset(self) -> Option> { - match self { - GlyphInfo::Simple(_, _) => None, - GlyphInfo::Detail(store, entry_i, detail_j) => { - Some(store.detail_store.detailed_glyph_with_index(entry_i, detail_j).offset) - } - } - } - - pub fn char_is_space(self) -> bool { - let (store, entry_i) = match self { - GlyphInfo::Simple(store, entry_i) => (store, entry_i), - GlyphInfo::Detail(store, entry_i, _) => (store, entry_i), - }; - - store.char_is_space(entry_i) - } -} - -/// Stores the glyph data belonging to a text run. -/// -/// Simple glyphs are stored inline in the `entry_buffer`, detailed glyphs are -/// stored as pointers into the `detail_store`. -/// -/// ~~~ascii -/// +- GlyphStore --------------------------------+ -/// | +---+---+---+---+---+---+---+ | -/// | entry_buffer: | | s | | s | | s | s | | d = detailed -/// | +-|-+---+-|-+---+-|-+---+---+ | s = simple -/// | | | | | -/// | | +---+-------+ | -/// | | | | -/// | +-V-+-V-+ | -/// | detail_store: | d | d | | -/// | +---+---+ | -/// +---------------------------------------------+ -/// ~~~ -#[derive(Clone, Deserialize, Serialize)] -pub struct GlyphStore { - // TODO(pcwalton): Allocation of this buffer is expensive. Consider a small-vector - // optimization. - /// A buffer of glyphs within the text run, in the order in which they - /// appear in the input text. - /// Any changes will also need to be reflected in - /// transmute_entry_buffer_to_u32_buffer(). - entry_buffer: Vec, - /// A store of the detailed glyph data. Detailed glyphs contained in the - /// `entry_buffer` point to locations in this data structure. - detail_store: DetailedGlyphStore, - - /// A cache of the advance of the entire glyph store. - total_advance: Au, - /// A cache of the number of spaces in the entire glyph store. - total_spaces: i32, - - /// Used to check if fast path should be used in glyph iteration. - has_detailed_glyphs: bool, - is_whitespace: bool, - is_rtl: bool, -} - -impl<'a> GlyphStore { - /// Initializes the glyph store, but doesn't actually shape anything. - /// - /// Use the `add_*` methods to store glyph data. - pub fn new(length: usize, is_whitespace: bool, is_rtl: bool) -> GlyphStore { - assert!(length > 0); - - GlyphStore { - entry_buffer: vec![GlyphEntry::initial(); length], - detail_store: DetailedGlyphStore::new(), - total_advance: Au(0), - total_spaces: 0, - has_detailed_glyphs: false, - is_whitespace: is_whitespace, - is_rtl: is_rtl, - } - } - - #[inline] - pub fn len(&self) -> ByteIndex { - ByteIndex(self.entry_buffer.len() as isize) - } - - #[inline] - pub fn is_whitespace(&self) -> bool { - self.is_whitespace - } - - pub fn finalize_changes(&mut self) { - self.detail_store.ensure_sorted(); - self.cache_total_advance_and_spaces() - } - - #[inline(never)] - fn cache_total_advance_and_spaces(&mut self) { - let mut total_advance = Au(0); - let mut total_spaces = 0; - for glyph in self.iter_glyphs_for_byte_range(&Range::new(ByteIndex(0), self.len())) { - total_advance = total_advance + glyph.advance(); - if glyph.char_is_space() { - total_spaces += 1; - } - } - self.total_advance = total_advance; - self.total_spaces = total_spaces; - } - - /// Adds a single glyph. - pub fn add_glyph_for_byte_index(&mut self, - i: ByteIndex, - character: char, - data: &GlyphData) { - let glyph_is_compressible = is_simple_glyph_id(data.id) && - is_simple_advance(data.advance) && - data.offset == Point2D::zero() && - data.cluster_start; // others are stored in detail buffer - - debug_assert!(data.ligature_start); // can't compress ligature continuation glyphs. - debug_assert!(i < self.len()); - - let mut entry = if glyph_is_compressible { - GlyphEntry::simple(data.id, data.advance) - } else { - let glyph = &[DetailedGlyph::new(data.id, data.advance, data.offset)]; - self.has_detailed_glyphs = true; - self.detail_store.add_detailed_glyphs_for_entry(i, glyph); - GlyphEntry::complex(data.cluster_start, data.ligature_start, 1) - }; - - if character == ' ' { - entry.set_char_is_space() - } - - self.entry_buffer[i.to_usize()] = entry; - } - - pub fn add_glyphs_for_byte_index(&mut self, i: ByteIndex, data_for_glyphs: &[GlyphData]) { - assert!(i < self.len()); - assert!(data_for_glyphs.len() > 0); - - let glyph_count = data_for_glyphs.len(); - - let first_glyph_data = data_for_glyphs[0]; - let glyphs_vec: Vec = (0..glyph_count).map(|i| { - DetailedGlyph::new(data_for_glyphs[i].id, - data_for_glyphs[i].advance, - data_for_glyphs[i].offset) - }).collect(); - - self.has_detailed_glyphs = true; - self.detail_store.add_detailed_glyphs_for_entry(i, &glyphs_vec); - - let entry = GlyphEntry::complex(first_glyph_data.cluster_start, - first_glyph_data.ligature_start, - glyph_count); - - debug!("Adding multiple glyphs[idx={:?}, count={}]: {:?}", i, glyph_count, entry); - - self.entry_buffer[i.to_usize()] = entry; - } - - #[inline] - pub fn iter_glyphs_for_byte_range(&'a self, range: &Range) -> GlyphIterator<'a> { - if range.begin() >= self.len() { - panic!("iter_glyphs_for_range: range.begin beyond length!"); - } - if range.end() > self.len() { - panic!("iter_glyphs_for_range: range.end beyond length!"); - } - - GlyphIterator { - store: self, - byte_index: if self.is_rtl { range.end() } else { range.begin() - ByteIndex(1) }, - byte_range: *range, - glyph_range: None, - } - } - - // Scan the glyphs for a given range until we reach a given advance. Returns the index - // and advance of the glyph in the range at the given advance, if reached. Otherwise, returns the - // the number of glyphs and the advance for the given range. - #[inline] - pub fn range_index_of_advance(&self, range: &Range, advance: Au, extra_word_spacing: Au) -> (usize, Au) { - let mut index = 0; - let mut current_advance = Au(0); - for glyph in self.iter_glyphs_for_byte_range(range) { - if glyph.char_is_space() { - current_advance += glyph.advance() + extra_word_spacing - } else { - current_advance += glyph.advance() - } - if current_advance > advance { - break; - } - index += 1; - } - (index, current_advance) - } - - #[inline] - pub fn advance_for_byte_range(&self, range: &Range, extra_word_spacing: Au) -> Au { - if range.begin() == ByteIndex(0) && range.end() == self.len() { - self.total_advance + extra_word_spacing * self.total_spaces - } else if !self.has_detailed_glyphs { - self.advance_for_byte_range_simple_glyphs(range, extra_word_spacing) - } else { - self.advance_for_byte_range_slow_path(range, extra_word_spacing) - } - } - - #[inline] - pub fn advance_for_byte_range_slow_path(&self, range: &Range, extra_word_spacing: Au) -> Au { - self.iter_glyphs_for_byte_range(range) - .fold(Au(0), |advance, glyph| { - if glyph.char_is_space() { - advance + glyph.advance() + extra_word_spacing - } else { - advance + glyph.advance() - } - }) - } - - #[inline] - #[cfg(feature = "unstable")] - #[cfg(any(target_feature = "sse2", target_feature = "neon"))] - fn advance_for_byte_range_simple_glyphs(&self, range: &Range, extra_word_spacing: Au) -> Au { - let advance_mask = u32x4::splat(GLYPH_ADVANCE_MASK); - let space_flag_mask = u32x4::splat(FLAG_CHAR_IS_SPACE); - let mut simd_advance = u32x4::splat(0); - let mut simd_spaces = u32x4::splat(0); - let begin = range.begin().to_usize(); - let len = range.length().to_usize(); - let num_simd_iterations = len / 4; - let leftover_entries = range.end().to_usize() - (len - num_simd_iterations * 4); - let buf = self.transmute_entry_buffer_to_u32_buffer(); - - for i in 0..num_simd_iterations { - let v = u32x4::load(buf, begin + i * 4); - let advance = (v & advance_mask) >> GLYPH_ADVANCE_SHIFT; - let spaces = (v & space_flag_mask) >> FLAG_CHAR_IS_SPACE_SHIFT; - simd_advance = simd_advance + advance; - simd_spaces = simd_spaces + spaces; - } - - let advance = - (simd_advance.extract(0) + - simd_advance.extract(1) + - simd_advance.extract(2) + - simd_advance.extract(3)) as i32; - let spaces = - (simd_spaces.extract(0) + - simd_spaces.extract(1) + - simd_spaces.extract(2) + - simd_spaces.extract(3)) as i32; - let mut leftover_advance = Au(0); - let mut leftover_spaces = 0; - for i in leftover_entries..range.end().to_usize() { - leftover_advance = leftover_advance + self.entry_buffer[i].advance(); - if self.entry_buffer[i].char_is_space() { - leftover_spaces += 1; - } - } - Au::new(advance) + leftover_advance + extra_word_spacing * (spaces + leftover_spaces) - } - - /// When SIMD isn't available, fallback to the slow path. - #[inline] - #[cfg(not(all(feature = "unstable", any(target_feature = "sse2", target_feature = "neon"))))] - fn advance_for_byte_range_simple_glyphs(&self, range: &Range, extra_word_spacing: Au) -> Au { - self.advance_for_byte_range_slow_path(range, extra_word_spacing) - } - - /// Used for SIMD. - #[inline] - #[cfg(feature = "unstable")] - #[cfg(any(target_feature = "sse2", target_feature = "neon"))] - #[allow(unsafe_code)] - fn transmute_entry_buffer_to_u32_buffer(&self) -> &[u32] { - unsafe { mem::transmute(self.entry_buffer.as_slice()) } - } - - pub fn char_is_space(&self, i: ByteIndex) -> bool { - assert!(i < self.len()); - self.entry_buffer[i.to_usize()].char_is_space() - } - - pub fn space_count_in_range(&self, range: &Range) -> u32 { - let mut spaces = 0; - for index in range.each_index() { - if self.char_is_space(index) { - spaces += 1 - } - } - spaces - } -} - -impl fmt::Debug for GlyphStore { - fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { - write!(formatter, "GlyphStore:\n")?; - let mut detailed_buffer = self.detail_store.detail_buffer.iter(); - for entry in self.entry_buffer.iter() { - if entry.is_simple() { - write!(formatter, - " simple id={:?} advance={:?}\n", - entry.id(), - entry.advance())?; - continue - } - if entry.is_initial() { - continue - } - write!(formatter, " complex...")?; - if detailed_buffer.next().is_none() { - continue - } - write!(formatter, - " detailed id={:?} advance={:?}\n", - entry.id(), - entry.advance())?; - } - Ok(()) - } -} - -/// An iterator over the glyphs in a byte range in a `GlyphStore`. -pub struct GlyphIterator<'a> { - store: &'a GlyphStore, - byte_index: ByteIndex, - byte_range: Range, - glyph_range: Option>, -} - -impl<'a> GlyphIterator<'a> { - // Slow path when there is a glyph range. - #[inline(never)] - fn next_glyph_range(&mut self) -> Option> { - match self.glyph_range.as_mut().unwrap().next() { - Some(j) => { - Some(GlyphInfo::Detail(self.store, self.byte_index, j.get() as u16 /* ??? */)) - } - None => { - // No more glyphs for current character. Try to get another. - self.glyph_range = None; - self.next() - } - } - } - - // Slow path when there is a complex glyph. - #[inline(never)] - fn next_complex_glyph(&mut self, entry: &GlyphEntry, i: ByteIndex) -> Option> { - let glyphs = self.store.detail_store.detailed_glyphs_for_entry(i, entry.glyph_count()); - self.glyph_range = Some(range::each_index(ByteIndex(0), ByteIndex(glyphs.len() as isize))); - self.next() - } -} - -impl<'a> Iterator for GlyphIterator<'a> { - type Item = GlyphInfo<'a>; - - // I tried to start with something simpler and apply FlatMap, but the - // inability to store free variables in the FlatMap struct was problematic. - // - // This function consists of the fast path and is designed to be inlined into its caller. The - // slow paths, which should not be inlined, are `next_glyph_range()` and - // `next_complex_glyph()`. - #[inline(always)] - fn next(&mut self) -> Option> { - // Would use 'match' here but it borrows contents in a way that interferes with mutation. - if self.glyph_range.is_some() { - return self.next_glyph_range() - } - - // No glyph range. Look at next byte. - self.byte_index = self.byte_index + if self.store.is_rtl { - ByteIndex(-1) - } else { - ByteIndex(1) - }; - let i = self.byte_index; - if !self.byte_range.contains(i) { - return None - } - debug_assert!(i < self.store.len()); - let entry = self.store.entry_buffer[i.to_usize()]; - if entry.is_simple() { - Some(GlyphInfo::Simple(self.store, i)) - } else { - // Fall back to the slow path. - self.next_complex_glyph(&entry, i) - } - } -} diff --git a/servo/components/gfx/text/mod.rs b/servo/components/gfx/text/mod.rs deleted file mode 100644 index 5aae0876428f..000000000000 --- a/servo/components/gfx/text/mod.rs +++ /dev/null @@ -1,12 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -pub use text::shaping::Shaper; -pub use text::text_run::TextRun; - -pub mod glyph; -pub mod shaping; -pub mod text_run; -pub mod util; - diff --git a/servo/components/gfx/text/shaping/harfbuzz.rs b/servo/components/gfx/text/shaping/harfbuzz.rs deleted file mode 100644 index c1b25e42d9bc..000000000000 --- a/servo/components/gfx/text/shaping/harfbuzz.rs +++ /dev/null @@ -1,532 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -#![allow(unsafe_code)] - -use app_units::Au; -use euclid::Point2D; -use font::{ShapingFlags, Font, FontTableMethods, FontTableTag, ShapingOptions, KERN}; -use harfbuzz::{HB_DIRECTION_LTR, HB_DIRECTION_RTL, HB_MEMORY_MODE_READONLY}; -use harfbuzz::{hb_blob_create, hb_face_create_for_tables}; -use harfbuzz::{hb_buffer_create, hb_font_destroy}; -use harfbuzz::{hb_buffer_get_glyph_infos, hb_shape}; -use harfbuzz::{hb_buffer_set_direction, hb_buffer_set_script}; -use harfbuzz::{hb_buffer_t, hb_codepoint_t, hb_font_funcs_t}; -use harfbuzz::{hb_face_t, hb_font_t}; -use harfbuzz::{hb_position_t, hb_tag_t}; -use harfbuzz::hb_blob_t; -use harfbuzz::hb_bool_t; -use harfbuzz::hb_buffer_add_utf8; -use harfbuzz::hb_buffer_destroy; -use harfbuzz::hb_buffer_get_glyph_positions; -use harfbuzz::hb_buffer_get_length; -use harfbuzz::hb_face_destroy; -use harfbuzz::hb_feature_t; -use harfbuzz::hb_font_create; -use harfbuzz::hb_font_funcs_create; -use harfbuzz::hb_font_funcs_set_glyph_func; -use harfbuzz::hb_font_funcs_set_glyph_h_advance_func; -use harfbuzz::hb_font_funcs_set_glyph_h_kerning_func; -use harfbuzz::hb_font_set_funcs; -use harfbuzz::hb_font_set_ppem; -use harfbuzz::hb_font_set_scale; -use harfbuzz::hb_glyph_info_t; -use harfbuzz::hb_glyph_position_t; -use libc::{c_char, c_int, c_uint, c_void}; -use platform::font::FontTable; -use std::{char, cmp, ptr}; -use text::glyph::{ByteIndex, GlyphData, GlyphId, GlyphStore}; -use text::shaping::ShaperMethods; -use text::util::{fixed_to_float, float_to_fixed, is_bidi_control}; - -const NO_GLYPH: i32 = -1; -const LIGA: u32 = ot_tag!('l', 'i', 'g', 'a'); - -pub struct ShapedGlyphData { - count: usize, - glyph_infos: *mut hb_glyph_info_t, - pos_infos: *mut hb_glyph_position_t, -} - -pub struct ShapedGlyphEntry { - codepoint: GlyphId, - advance: Au, - offset: Option>, -} - -impl ShapedGlyphData { - pub fn new(buffer: *mut hb_buffer_t) -> ShapedGlyphData { - unsafe { - let mut glyph_count = 0; - let glyph_infos = hb_buffer_get_glyph_infos(buffer, &mut glyph_count); - assert!(!glyph_infos.is_null()); - let mut pos_count = 0; - let pos_infos = hb_buffer_get_glyph_positions(buffer, &mut pos_count); - assert!(!pos_infos.is_null()); - assert_eq!(glyph_count, pos_count); - - ShapedGlyphData { - count: glyph_count as usize, - glyph_infos: glyph_infos, - pos_infos: pos_infos, - } - } - } - - #[inline(always)] - fn byte_offset_of_glyph(&self, i: usize) -> u32 { - assert!(i < self.count); - - unsafe { - let glyph_info_i = self.glyph_infos.offset(i as isize); - (*glyph_info_i).cluster - } - } - - pub fn len(&self) -> usize { - self.count - } - - /// Returns shaped glyph data for one glyph, and updates the y-position of the pen. - pub fn entry_for_glyph(&self, i: usize, y_pos: &mut Au) -> ShapedGlyphEntry { - assert!(i < self.count); - - unsafe { - let glyph_info_i = self.glyph_infos.offset(i as isize); - let pos_info_i = self.pos_infos.offset(i as isize); - let x_offset = Shaper::fixed_to_float((*pos_info_i).x_offset); - let y_offset = Shaper::fixed_to_float((*pos_info_i).y_offset); - let x_advance = Shaper::fixed_to_float((*pos_info_i).x_advance); - let y_advance = Shaper::fixed_to_float((*pos_info_i).y_advance); - - let x_offset = Au::from_f64_px(x_offset); - let y_offset = Au::from_f64_px(y_offset); - let x_advance = Au::from_f64_px(x_advance); - let y_advance = Au::from_f64_px(y_advance); - - let offset = if x_offset == Au(0) && y_offset == Au(0) && y_advance == Au(0) { - None - } else { - // adjust the pen.. - if y_advance > Au(0) { - *y_pos = *y_pos - y_advance; - } - - Some(Point2D::new(x_offset, *y_pos - y_offset)) - }; - - ShapedGlyphEntry { - codepoint: (*glyph_info_i).codepoint as GlyphId, - advance: x_advance, - offset: offset, - } - } - } -} - -#[derive(Debug)] -pub struct Shaper { - hb_face: *mut hb_face_t, - hb_font: *mut hb_font_t, - font: *const Font, -} - -impl Drop for Shaper { - fn drop(&mut self) { - unsafe { - assert!(!self.hb_face.is_null()); - hb_face_destroy(self.hb_face); - - assert!(!self.hb_font.is_null()); - hb_font_destroy(self.hb_font); - } - } -} - -impl Shaper { - pub fn new(font: *const Font) -> Shaper { - unsafe { - let hb_face: *mut hb_face_t = - hb_face_create_for_tables(Some(font_table_func), - font as *const c_void as *mut c_void, - None); - let hb_font: *mut hb_font_t = hb_font_create(hb_face); - - // Set points-per-em. if zero, performs no hinting in that direction. - let pt_size = (*font).actual_pt_size.to_f64_px(); - hb_font_set_ppem(hb_font, pt_size as c_uint, pt_size as c_uint); - - // Set scaling. Note that this takes 16.16 fixed point. - hb_font_set_scale(hb_font, - Shaper::float_to_fixed(pt_size) as c_int, - Shaper::float_to_fixed(pt_size) as c_int); - - // configure static function callbacks. - hb_font_set_funcs(hb_font, HB_FONT_FUNCS.0, font as *mut Font as *mut c_void, None); - - Shaper { - hb_face: hb_face, - hb_font: hb_font, - font: font, - } - } - } - - fn float_to_fixed(f: f64) -> i32 { - float_to_fixed(16, f) - } - - fn fixed_to_float(i: hb_position_t) -> f64 { - fixed_to_float(16, i) - } -} - -impl ShaperMethods for Shaper { - /// Calculate the layout metrics associated with the given text when painted in a specific - /// font. - fn shape_text(&self, text: &str, options: &ShapingOptions, glyphs: &mut GlyphStore) { - unsafe { - let hb_buffer: *mut hb_buffer_t = hb_buffer_create(); - hb_buffer_set_direction(hb_buffer, if options.flags.contains(ShapingFlags::RTL_FLAG) { - HB_DIRECTION_RTL - } else { - HB_DIRECTION_LTR - }); - - hb_buffer_set_script(hb_buffer, options.script.to_hb_script()); - - hb_buffer_add_utf8(hb_buffer, - text.as_ptr() as *const c_char, - text.len() as c_int, - 0, - text.len() as c_int); - - let mut features = Vec::new(); - if options.flags.contains(ShapingFlags::IGNORE_LIGATURES_SHAPING_FLAG) { - features.push(hb_feature_t { - tag: LIGA, - value: 0, - start: 0, - end: hb_buffer_get_length(hb_buffer), - }) - } - if options.flags.contains(ShapingFlags::DISABLE_KERNING_SHAPING_FLAG) { - features.push(hb_feature_t { - tag: KERN, - value: 0, - start: 0, - end: hb_buffer_get_length(hb_buffer), - }) - } - - hb_shape(self.hb_font, hb_buffer, features.as_mut_ptr(), features.len() as u32); - self.save_glyph_results(text, options, glyphs, hb_buffer); - hb_buffer_destroy(hb_buffer); - } - } -} - -impl Shaper { - fn save_glyph_results(&self, - text: &str, - options: &ShapingOptions, - glyphs: &mut GlyphStore, - buffer: *mut hb_buffer_t) { - let glyph_data = ShapedGlyphData::new(buffer); - let glyph_count = glyph_data.len(); - let byte_max = text.len(); - - debug!("Shaped text[byte count={}], got back {} glyph info records.", - byte_max, - glyph_count); - - // make map of what chars have glyphs - let mut byte_to_glyph = vec![NO_GLYPH; byte_max]; - - debug!("(glyph idx) -> (text byte offset)"); - for i in 0..glyph_data.len() { - let loc = glyph_data.byte_offset_of_glyph(i) as usize; - if loc < byte_max { - byte_to_glyph[loc] = i as i32; - } else { - debug!("ERROR: tried to set out of range byte_to_glyph: idx={}, glyph idx={}", - loc, - i); - } - debug!("{} -> {}", i, loc); - } - - debug!("text: {:?}", text); - debug!("(char idx): char->(glyph index):"); - for (i, ch) in text.char_indices() { - debug!("{}: {:?} --> {}", i, ch, byte_to_glyph[i]); - } - - let mut glyph_span = 0..0; - let mut byte_range = 0..0; - - let mut y_pos = Au(0); - - // main loop over each glyph. each iteration usually processes 1 glyph and 1+ chars. - // in cases with complex glyph-character associations, 2+ glyphs and 1+ chars can be - // processed. - while glyph_span.start < glyph_count { - debug!("Processing glyph at idx={}", glyph_span.start); - glyph_span.end = glyph_span.start; - byte_range.end = glyph_data.byte_offset_of_glyph(glyph_span.start) as usize; - - while byte_range.end < byte_max { - byte_range.end += 1; - // Extend the byte range to include any following byte without its own glyph. - while byte_range.end < byte_max && byte_to_glyph[byte_range.end] == NO_GLYPH { - byte_range.end += 1; - } - - // Extend the glyph range to include all glyphs covered by bytes processed so far. - let mut max_glyph_idx = glyph_span.end; - for glyph_idx in &byte_to_glyph[byte_range.clone()] { - if *glyph_idx != NO_GLYPH { - max_glyph_idx = cmp::max(*glyph_idx as usize + 1, max_glyph_idx); - } - } - if max_glyph_idx > glyph_span.end { - glyph_span.end = max_glyph_idx; - debug!("Extended glyph span to {:?}", glyph_span); - } - - // if there's just one glyph, then we don't need further checks. - if glyph_span.len() == 1 { break; } - - // if no glyphs were found yet, extend the char byte range more. - if glyph_span.len() == 0 { continue; } - - // If byte_range now includes all the byte offsets found in glyph_span, then we - // have found a contiguous "cluster" and can stop extending it. - let mut all_glyphs_are_within_cluster: bool = true; - for j in glyph_span.clone() { - let loc = glyph_data.byte_offset_of_glyph(j) as usize; - if !(byte_range.start <= loc && loc < byte_range.end) { - all_glyphs_are_within_cluster = false; - break - } - } - if all_glyphs_are_within_cluster { - break - } - - // Otherwise, the bytes we have seen so far correspond to a non-contiguous set of - // glyphs. Keep extending byte_range until we fill in all the holes in the glyph - // span or reach the end of the text. - } - - assert!(byte_range.len() > 0); - assert!(glyph_span.len() > 0); - - // Now byte_range is the ligature clump formed by the glyphs in glyph_span. - // We will save these glyphs to the glyph store at the index of the first byte. - let byte_idx = ByteIndex(byte_range.start as isize); - - if glyph_span.len() == 1 { - // Fast path: 1-to-1 mapping of byte offset to single glyph. - // - // TODO(Issue #214): cluster ranges need to be computed before - // shaping, and then consulted here. - // for now, just pretend that every character is a cluster start. - // (i.e., pretend there are no combining character sequences). - // 1-to-1 mapping of character to glyph also treated as ligature start. - // - // NB: When we acquire the ability to handle ligatures that cross word boundaries, - // we'll need to do something special to handle `word-spacing` properly. - let character = text[byte_range.clone()].chars().next().unwrap(); - if is_bidi_control(character) { - // Don't add any glyphs for bidi control chars - } else if character == '\t' { - // Treat tabs in pre-formatted text as a fixed number of spaces. - // - // TODO: Proper tab stops. - const TAB_COLS: i32 = 8; - let (space_glyph_id, space_advance) = glyph_space_advance(self.font); - let advance = Au::from_f64_px(space_advance) * TAB_COLS; - let data = GlyphData::new(space_glyph_id, - advance, - Default::default(), - true, - true); - glyphs.add_glyph_for_byte_index(byte_idx, character, &data); - } else { - let shape = glyph_data.entry_for_glyph(glyph_span.start, &mut y_pos); - let advance = self.advance_for_shaped_glyph(shape.advance, character, options); - let data = GlyphData::new(shape.codepoint, - advance, - shape.offset, - true, - true); - glyphs.add_glyph_for_byte_index(byte_idx, character, &data); - } - } else { - // collect all glyphs to be assigned to the first character. - let mut datas = vec!(); - - for glyph_i in glyph_span.clone() { - let shape = glyph_data.entry_for_glyph(glyph_i, &mut y_pos); - datas.push(GlyphData::new(shape.codepoint, - shape.advance, - shape.offset, - true, // treat as cluster start - glyph_i > glyph_span.start)); - // all but first are ligature continuations - } - // now add the detailed glyph entry. - glyphs.add_glyphs_for_byte_index(byte_idx, &datas); - } - - glyph_span.start = glyph_span.end; - byte_range.start = byte_range.end; - } - - // this must be called after adding all glyph data; it sorts the - // lookup table for finding detailed glyphs by associated char index. - glyphs.finalize_changes(); - } - - fn advance_for_shaped_glyph(&self, mut advance: Au, character: char, options: &ShapingOptions) - -> Au { - if let Some(letter_spacing) = options.letter_spacing { - advance = advance + letter_spacing; - }; - - // CSS 2.1 § 16.4 states that "word spacing affects each space (U+0020) and non-breaking - // space (U+00A0) left in the text after the white space processing rules have been - // applied. The effect of the property on other word-separator characters is undefined." - // We elect to only space the two required code points. - if character == ' ' || character == '\u{a0}' { - // https://drafts.csswg.org/css-text-3/#word-spacing-property - let (length, percent) = options.word_spacing; - advance = (advance + length) + Au::new((advance.0 as f32 * percent.into_inner()) as i32); - } - - advance - } -} - -/// Callbacks from Harfbuzz when font map and glyph advance lookup needed. -struct FontFuncs(*mut hb_font_funcs_t); - -unsafe impl Sync for FontFuncs {} - -lazy_static! { - static ref HB_FONT_FUNCS: FontFuncs = unsafe { - let hb_funcs = hb_font_funcs_create(); - hb_font_funcs_set_glyph_func(hb_funcs, Some(glyph_func), ptr::null_mut(), None); - hb_font_funcs_set_glyph_h_advance_func( - hb_funcs, Some(glyph_h_advance_func), ptr::null_mut(), None); - hb_font_funcs_set_glyph_h_kerning_func( - hb_funcs, Some(glyph_h_kerning_func), ptr::null_mut(), None); - - FontFuncs(hb_funcs) - }; -} - -extern fn glyph_func(_: *mut hb_font_t, - font_data: *mut c_void, - unicode: hb_codepoint_t, - _: hb_codepoint_t, - glyph: *mut hb_codepoint_t, - _: *mut c_void) - -> hb_bool_t { - let font: *const Font = font_data as *const Font; - assert!(!font.is_null()); - - unsafe { - match (*font).glyph_index(char::from_u32(unicode).unwrap()) { - Some(g) => { - *glyph = g as hb_codepoint_t; - true as hb_bool_t - } - None => false as hb_bool_t - } - } -} - -extern fn glyph_h_advance_func(_: *mut hb_font_t, - font_data: *mut c_void, - glyph: hb_codepoint_t, - _: *mut c_void) - -> hb_position_t { - let font: *mut Font = font_data as *mut Font; - assert!(!font.is_null()); - - unsafe { - let advance = (*font).glyph_h_advance(glyph as GlyphId); - Shaper::float_to_fixed(advance) - } -} - -fn glyph_space_advance(font: *const Font) -> (hb_codepoint_t, f64) { - let space_unicode = ' '; - let space_glyph: hb_codepoint_t; - match unsafe { (*font).glyph_index(space_unicode) } { - Some(g) => { - space_glyph = g as hb_codepoint_t; - } - None => panic!("No space info") - } - let space_advance = unsafe { (*font).glyph_h_advance(space_glyph as GlyphId) }; - (space_glyph, space_advance) -} - -extern fn glyph_h_kerning_func(_: *mut hb_font_t, - font_data: *mut c_void, - first_glyph: hb_codepoint_t, - second_glyph: hb_codepoint_t, - _: *mut c_void) - -> hb_position_t { - let font: *mut Font = font_data as *mut Font; - assert!(!font.is_null()); - - unsafe { - let advance = (*font).glyph_h_kerning(first_glyph as GlyphId, second_glyph as GlyphId); - Shaper::float_to_fixed(advance) - } -} - -// Callback to get a font table out of a font. -extern fn font_table_func(_: *mut hb_face_t, - tag: hb_tag_t, - user_data: *mut c_void) - -> *mut hb_blob_t { - unsafe { - // NB: These asserts have security implications. - let font = user_data as *const Font; - assert!(!font.is_null()); - - // TODO(Issue #197): reuse font table data, which will change the unsound trickery here. - match (*font).table_for_tag(tag as FontTableTag) { - None => ptr::null_mut(), - Some(font_table) => { - // `Box::into_raw` intentionally leaks the FontTable so we don't destroy the buffer - // while HarfBuzz is using it. When HarfBuzz is done with the buffer, it will pass - // this raw pointer back to `destroy_blob_func` which will deallocate the Box. - let font_table_ptr = Box::into_raw(Box::new(font_table)); - - let buf = (*font_table_ptr).buffer(); - // HarfBuzz calls `destroy_blob_func` when the buffer is no longer needed. - let blob = hb_blob_create(buf.as_ptr() as *const c_char, - buf.len() as c_uint, - HB_MEMORY_MODE_READONLY, - font_table_ptr as *mut c_void, - Some(destroy_blob_func)); - - assert!(!blob.is_null()); - blob - } - } - } -} - -extern fn destroy_blob_func(font_table_ptr: *mut c_void) { - unsafe { - drop(Box::from_raw(font_table_ptr as *mut FontTable)); - } -} diff --git a/servo/components/gfx/text/shaping/mod.rs b/servo/components/gfx/text/shaping/mod.rs deleted file mode 100644 index 79e5452db061..000000000000 --- a/servo/components/gfx/text/shaping/mod.rs +++ /dev/null @@ -1,20 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -//! Shaper encapsulates a specific shaper, such as Harfbuzz, -//! Uniscribe, Pango, or Coretext. -//! -//! Currently, only harfbuzz bindings are implemented. - -use font::ShapingOptions; -use text::glyph::GlyphStore; - -pub use text::shaping::harfbuzz::Shaper; - -pub mod harfbuzz; - -pub trait ShaperMethods { - fn shape_text(&self, text: &str, options: &ShapingOptions, glyphs: &mut GlyphStore); -} - diff --git a/servo/components/gfx/text/text_run.rs b/servo/components/gfx/text/text_run.rs deleted file mode 100644 index 62126ab838a7..000000000000 --- a/servo/components/gfx/text/text_run.rs +++ /dev/null @@ -1,409 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -use app_units::Au; -use font::{Font, FontHandleMethods, FontMetrics, ShapingFlags}; -use font::{RunMetrics, ShapingOptions}; -use platform::font_template::FontTemplateData; -use range::Range; -use std::cell::Cell; -use std::cmp::{Ordering, max}; -use std::slice::Iter; -use std::sync::Arc; -use style::str::char_is_whitespace; -use text::glyph::{ByteIndex, GlyphStore}; -use unicode_bidi as bidi; -use webrender_api; -use xi_unicode::LineBreakLeafIter; - -thread_local! { - static INDEX_OF_FIRST_GLYPH_RUN_CACHE: Cell> = - Cell::new(None) -} - -/// A single "paragraph" of text in one font size and style. -#[derive(Clone, Deserialize, Serialize)] -pub struct TextRun { - /// The UTF-8 string represented by this text run. - pub text: Arc, - pub font_template: Arc, - pub actual_pt_size: Au, - pub font_metrics: FontMetrics, - pub font_key: webrender_api::FontInstanceKey, - /// The glyph runs that make up this text run. - pub glyphs: Arc>, - pub bidi_level: bidi::Level, - pub extra_word_spacing: Au, -} - -impl Drop for TextRun { - fn drop(&mut self) { - // Invalidate the glyph run cache if it was our text run that got freed. - INDEX_OF_FIRST_GLYPH_RUN_CACHE.with(|index_of_first_glyph_run_cache| { - if let Some((text_run_ptr, _, _)) = index_of_first_glyph_run_cache.get() { - if text_run_ptr == (self as *const TextRun) { - index_of_first_glyph_run_cache.set(None); - } - } - }) - } -} - -/// A single series of glyphs within a text run. -#[derive(Clone, Deserialize, Serialize)] -pub struct GlyphRun { - /// The glyphs. - pub glyph_store: Arc, - /// The byte range of characters in the containing run. - pub range: Range, -} - -pub struct NaturalWordSliceIterator<'a> { - glyphs: &'a [GlyphRun], - index: usize, - range: Range, - reverse: bool, -} - -impl GlyphRun { - fn compare(&self, key: &ByteIndex) -> Ordering { - if *key < self.range.begin() { - Ordering::Greater - } else if *key >= self.range.end() { - Ordering::Less - } else { - Ordering::Equal - } - } -} - -/// A "slice" of a text run is a series of contiguous glyphs that all belong to the same glyph -/// store. Line breaking strategies yield these. -pub struct TextRunSlice<'a> { - /// The glyph store that the glyphs in this slice belong to. - pub glyphs: &'a GlyphStore, - /// The byte index that this slice begins at, relative to the start of the *text run*. - pub offset: ByteIndex, - /// The range that these glyphs encompass, relative to the start of the *glyph store*. - pub range: Range, -} - -impl<'a> TextRunSlice<'a> { - /// Returns the range that these glyphs encompass, relative to the start of the *text run*. - #[inline] - pub fn text_run_range(&self) -> Range { - let mut range = self.range; - range.shift_by(self.offset); - range - } -} - -impl<'a> Iterator for NaturalWordSliceIterator<'a> { - type Item = TextRunSlice<'a>; - - // inline(always) due to the inefficient rt failures messing up inline heuristics, I think. - #[inline(always)] - fn next(&mut self) -> Option> { - let slice_glyphs; - if self.reverse { - if self.index == 0 { - return None; - } - self.index -= 1; - slice_glyphs = &self.glyphs[self.index]; - } else { - if self.index >= self.glyphs.len() { - return None; - } - slice_glyphs = &self.glyphs[self.index]; - self.index += 1; - } - - let mut byte_range = self.range.intersect(&slice_glyphs.range); - let slice_range_begin = slice_glyphs.range.begin(); - byte_range.shift_by(-slice_range_begin); - - if !byte_range.is_empty() { - Some(TextRunSlice { - glyphs: &*slice_glyphs.glyph_store, - offset: slice_range_begin, - range: byte_range, - }) - } else { - None - } - } -} - -pub struct CharacterSliceIterator<'a> { - text: &'a str, - glyph_run: Option<&'a GlyphRun>, - glyph_run_iter: Iter<'a, GlyphRun>, - range: Range, -} - -impl<'a> Iterator for CharacterSliceIterator<'a> { - type Item = TextRunSlice<'a>; - - // inline(always) due to the inefficient rt failures messing up inline heuristics, I think. - #[inline(always)] - fn next(&mut self) -> Option> { - let glyph_run = self.glyph_run?; - - debug_assert!(!self.range.is_empty()); - let byte_start = self.range.begin(); - let byte_len = match self.text[byte_start.to_usize()..].chars().next() { - Some(ch) => ByteIndex(ch.len_utf8() as isize), - None => unreachable!() // XXX refactor? - }; - - self.range.adjust_by(byte_len, -byte_len); - if self.range.is_empty() { - // We're done. - self.glyph_run = None - } else if self.range.intersect(&glyph_run.range).is_empty() { - // Move on to the next glyph run. - self.glyph_run = self.glyph_run_iter.next(); - } - - let index_within_glyph_run = byte_start - glyph_run.range.begin(); - Some(TextRunSlice { - glyphs: &*glyph_run.glyph_store, - offset: glyph_run.range.begin(), - range: Range::new(index_within_glyph_run, byte_len), - }) - } -} - -impl<'a> TextRun { - /// Constructs a new text run. Also returns if there is a line break at the beginning - pub fn new(font: &mut Font, text: String, options: &ShapingOptions, - bidi_level: bidi::Level, breaker: &mut Option) -> (TextRun, bool) { - let (glyphs, break_at_zero) = TextRun::break_and_shape(font, &text, options, breaker); - (TextRun { - text: Arc::new(text), - font_metrics: font.metrics.clone(), - font_template: font.handle.template(), - font_key: font.font_key, - actual_pt_size: font.actual_pt_size, - glyphs: Arc::new(glyphs), - bidi_level: bidi_level, - extra_word_spacing: Au(0), - }, break_at_zero) - } - - pub fn break_and_shape(font: &mut Font, text: &str, options: &ShapingOptions, - breaker: &mut Option) -> (Vec, bool) { - let mut glyphs = vec!(); - let mut slice = 0..0; - - let mut finished = false; - let mut break_at_zero = false; - - if breaker.is_none() { - if text.len() == 0 { - return (glyphs, true) - } - *breaker = Some(LineBreakLeafIter::new(&text, 0)); - } - - let breaker = breaker.as_mut().unwrap(); - - while !finished { - let (idx, _is_hard_break) = breaker.next(text); - if idx == text.len() { - finished = true; - } - if idx == 0 { - break_at_zero = true; - } - - // Extend the slice to the next UAX#14 line break opportunity. - slice.end = idx; - let word = &text[slice.clone()]; - - // Split off any trailing whitespace into a separate glyph run. - let mut whitespace = slice.end..slice.end; - if let Some((i, _)) = word.char_indices().rev() - .take_while(|&(_, c)| char_is_whitespace(c)).last() { - whitespace.start = slice.start + i; - slice.end = whitespace.start; - } else if idx != text.len() && options.flags.contains(ShapingFlags::KEEP_ALL_FLAG) { - // If there's no whitespace and word-break is set to - // keep-all, try increasing the slice. - continue; - } - if slice.len() > 0 { - glyphs.push(GlyphRun { - glyph_store: font.shape_text(&text[slice.clone()], options), - range: Range::new(ByteIndex(slice.start as isize), - ByteIndex(slice.len() as isize)), - }); - } - if whitespace.len() > 0 { - let mut options = options.clone(); - options.flags.insert(ShapingFlags::IS_WHITESPACE_SHAPING_FLAG); - glyphs.push(GlyphRun { - glyph_store: font.shape_text(&text[whitespace.clone()], &options), - range: Range::new(ByteIndex(whitespace.start as isize), - ByteIndex(whitespace.len() as isize)), - }); - } - slice.start = whitespace.end; - } - (glyphs, break_at_zero) - } - - pub fn ascent(&self) -> Au { - self.font_metrics.ascent - } - - pub fn descent(&self) -> Au { - self.font_metrics.descent - } - - pub fn advance_for_range(&self, range: &Range) -> Au { - if range.is_empty() { - return Au(0) - } - - // TODO(Issue #199): alter advance direction for RTL - // TODO(Issue #98): using inter-char and inter-word spacing settings when measuring text - self.natural_word_slices_in_range(range) - .fold(Au(0), |advance, slice| { - advance + slice.glyphs.advance_for_byte_range(&slice.range, self.extra_word_spacing) - }) - } - - pub fn metrics_for_range(&self, range: &Range) -> RunMetrics { - RunMetrics::new(self.advance_for_range(range), - self.font_metrics.ascent, - self.font_metrics.descent) - } - - pub fn metrics_for_slice(&self, glyphs: &GlyphStore, slice_range: &Range) - -> RunMetrics { - RunMetrics::new(glyphs.advance_for_byte_range(slice_range, self.extra_word_spacing), - self.font_metrics.ascent, - self.font_metrics.descent) - } - - pub fn min_width_for_range(&self, range: &Range) -> Au { - debug!("iterating outer range {:?}", range); - self.natural_word_slices_in_range(range).fold(Au(0), |max_piece_width, slice| { - debug!("iterated on {:?}[{:?}]", slice.offset, slice.range); - max(max_piece_width, self.advance_for_range(&slice.range)) - }) - } - - pub fn minimum_splittable_inline_size(&self, range: &Range) -> Au { - match self.natural_word_slices_in_range(range).next() { - None => Au(0), - Some(slice) => self.advance_for_range(&slice.range), - } - } - - /// Returns the index of the first glyph run containing the given character index. - fn index_of_first_glyph_run_containing(&self, index: ByteIndex) -> Option { - let self_ptr = self as *const TextRun; - INDEX_OF_FIRST_GLYPH_RUN_CACHE.with(|index_of_first_glyph_run_cache| { - if let Some((last_text_run, last_index, last_result)) = - index_of_first_glyph_run_cache.get() { - if last_text_run == self_ptr && last_index == index { - return Some(last_result) - } - } - - if let Ok(result) = (&**self.glyphs).binary_search_by(|current| current.compare(&index)) { - index_of_first_glyph_run_cache.set(Some((self_ptr, index, result))); - Some(result) - } else { - None - } - }) - } - - pub fn on_glyph_run_boundary(&self, index: ByteIndex) -> bool { - if let Some(glyph_index) = self.index_of_first_glyph_run_containing(index) { - self.glyphs[glyph_index].range.begin() == index - } else { - true - } - } - - /// Returns the index in the range of the first glyph advancing over given advance - pub fn range_index_of_advance(&self, range: &Range, advance: Au) -> usize { - // TODO(Issue #199): alter advance direction for RTL - // TODO(Issue #98): using inter-char and inter-word spacing settings when measuring text - let mut remaining = advance; - self.natural_word_slices_in_range(range) - .map(|slice| { - let (slice_index, slice_advance) = - slice.glyphs.range_index_of_advance(&slice.range, remaining, self.extra_word_spacing); - remaining -= slice_advance; - slice_index - }) - .sum() - } - - /// Returns an iterator that will iterate over all slices of glyphs that represent natural - /// words in the given range. - pub fn natural_word_slices_in_range(&'a self, range: &Range) - -> NaturalWordSliceIterator<'a> { - let index = match self.index_of_first_glyph_run_containing(range.begin()) { - None => self.glyphs.len(), - Some(index) => index, - }; - NaturalWordSliceIterator { - glyphs: &self.glyphs[..], - index: index, - range: *range, - reverse: false, - } - } - - /// Returns an iterator that over natural word slices in visual order (left to right or - /// right to left, depending on the bidirectional embedding level). - pub fn natural_word_slices_in_visual_order(&'a self, range: &Range) - -> NaturalWordSliceIterator<'a> { - // Iterate in reverse order if bidi level is RTL. - let reverse = self.bidi_level.is_rtl(); - - let index = if reverse { - match self.index_of_first_glyph_run_containing(range.end() - ByteIndex(1)) { - Some(i) => i + 1, // In reverse mode, index points one past the next element. - None => 0 - } - } else { - match self.index_of_first_glyph_run_containing(range.begin()) { - Some(i) => i, - None => self.glyphs.len() - } - }; - NaturalWordSliceIterator { - glyphs: &self.glyphs[..], - index: index, - range: *range, - reverse: reverse, - } - } - - /// Returns an iterator that will iterate over all slices of glyphs that represent individual - /// characters in the given range. - pub fn character_slices_in_range(&'a self, range: &Range) - -> CharacterSliceIterator<'a> { - let index = match self.index_of_first_glyph_run_containing(range.begin()) { - None => self.glyphs.len(), - Some(index) => index, - }; - let mut glyph_run_iter = self.glyphs[index..].iter(); - let first_glyph_run = glyph_run_iter.next(); - CharacterSliceIterator { - text: &self.text, - glyph_run: first_glyph_run, - glyph_run_iter: glyph_run_iter, - range: *range, - } - } -} diff --git a/servo/components/gfx/text/util.rs b/servo/components/gfx/text/util.rs deleted file mode 100644 index 5be03cb2b78c..000000000000 --- a/servo/components/gfx/text/util.rs +++ /dev/null @@ -1,116 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -#[derive(Clone, Copy, Debug, Eq, PartialEq)] -pub enum CompressionMode { - CompressNone, - CompressWhitespace, - CompressWhitespaceNewline, - DiscardNewline -} - -// ported from Gecko's nsTextFrameUtils::TransformText. -// -// High level TODOs: -// -// * Issue #113: consider incoming text state (arabic, etc) -// and propagate outgoing text state (dual of above) -// -// * Issue #114: record skipped and kept chars for mapping original to new text -// -// * Untracked: various edge cases for bidi, CJK, etc. -pub fn transform_text(text: &str, - mode: CompressionMode, - incoming_whitespace: bool, - output_text: &mut String) - -> bool { - let out_whitespace = match mode { - CompressionMode::CompressNone | CompressionMode::DiscardNewline => { - for ch in text.chars() { - if is_discardable_char(ch, mode) { - // TODO: record skipped char - } else { - // TODO: record kept char - if ch == '\t' { - // TODO: set "has tab" flag - } - output_text.push(ch); - } - } - false - }, - - CompressionMode::CompressWhitespace | CompressionMode::CompressWhitespaceNewline => { - let mut in_whitespace: bool = incoming_whitespace; - for ch in text.chars() { - // TODO: discard newlines between CJK chars - let mut next_in_whitespace: bool = is_in_whitespace(ch, mode); - - if !next_in_whitespace { - if is_always_discardable_char(ch) { - // revert whitespace setting, since this char was discarded - next_in_whitespace = in_whitespace; - // TODO: record skipped char - } else { - // TODO: record kept char - output_text.push(ch); - } - } else { /* next_in_whitespace; possibly add a space char */ - if in_whitespace { - // TODO: record skipped char - } else { - // TODO: record kept char - output_text.push(' '); - } - } - // save whitespace context for next char - in_whitespace = next_in_whitespace; - } /* /for str::each_char */ - in_whitespace - } - }; - - return out_whitespace; - - fn is_in_whitespace(ch: char, mode: CompressionMode) -> bool { - match (ch, mode) { - (' ', _) => true, - ('\t', _) => true, - ('\n', CompressionMode::CompressWhitespaceNewline) => true, - (_, _) => false - } - } - - fn is_discardable_char(ch: char, mode: CompressionMode) -> bool { - if is_always_discardable_char(ch) { - return true; - } - match mode { - CompressionMode::DiscardNewline | CompressionMode::CompressWhitespaceNewline => ch == '\n', - _ => false - } - } - - fn is_always_discardable_char(ch: char) -> bool { - // TODO: check for soft hyphens. - is_bidi_control(ch) - } -} - -pub fn float_to_fixed(before: usize, f: f64) -> i32 { - ((1i32 << before) as f64 * f) as i32 -} - -pub fn fixed_to_float(before: usize, f: i32) -> f64 { - f as f64 * 1.0f64 / ((1i32 << before) as f64) -} - -pub fn is_bidi_control(c: char) -> bool { - match c { - '\u{202A}'...'\u{202E}' => true, - '\u{2066}'...'\u{2069}' => true, - '\u{200E}' | '\u{200F}' | '\u{061C}' => true, - _ => false - } -} diff --git a/servo/components/gfx_traits/Cargo.toml b/servo/components/gfx_traits/Cargo.toml deleted file mode 100644 index 8d558d19ba0b..000000000000 --- a/servo/components/gfx_traits/Cargo.toml +++ /dev/null @@ -1,16 +0,0 @@ -[package] -name = "gfx_traits" -version = "0.0.1" -authors = ["The Servo Project Developers"] -license = "MPL-2.0" -publish = false - -[lib] -name = "gfx_traits" -path = "lib.rs" - -[dependencies] -malloc_size_of = { path = "../malloc_size_of" } -malloc_size_of_derive = { path = "../malloc_size_of_derive" } -range = {path = "../range"} -serde = "1.0" diff --git a/servo/components/gfx_traits/lib.rs b/servo/components/gfx_traits/lib.rs deleted file mode 100644 index 247396ca04e1..000000000000 --- a/servo/components/gfx_traits/lib.rs +++ /dev/null @@ -1,109 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -#![crate_name = "gfx_traits"] -#![crate_type = "rlib"] - -#![deny(unsafe_code)] - -extern crate malloc_size_of; -#[macro_use] extern crate malloc_size_of_derive; -#[macro_use] extern crate range; -#[macro_use] extern crate serde; - -pub mod print_tree; - -use range::RangeIndex; -use std::sync::atomic::{ATOMIC_USIZE_INIT, AtomicUsize, Ordering}; - -/// A newtype struct for denoting the age of messages; prevents race conditions. -#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, Ord, PartialEq, PartialOrd, Serialize)] -pub struct Epoch(pub u32); - -impl Epoch { - pub fn next(&mut self) { - self.0 += 1; - } -} - -/// A unique ID for every stacking context. -#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, MallocSizeOf, PartialEq, Serialize)] -pub struct StackingContextId( - /// The identifier for this StackingContext, derived from the Flow's memory address - /// and fragment type. As a space optimization, these are combined into a single word. - pub u64 -); - -impl StackingContextId { - /// Returns the stacking context ID for the outer document/layout root. - #[inline] - pub fn root() -> StackingContextId { - StackingContextId(0) - } - - pub fn next(&self) -> StackingContextId { - let StackingContextId(id) = *self; - StackingContextId(id + 1) - } -} - -int_range_index! { - #[derive(Deserialize, Serialize)] - #[doc = "An index that refers to a byte offset in a text run. This could \ - point to the middle of a glyph."] - #[derive(MallocSizeOf)] - struct ByteIndex(isize) -} - -/// The type of fragment that a scroll root is created for. -/// -/// This can only ever grow to maximum 4 entries. That's because we cram the value of this enum -/// into the lower 2 bits of the `ScrollRootId`, which otherwise contains a 32-bit-aligned -/// heap address. -#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, MallocSizeOf, PartialEq, Serialize)] -pub enum FragmentType { - /// A StackingContext for the fragment body itself. - FragmentBody, - /// A StackingContext created to contain ::before pseudo-element content. - BeforePseudoContent, - /// A StackingContext created to contain ::after pseudo-element content. - AfterPseudoContent, -} - -/// The next ID that will be used for a special scroll root id. -/// -/// A special scroll root is a scroll root that is created for generated content. -static NEXT_SPECIAL_SCROLL_ROOT_ID: AtomicUsize = ATOMIC_USIZE_INIT; - -/// If none of the bits outside this mask are set, the scroll root is a special scroll root. -/// Note that we assume that the top 16 bits of the address space are unused on the platform. -const SPECIAL_SCROLL_ROOT_ID_MASK: usize = 0xffff; - -/// Returns a new scroll root ID for a scroll root. -fn next_special_id() -> usize { - // We shift this left by 2 to make room for the fragment type ID. - ((NEXT_SPECIAL_SCROLL_ROOT_ID.fetch_add(1, Ordering::SeqCst) + 1) << 2) & - SPECIAL_SCROLL_ROOT_ID_MASK -} - -pub fn combine_id_with_fragment_type(id: usize, fragment_type: FragmentType) -> usize { - debug_assert_eq!(id & (fragment_type as usize), 0); - if fragment_type == FragmentType::FragmentBody { - id - } else { - next_special_id() | (fragment_type as usize) - } -} - -pub fn node_id_from_scroll_id(id: usize) -> Option { - if (id & !SPECIAL_SCROLL_ROOT_ID_MASK) != 0 { - return Some((id & !3) as usize); - } - None -} - -pub trait DisplayList { - /// Returns true if this display list contains meaningful content. - fn is_contentful(&self) -> bool; -} diff --git a/servo/components/gfx_traits/print_tree.rs b/servo/components/gfx_traits/print_tree.rs deleted file mode 100644 index e347c82bed99..000000000000 --- a/servo/components/gfx_traits/print_tree.rs +++ /dev/null @@ -1,89 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -/// A struct that makes it easier to print out a pretty tree of data, which -/// can be visually scanned more easily. -pub struct PrintTree { - /// The current level of recursion. - level: u32, - - /// An item which is queued up, so that we can determine if we need - /// a mid-tree prefix or a branch ending prefix. - queued_item: Option, -} - -impl PrintTree { - pub fn new(title: String) -> PrintTree { - println!("\u{250c} {}", title); - PrintTree { - level: 1, - queued_item: None, - } - } - - /// Descend one level in the tree with the given title string. - pub fn new_level(&mut self, queued_title: String) { - self.flush_queued_item("\u{251C}\u{2500}"); - - self.print_level_prefix(); - - let items: Vec<&str> = queued_title.split("\n").collect(); - println!("\u{251C}\u{2500} {}", items[0]); - for i in 1..items.len() { - self.print_level_child_indentation(); - print!("{}", items[i]); - if i < items.len() { - print!("\n"); - } - } - - self.level = self.level + 1; - } - - /// Ascend one level in the tree. - pub fn end_level(&mut self) { - self.flush_queued_item("\u{2514}\u{2500}"); - self.level -= 1; - } - - /// Add an item to the current level in the tree. - pub fn add_item(&mut self, text: String) { - self.flush_queued_item("\u{251C}\u{2500}"); - self.queued_item = Some(text); - } - - fn print_level_prefix(&self) { - for _ in 0..self.level { - print!("\u{2502} "); - } - } - - fn print_level_child_indentation(&self) { - for _ in 0..(self.level + 1) { - print!("\u{2502} "); - } - print!("{}", " ".repeat(7)); - } - - fn flush_queued_item(&mut self, prefix: &str) { - if let Some(queued_item) = self.queued_item.take() { - self.print_level_prefix(); - let items: Vec<&str> = queued_item.split("\n").collect(); - println!("{} {}", prefix, items[0]); - for i in 1..items.len() { - self.print_level_child_indentation(); - print!("{}", items[i]); - if i < items.len() { - print!("\n"); - } - } - } - } -} - -impl Drop for PrintTree { - fn drop(&mut self) { - self.flush_queued_item("\u{9492}\u{9472}"); - } -} diff --git a/servo/components/jstraceable_derive/Cargo.toml b/servo/components/jstraceable_derive/Cargo.toml deleted file mode 100644 index 44dbd8ee7164..000000000000 --- a/servo/components/jstraceable_derive/Cargo.toml +++ /dev/null @@ -1,15 +0,0 @@ -[package] -name = "jstraceable_derive" -version = "0.0.1" -authors = ["The Servo Project Developers"] -license = "MPL-2.0" -publish = false - -[lib] -path = "lib.rs" -proc-macro = true - -[dependencies] -quote = "0.4.2" -syn = "0.12.12" -synstructure = "0.7" diff --git a/servo/components/jstraceable_derive/lib.rs b/servo/components/jstraceable_derive/lib.rs deleted file mode 100644 index d90ada8d19d7..000000000000 --- a/servo/components/jstraceable_derive/lib.rs +++ /dev/null @@ -1,40 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -#[macro_use] extern crate quote; -#[macro_use] extern crate syn; -#[macro_use] extern crate synstructure; - -decl_derive!([JSTraceable] => js_traceable_derive); - -fn js_traceable_derive(s: synstructure::Structure) -> quote::Tokens { - let match_body = s.each(|binding| { - Some(quote!(#binding.trace(tracer);)) - }); - - let ast = s.ast(); - let name = ast.ident; - let (impl_generics, ty_generics, where_clause) = ast.generics.split_for_impl(); - let mut where_clause = where_clause.unwrap_or(&parse_quote!(where)).clone(); - for param in ast.generics.type_params() { - let ident = param.ident; - where_clause.predicates.push(parse_quote!(#ident: ::dom::bindings::trace::JSTraceable)) - } - - let tokens = quote! { - #[allow(unsafe_code)] - unsafe impl #impl_generics ::dom::bindings::trace::JSTraceable for #name #ty_generics #where_clause { - #[inline] - #[allow(unused_variables, unused_imports)] - unsafe fn trace(&self, tracer: *mut ::js::jsapi::JSTracer) { - use ::dom::bindings::trace::JSTraceable; - match *self { - #match_body - } - } - } - }; - - tokens -} diff --git a/servo/components/layout/Cargo.toml b/servo/components/layout/Cargo.toml deleted file mode 100644 index 798f91aa6cda..000000000000 --- a/servo/components/layout/Cargo.toml +++ /dev/null @@ -1,55 +0,0 @@ -[package] -name = "layout" -version = "0.0.1" -authors = ["The Servo Project Developers"] -license = "MPL-2.0" -publish = false - -[lib] -name = "layout" -path = "lib.rs" -test = false -doctest = false - -[dependencies] -app_units = "0.6.1" -atomic_refcell = "0.1" -bitflags = "1.0" -canvas_traits = {path = "../canvas_traits"} -euclid = "0.17" -fnv = "1.0" -gfx = {path = "../gfx"} -gfx_traits = {path = "../gfx_traits"} -html5ever = "0.22" -ipc-channel = "0.10" -libc = "0.2" -log = "0.4" -malloc_size_of = { path = "../malloc_size_of" } -msg = {path = "../msg"} -net_traits = {path = "../net_traits"} -ordered-float = "0.4" -parking_lot = "0.5" -profile_traits = {path = "../profile_traits"} -range = {path = "../range"} -rayon = "1" -script_layout_interface = {path = "../script_layout_interface"} -script_traits = {path = "../script_traits"} -selectors = { path = "../selectors" } -serde = "1.0" -servo_arc = {path = "../servo_arc"} -servo_atoms = {path = "../atoms"} -servo_geometry = {path = "../geometry"} -serde_json = "1.0" -servo_config = {path = "../config"} -servo_url = {path = "../url"} -smallvec = "0.6" -style = {path = "../style", features = ["servo"]} -style_traits = {path = "../style_traits"} -unicode-bidi = {version = "0.3", features = ["with_serde"]} -unicode-script = {version = "0.1", features = ["harfbuzz"]} -webrender_api = {git = "https://github.com/servo/webrender", features = ["ipc"]} -xi-unicode = "0.1.0" - -[dev-dependencies] -size_of_test = {path = "../size_of_test"} - diff --git a/servo/components/layout/animation.rs b/servo/components/layout/animation.rs deleted file mode 100644 index b3416984f101..000000000000 --- a/servo/components/layout/animation.rs +++ /dev/null @@ -1,187 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -//! CSS transitions and animations. - -use context::LayoutContext; -use flow::{Flow, GetBaseFlow}; -use fnv::FnvHashMap; -use gfx::display_list::OpaqueNode; -use ipc_channel::ipc::IpcSender; -use msg::constellation_msg::PipelineId; -use opaque_node::OpaqueNodeMethods; -use script_traits::{AnimationState, ConstellationControlMsg, LayoutMsg as ConstellationMsg}; -use script_traits::UntrustedNodeAddress; -use std::sync::mpsc::Receiver; -use style::animation::{Animation, update_style_for_animation}; -use style::dom::TElement; -use style::font_metrics::ServoMetricsProvider; -use style::selector_parser::RestyleDamage; -use style::timer::Timer; - -/// Processes any new animations that were discovered after style recalculation. -/// Also expire any old animations that have completed, inserting them into -/// `expired_animations`. -pub fn update_animation_state( - constellation_chan: &IpcSender, - script_chan: &IpcSender, - running_animations: &mut FnvHashMap>, - expired_animations: &mut FnvHashMap>, - mut newly_transitioning_nodes: Option<&mut Vec>, - new_animations_receiver: &Receiver, - pipeline_id: PipelineId, - timer: &Timer, -) -where - E: TElement, -{ - let mut new_running_animations = vec![]; - while let Ok(animation) = new_animations_receiver.try_recv() { - let mut should_push = true; - if let Animation::Keyframes(ref node, _, ref name, ref state) = animation { - // If the animation was already present in the list for the - // node, just update its state, else push the new animation to - // run. - if let Some(ref mut animations) = running_animations.get_mut(node) { - // TODO: This being linear is probably not optimal. - for anim in animations.iter_mut() { - if let Animation::Keyframes(_, _, ref anim_name, ref mut anim_state) = *anim { - if *name == *anim_name { - debug!("update_animation_state: Found other animation {}", name); - anim_state.update_from_other(&state, timer); - should_push = false; - break; - } - } - } - } - } - - if should_push { - new_running_animations.push(animation); - } - } - - if running_animations.is_empty() && new_running_animations.is_empty() { - // Nothing to do. Return early so we don't flood the compositor with - // `ChangeRunningAnimationsState` messages. - return - } - - let now = timer.seconds(); - // Expire old running animations. - // - // TODO: Do not expunge Keyframes animations, since we need that state if - // the animation gets re-triggered. Probably worth splitting in two - // different maps, or at least using a linked list? - let mut keys_to_remove = vec![]; - for (key, running_animations) in running_animations.iter_mut() { - let mut animations_still_running = vec![]; - for mut running_animation in running_animations.drain(..) { - let still_running = !running_animation.is_expired() && match running_animation { - Animation::Transition(_, started_at, ref frame, _expired) => { - now < started_at + frame.duration - } - Animation::Keyframes(_, _, _, ref mut state) => { - // This animation is still running, or we need to keep - // iterating. - now < state.started_at + state.duration || state.tick() - } - }; - - if still_running { - animations_still_running.push(running_animation); - continue - } - - if let Animation::Transition(node, _, ref frame, _) = running_animation { - script_chan.send(ConstellationControlMsg::TransitionEnd(node.to_untrusted_node_address(), - frame.property_animation - .property_name().into(), - frame.duration)) - .unwrap(); - } - - expired_animations.entry(*key) - .or_insert_with(Vec::new) - .push(running_animation); - } - - if animations_still_running.is_empty() { - keys_to_remove.push(*key); - } else { - *running_animations = animations_still_running - } - } - - for key in keys_to_remove { - running_animations.remove(&key).unwrap(); - } - - // Add new running animations. - for new_running_animation in new_running_animations { - if new_running_animation.is_transition() { - match newly_transitioning_nodes { - Some(ref mut nodes) => { - nodes.push(new_running_animation.node().to_untrusted_node_address()); - } - None => { - warn!("New transition encountered from compositor-initiated layout."); - } - } - } - - running_animations.entry(*new_running_animation.node()) - .or_insert_with(Vec::new) - .push(new_running_animation) - } - - let animation_state = if running_animations.is_empty() { - AnimationState::NoAnimationsPresent - } else { - AnimationState::AnimationsPresent - }; - - constellation_chan.send(ConstellationMsg::ChangeRunningAnimationsState(pipeline_id, - animation_state)) - .unwrap(); -} - -/// Recalculates style for a set of animations. This does *not* run with the DOM -/// lock held. -pub fn recalc_style_for_animations( - context: &LayoutContext, - flow: &mut Flow, - animations: &FnvHashMap>, -) -where - E: TElement, -{ - let mut damage = RestyleDamage::empty(); - flow.mutate_fragments(&mut |fragment| { - if let Some(ref animations) = animations.get(&fragment.node) { - for animation in animations.iter() { - let old_style = fragment.style.clone(); - update_style_for_animation::( - &context.style_context, - animation, - &mut fragment.style, - &ServoMetricsProvider, - ); - let difference = - RestyleDamage::compute_style_difference( - &old_style, - &fragment.style, - ); - damage |= difference.damage; - } - } - }); - - let base = flow.mut_base(); - base.restyle_damage.insert(damage); - for kid in base.children.iter_mut() { - recalc_style_for_animations::(context, kid, animations) - } -} diff --git a/servo/components/layout/block.rs b/servo/components/layout/block.rs deleted file mode 100644 index 225def736779..000000000000 --- a/servo/components/layout/block.rs +++ /dev/null @@ -1,3111 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -//! Layout for CSS block-level elements. -//! -//! As a terminology note, the term *absolute positioning* here refers to elements with position -//! `absolute` or `fixed`. The term *positioned element* refers to elements with position -//! `relative`, `absolute`, and `fixed`. The term *containing block* (occasionally abbreviated as -//! *CB*) is the containing block for the current flow, which differs from the static containing -//! block if the flow is absolutely-positioned. -//! -//! "CSS 2.1" or "CSS 2.2" refers to the editor's draft of the W3C "Cascading Style Sheets Level 2 -//! Revision 2 (CSS 2.2) Specification" available here: -//! -//! http://dev.w3.org/csswg/css2/ -//! -//! "INTRINSIC" refers to L. David Baron's "More Precise Definitions of Inline Layout and Table -//! Layout" available here: -//! -//! http://dbaron.org/css/intrinsic/ -//! -//! "CSS-SIZING" refers to the W3C "CSS Intrinsic & Extrinsic Sizing Module Level 3" document -//! available here: -//! -//! http://dev.w3.org/csswg/css-sizing/ - -#![deny(unsafe_code)] - -use app_units::{Au, MAX_AU}; -use context::LayoutContext; -use display_list::{BlockFlowDisplayListBuilding, BorderPaintingMode}; -use display_list::{DisplayListBuildState, StackingContextCollectionFlags}; -use display_list::StackingContextCollectionState; -use euclid::{Point2D, Rect, SideOffsets2D, Size2D}; -use floats::{ClearType, FloatKind, Floats, PlacementInfo}; -use flow::{BaseFlow, EarlyAbsolutePositionInfo, Flow, FlowClass, ForceNonfloatedFlag, GetBaseFlow}; -use flow::{ImmutableFlowUtils, LateAbsolutePositionInfo, OpaqueFlow, FragmentationContext, FlowFlags}; -use flow_list::FlowList; -use fragment::{CoordinateSystem, Fragment, FragmentBorderBoxIterator, Overflow, FragmentFlags}; -use gfx::display_list::DisplayListSection; -use gfx_traits::print_tree::PrintTree; -use incremental::RelayoutMode; -use layout_debug; -use model::{AdjoiningMargins, CollapsibleMargins, IntrinsicISizes, MarginCollapseInfo, MaybeAuto}; -use sequential; -use serde::{Serialize, Serializer}; -use servo_geometry::MaxRect; -use std::cmp::{max, min}; -use std::fmt; -use std::sync::Arc; -use style::computed_values::box_sizing::T as BoxSizing; -use style::computed_values::display::T as Display; -use style::computed_values::float::T as Float; -use style::computed_values::overflow_x::T as StyleOverflow; -use style::computed_values::position::T as Position; -use style::computed_values::text_align::T as TextAlign; -use style::context::SharedStyleContext; -use style::logical_geometry::{LogicalMargin, LogicalPoint, LogicalRect, LogicalSize, WritingMode}; -use style::properties::ComputedValues; -use style::servo::restyle_damage::ServoRestyleDamage; -use style::values::computed::{LengthOrPercentageOrNone, LengthOrPercentage}; -use style::values::computed::LengthOrPercentageOrAuto; -use traversal::PreorderFlowTraversal; - -/// Information specific to floated blocks. -#[derive(Clone, Serialize)] -pub struct FloatedBlockInfo { - /// The amount of inline size that is available for the float. - pub containing_inline_size: Au, - - /// The float ceiling, relative to `BaseFlow::position::cur_b` (i.e. the top part of the border - /// box). - pub float_ceiling: Au, - - /// Left or right? - pub float_kind: FloatKind, -} - -impl FloatedBlockInfo { - pub fn new(float_kind: FloatKind) -> FloatedBlockInfo { - FloatedBlockInfo { - containing_inline_size: Au(0), - float_ceiling: Au(0), - float_kind: float_kind, - } - } -} - -/// The solutions for the block-size-and-margins constraint equation. -#[derive(Clone, Copy)] -struct BSizeConstraintSolution { - block_start: Au, - block_size: Au, - margin_block_start: Au, - margin_block_end: Au -} - -impl BSizeConstraintSolution { - fn new(block_start: Au, - block_size: Au, - margin_block_start: Au, - margin_block_end: Au) - -> BSizeConstraintSolution { - BSizeConstraintSolution { - block_start: block_start, - block_size: block_size, - margin_block_start: margin_block_start, - margin_block_end: margin_block_end, - } - } - - /// Solve the vertical constraint equation for absolute non-replaced elements. - /// - /// CSS Section 10.6.4 - /// Constraint equation: - /// block-start + block-end + block-size + margin-block-start + margin-block-end - /// = absolute containing block block-size - (vertical padding and border) - /// [aka available_block-size] - /// - /// Return the solution for the equation. - fn solve_vertical_constraints_abs_nonreplaced(block_size: MaybeAuto, - block_start_margin: MaybeAuto, - block_end_margin: MaybeAuto, - block_start: MaybeAuto, - block_end: MaybeAuto, - content_block_size: Au, - available_block_size: Au) - -> BSizeConstraintSolution { - let (block_start, block_size, margin_block_start, margin_block_end) = - match (block_start, block_end, block_size) { - (MaybeAuto::Auto, MaybeAuto::Auto, MaybeAuto::Auto) => { - let margin_block_start = block_start_margin.specified_or_zero(); - let margin_block_end = block_end_margin.specified_or_zero(); - // Now it is the same situation as block-start Specified and block-end - // and block-size Auto. - let block_size = content_block_size; - // Use a dummy value for `block_start`, since it has the static position. - (Au(0), block_size, margin_block_start, margin_block_end) - } - (MaybeAuto::Specified(block_start), - MaybeAuto::Specified(block_end), - MaybeAuto::Specified(block_size)) => { - match (block_start_margin, block_end_margin) { - (MaybeAuto::Auto, MaybeAuto::Auto) => { - let total_margin_val = - available_block_size - block_start - block_end - block_size; - (block_start, - block_size, - total_margin_val.scale_by(0.5), - total_margin_val.scale_by(0.5)) - } - (MaybeAuto::Specified(margin_block_start), MaybeAuto::Auto) => { - let sum = block_start + block_end + block_size + margin_block_start; - (block_start, - block_size, - margin_block_start, - available_block_size - sum) - } - (MaybeAuto::Auto, MaybeAuto::Specified(margin_block_end)) => { - let sum = block_start + block_end + block_size + margin_block_end; - (block_start, block_size, available_block_size - sum, margin_block_end) - } - (MaybeAuto::Specified(margin_block_start), - MaybeAuto::Specified(margin_block_end)) => { - // Values are over-constrained. Ignore value for 'block-end'. - (block_start, block_size, margin_block_start, margin_block_end) - } - } - } - - // For the rest of the cases, auto values for margin are set to 0 - - // If only one is Auto, solve for it - (MaybeAuto::Auto, - MaybeAuto::Specified(block_end), - MaybeAuto::Specified(block_size)) => { - let margin_block_start = block_start_margin.specified_or_zero(); - let margin_block_end = block_end_margin.specified_or_zero(); - let sum = block_end + block_size + margin_block_start + margin_block_end; - (available_block_size - sum, block_size, margin_block_start, margin_block_end) - } - (MaybeAuto::Specified(block_start), - MaybeAuto::Auto, - MaybeAuto::Specified(block_size)) => { - let margin_block_start = block_start_margin.specified_or_zero(); - let margin_block_end = block_end_margin.specified_or_zero(); - (block_start, block_size, margin_block_start, margin_block_end) - } - (MaybeAuto::Specified(block_start), - MaybeAuto::Specified(block_end), - MaybeAuto::Auto) => { - let margin_block_start = block_start_margin.specified_or_zero(); - let margin_block_end = block_end_margin.specified_or_zero(); - let sum = block_start + block_end + margin_block_start + margin_block_end; - (block_start, available_block_size - sum, margin_block_start, margin_block_end) - } - - // If block-size is auto, then block-size is content block-size. Solve for the - // non-auto value. - (MaybeAuto::Specified(block_start), MaybeAuto::Auto, MaybeAuto::Auto) => { - let margin_block_start = block_start_margin.specified_or_zero(); - let margin_block_end = block_end_margin.specified_or_zero(); - let block_size = content_block_size; - (block_start, block_size, margin_block_start, margin_block_end) - } - (MaybeAuto::Auto, MaybeAuto::Specified(block_end), MaybeAuto::Auto) => { - let margin_block_start = block_start_margin.specified_or_zero(); - let margin_block_end = block_end_margin.specified_or_zero(); - let block_size = content_block_size; - let sum = block_end + block_size + margin_block_start + margin_block_end; - (available_block_size - sum, block_size, margin_block_start, margin_block_end) - } - - (MaybeAuto::Auto, MaybeAuto::Auto, MaybeAuto::Specified(block_size)) => { - let margin_block_start = block_start_margin.specified_or_zero(); - let margin_block_end = block_end_margin.specified_or_zero(); - // Use a dummy value for `block_start`, since it has the static position. - (Au(0), block_size, margin_block_start, margin_block_end) - } - }; - - BSizeConstraintSolution::new(block_start, block_size, margin_block_start, margin_block_end) - } - - /// Solve the vertical constraint equation for absolute replaced elements. - /// - /// Assumption: The used value for block-size has already been calculated. - /// - /// CSS Section 10.6.5 - /// Constraint equation: - /// block-start + block-end + block-size + margin-block-start + margin-block-end - /// = absolute containing block block-size - (vertical padding and border) - /// [aka available block-size] - /// - /// Return the solution for the equation. - fn solve_vertical_constraints_abs_replaced(block_size: Au, - block_start_margin: MaybeAuto, - block_end_margin: MaybeAuto, - block_start: MaybeAuto, - block_end: MaybeAuto, - _: Au, - available_block_size: Au) - -> BSizeConstraintSolution { - let (block_start, block_size, margin_block_start, margin_block_end) = - match (block_start, block_end) { - (MaybeAuto::Auto, MaybeAuto::Auto) => { - let margin_block_start = block_start_margin.specified_or_zero(); - let margin_block_end = block_end_margin.specified_or_zero(); - // Use a dummy value for `block_start`, since it has the static position. - (Au(0), block_size, margin_block_start, margin_block_end) - } - (MaybeAuto::Specified(block_start), MaybeAuto::Specified(block_end)) => { - match (block_start_margin, block_end_margin) { - (MaybeAuto::Auto, MaybeAuto::Auto) => { - let total_margin_val = available_block_size - block_start - block_end - - block_size; - (block_start, - block_size, - total_margin_val.scale_by(0.5), - total_margin_val.scale_by(0.5)) - } - (MaybeAuto::Specified(margin_block_start), MaybeAuto::Auto) => { - let sum = block_start + block_end + block_size + margin_block_start; - (block_start, - block_size, - margin_block_start, - available_block_size - sum) - } - (MaybeAuto::Auto, MaybeAuto::Specified(margin_block_end)) => { - let sum = block_start + block_end + block_size + margin_block_end; - (block_start, block_size, available_block_size - sum, margin_block_end) - } - (MaybeAuto::Specified(margin_block_start), - MaybeAuto::Specified(margin_block_end)) => { - // Values are over-constrained. Ignore value for 'block-end'. - (block_start, block_size, margin_block_start, margin_block_end) - } - } - } - - // If only one is Auto, solve for it - (MaybeAuto::Auto, MaybeAuto::Specified(block_end)) => { - let margin_block_start = block_start_margin.specified_or_zero(); - let margin_block_end = block_end_margin.specified_or_zero(); - let sum = block_end + block_size + margin_block_start + margin_block_end; - (available_block_size - sum, block_size, margin_block_start, margin_block_end) - } - (MaybeAuto::Specified(block_start), MaybeAuto::Auto) => { - let margin_block_start = block_start_margin.specified_or_zero(); - let margin_block_end = block_end_margin.specified_or_zero(); - (block_start, block_size, margin_block_start, margin_block_end) - } - }; - BSizeConstraintSolution::new(block_start, block_size, margin_block_start, margin_block_end) - } -} - -/// Performs block-size calculations potentially multiple times, taking -/// (assuming an horizontal writing mode) `height`, `min-height`, and `max-height` -/// into account. After each call to `next()`, the caller must call `.try()` with the -/// current calculated value of `height`. -/// -/// See CSS 2.1 § 10.7. -pub struct CandidateBSizeIterator { - block_size: MaybeAuto, - max_block_size: Option, - min_block_size: Au, - pub candidate_value: Au, - status: CandidateBSizeIteratorStatus, -} - -impl CandidateBSizeIterator { - /// Creates a new candidate block-size iterator. `block_container_block-size` is `None` if the block-size - /// of the block container has not been determined yet. It will always be `Some` in the case of - /// absolutely-positioned containing blocks. - pub fn new(fragment: &Fragment, block_container_block_size: Option) - -> CandidateBSizeIterator { - // Per CSS 2.1 § 10.7, (assuming an horizontal writing mode,) - // percentages in `min-height` and `max-height` refer to the height of - // the containing block. - // If that is not determined yet by the time we need to resolve - // `min-height` and `max-height`, percentage values are ignored. - - let block_size = match (fragment.style.content_block_size(), block_container_block_size) { - (LengthOrPercentageOrAuto::Percentage(percent), Some(block_container_block_size)) => { - MaybeAuto::Specified(block_container_block_size.scale_by(percent.0)) - } - (LengthOrPercentageOrAuto::Calc(calc), _) => { - MaybeAuto::from_option(calc.to_used_value(block_container_block_size)) - } - (LengthOrPercentageOrAuto::Percentage(_), None) | - (LengthOrPercentageOrAuto::Auto, _) => MaybeAuto::Auto, - (LengthOrPercentageOrAuto::Length(length), _) => MaybeAuto::Specified(Au::from(length)), - }; - let max_block_size = match (fragment.style.max_block_size(), block_container_block_size) { - (LengthOrPercentageOrNone::Percentage(percent), Some(block_container_block_size)) => { - Some(block_container_block_size.scale_by(percent.0)) - } - (LengthOrPercentageOrNone::Calc(calc), _) => { - calc.to_used_value(block_container_block_size) - } - (LengthOrPercentageOrNone::Percentage(_), None) | - (LengthOrPercentageOrNone::None, _) => None, - (LengthOrPercentageOrNone::Length(length), _) => Some(Au::from(length)), - }; - let min_block_size = match (fragment.style.min_block_size(), block_container_block_size) { - (LengthOrPercentage::Percentage(percent), Some(block_container_block_size)) => { - block_container_block_size.scale_by(percent.0) - } - (LengthOrPercentage::Calc(calc), _) => { - calc.to_used_value(block_container_block_size).unwrap_or(Au(0)) - } - (LengthOrPercentage::Percentage(_), None) => Au(0), - (LengthOrPercentage::Length(length), _) => Au::from(length), - }; - - // If the style includes `box-sizing: border-box`, subtract the border and padding. - let adjustment_for_box_sizing = match fragment.style.get_position().box_sizing { - BoxSizing::BorderBox => fragment.border_padding.block_start_end(), - BoxSizing::ContentBox => Au(0), - }; - - return CandidateBSizeIterator { - block_size: block_size.map(|size| adjust(size, adjustment_for_box_sizing)), - max_block_size: max_block_size.map(|size| adjust(size, adjustment_for_box_sizing)), - min_block_size: adjust(min_block_size, adjustment_for_box_sizing), - candidate_value: Au(0), - status: CandidateBSizeIteratorStatus::Initial, - }; - - fn adjust(size: Au, delta: Au) -> Au { - max(size - delta, Au(0)) - } - } -} - -impl Iterator for CandidateBSizeIterator { - type Item = MaybeAuto; - fn next(&mut self) -> Option { - self.status = match self.status { - CandidateBSizeIteratorStatus::Initial => CandidateBSizeIteratorStatus::Trying, - CandidateBSizeIteratorStatus::Trying => { - match self.max_block_size { - Some(max_block_size) if self.candidate_value > max_block_size => { - CandidateBSizeIteratorStatus::TryingMax - } - _ if self.candidate_value < self.min_block_size => { - CandidateBSizeIteratorStatus::TryingMin - } - _ => CandidateBSizeIteratorStatus::Found, - } - } - CandidateBSizeIteratorStatus::TryingMax => { - if self.candidate_value < self.min_block_size { - CandidateBSizeIteratorStatus::TryingMin - } else { - CandidateBSizeIteratorStatus::Found - } - } - CandidateBSizeIteratorStatus::TryingMin | CandidateBSizeIteratorStatus::Found => { - CandidateBSizeIteratorStatus::Found - } - }; - - match self.status { - CandidateBSizeIteratorStatus::Trying => Some(self.block_size), - CandidateBSizeIteratorStatus::TryingMax => { - Some(MaybeAuto::Specified(self.max_block_size.unwrap())) - } - CandidateBSizeIteratorStatus::TryingMin => { - Some(MaybeAuto::Specified(self.min_block_size)) - } - CandidateBSizeIteratorStatus::Found => None, - CandidateBSizeIteratorStatus::Initial => panic!(), - } - } -} - -enum CandidateBSizeIteratorStatus { - Initial, - Trying, - TryingMax, - TryingMin, - Found, -} - -// A helper function used in block-size calculation. -fn translate_including_floats(cur_b: &mut Au, delta: Au, floats: &mut Floats) { - *cur_b = *cur_b + delta; - let writing_mode = floats.writing_mode; - floats.translate(LogicalSize::new(writing_mode, Au(0), -delta)); -} - -/// The real assign-block-sizes traversal for flows with position 'absolute'. -/// -/// This is a traversal of an Absolute Flow tree. -/// - Relatively positioned flows and the Root flow start new Absolute flow trees. -/// - The kids of a flow in this tree will be the flows for which it is the -/// absolute Containing Block. -/// - Thus, leaf nodes and inner non-root nodes are all Absolute Flows. -/// -/// A Flow tree can have several Absolute Flow trees (depending on the number -/// of relatively positioned flows it has). -/// -/// Note that flows with position 'fixed' just form a flat list as they all -/// have the Root flow as their CB. -pub struct AbsoluteAssignBSizesTraversal<'a>(pub &'a SharedStyleContext<'a>); - -impl<'a> PreorderFlowTraversal for AbsoluteAssignBSizesTraversal<'a> { - #[inline] - fn process(&self, flow: &mut Flow) { - if !flow.is_block_like() { - return - } - - // This flow might not be an absolutely positioned flow if it is the root of the tree. - let block = flow.as_mut_block(); - if !block.base.flags.contains(FlowFlags::IS_ABSOLUTELY_POSITIONED) { - return; - } - - if !block.base.restyle_damage.intersects(ServoRestyleDamage::REFLOW_OUT_OF_FLOW | ServoRestyleDamage::REFLOW) { - return - } - - block.calculate_absolute_block_size_and_margins(self.0); - } -} - -pub enum BlockType { - Replaced, - NonReplaced, - AbsoluteReplaced, - AbsoluteNonReplaced, - FloatReplaced, - FloatNonReplaced, - InlineBlockReplaced, - InlineBlockNonReplaced, - InlineFlexItem, -} - -#[derive(Clone, PartialEq)] -pub enum MarginsMayCollapseFlag { - MarginsMayCollapse, - MarginsMayNotCollapse, -} - -#[derive(Debug, PartialEq)] -pub enum FormattingContextType { - None, - Block, - Other, -} - -#[allow(unsafe_code)] -unsafe impl ::flow::HasBaseFlow for BlockFlow {} - -// A block formatting context. -#[derive(Serialize)] -#[repr(C)] -pub struct BlockFlow { - /// Data common to all flows. - pub base: BaseFlow, - - /// The associated fragment. - pub fragment: Fragment, - - /// Additional floating flow members. - pub float: Option>, - - /// Various flags. - flags: BlockFlowFlags, -} - -bitflags! { - struct BlockFlowFlags: u8 { - #[doc = "If this is set, then this block flow is the root flow."] - const IS_ROOT = 0b0000_0001; - #[doc = "If this is set, then this block flow has overflow and it will scroll."] - const HAS_SCROLLING_OVERFLOW = 0b0000_0010; - } -} - -impl Serialize for BlockFlowFlags { - fn serialize(&self, serializer: S) -> Result { - self.bits().serialize(serializer) - } -} - -impl BlockFlow { - pub fn from_fragment(fragment: Fragment) -> BlockFlow { - BlockFlow::from_fragment_and_float_kind(fragment, None) - } - - pub fn from_fragment_and_float_kind(fragment: Fragment, float_kind: Option) - -> BlockFlow { - let writing_mode = fragment.style().writing_mode; - BlockFlow { - base: BaseFlow::new(Some(fragment.style()), writing_mode, match float_kind { - Some(_) => ForceNonfloatedFlag::FloatIfNecessary, - None => ForceNonfloatedFlag::ForceNonfloated, - }), - fragment: fragment, - float: float_kind.map(|kind| Box::new(FloatedBlockInfo::new(kind))), - flags: BlockFlowFlags::empty(), - } - } - - /// Return the type of this block. - /// - /// This determines the algorithm used to calculate inline-size, block-size, and the - /// relevant margins for this Block. - pub fn block_type(&self) -> BlockType { - if self.base.flags.contains(FlowFlags::IS_ABSOLUTELY_POSITIONED) { - if self.fragment.is_replaced() { - BlockType::AbsoluteReplaced - } else { - BlockType::AbsoluteNonReplaced - } - } else if self.is_inline_flex_item() { - BlockType::InlineFlexItem - } else if self.base.flags.is_float() { - if self.fragment.is_replaced() { - BlockType::FloatReplaced - } else { - BlockType::FloatNonReplaced - } - } else if self.is_inline_block_or_inline_flex() { - if self.fragment.is_replaced() { - BlockType::InlineBlockReplaced - } else { - BlockType::InlineBlockNonReplaced - } - } else { - if self.fragment.is_replaced() { - BlockType::Replaced - } else { - BlockType::NonReplaced - } - } - } - - /// Compute the actual inline size and position for this block. - pub fn compute_used_inline_size(&mut self, - shared_context: &SharedStyleContext, - containing_block_inline_size: Au) { - let block_type = self.block_type(); - match block_type { - BlockType::AbsoluteReplaced => { - let inline_size_computer = AbsoluteReplaced; - inline_size_computer.compute_used_inline_size(self, - shared_context, - containing_block_inline_size); - } - BlockType::AbsoluteNonReplaced => { - let inline_size_computer = AbsoluteNonReplaced; - inline_size_computer.compute_used_inline_size(self, - shared_context, - containing_block_inline_size); - } - BlockType::FloatReplaced => { - let inline_size_computer = FloatReplaced; - inline_size_computer.compute_used_inline_size(self, - shared_context, - containing_block_inline_size); - } - BlockType::FloatNonReplaced => { - let inline_size_computer = FloatNonReplaced; - inline_size_computer.compute_used_inline_size(self, - shared_context, - containing_block_inline_size); - } - BlockType::InlineBlockReplaced => { - let inline_size_computer = InlineBlockReplaced; - inline_size_computer.compute_used_inline_size(self, - shared_context, - containing_block_inline_size); - } - BlockType::InlineBlockNonReplaced => { - let inline_size_computer = InlineBlockNonReplaced; - inline_size_computer.compute_used_inline_size(self, - shared_context, - containing_block_inline_size); - } - BlockType::Replaced => { - let inline_size_computer = BlockReplaced; - inline_size_computer.compute_used_inline_size(self, - shared_context, - containing_block_inline_size); - } - BlockType::NonReplaced => { - let inline_size_computer = BlockNonReplaced; - inline_size_computer.compute_used_inline_size(self, - shared_context, - containing_block_inline_size); - } - BlockType::InlineFlexItem => { - let inline_size_computer = InlineFlexItem; - inline_size_computer.compute_used_inline_size(self, - shared_context, - containing_block_inline_size); - } - } - } - - /// Return this flow's fragment. - pub fn fragment(&mut self) -> &mut Fragment { - &mut self.fragment - } - - pub fn stacking_relative_border_box(&self, coor: CoordinateSystem) -> Rect { - return self.fragment.stacking_relative_border_box( - &self.base.stacking_relative_position, - &self.base.early_absolute_position_info.relative_containing_block_size, - self.base.early_absolute_position_info.relative_containing_block_mode, - coor); - } - - /// Return the size of the containing block for the given immediate absolute descendant of this - /// flow. - /// - /// Right now, this only gets the containing block size for absolutely positioned elements. - /// Note: We assume this is called in a top-down traversal, so it is ok to reference the CB. - #[inline] - pub fn containing_block_size(&self, viewport_size: &Size2D, descendant: OpaqueFlow) - -> LogicalSize { - debug_assert!(self.base.flags.contains(FlowFlags::IS_ABSOLUTELY_POSITIONED)); - if self.is_fixed() || self.is_root() { - // Initial containing block is the CB for the root - LogicalSize::from_physical(self.base.writing_mode, *viewport_size) - } else { - self.base.absolute_cb.generated_containing_block_size(descendant) - } - } - - /// Return shrink-to-fit inline-size. - /// - /// This is where we use the preferred inline-sizes and minimum inline-sizes - /// calculated in the bubble-inline-sizes traversal. - pub fn get_shrink_to_fit_inline_size(&self, available_inline_size: Au) -> Au { - let content_intrinsic_inline_sizes = self.content_intrinsic_inline_sizes(); - min(content_intrinsic_inline_sizes.preferred_inline_size, - max(content_intrinsic_inline_sizes.minimum_inline_size, available_inline_size)) - } - - /// If this is the root flow, shifts all kids down and adjusts our size to account for - /// root flow margins, which should never be collapsed according to CSS § 8.3.1. - /// - /// TODO(#2017, pcwalton): This is somewhat inefficient (traverses kids twice); can we do - /// better? - fn adjust_fragments_for_collapsed_margins_if_root(&mut self, - shared_context: &SharedStyleContext) { - if !self.is_root() { - return - } - - let (block_start_margin_value, block_end_margin_value) = - match self.base.collapsible_margins { - CollapsibleMargins::CollapseThrough(_) => { - panic!("Margins unexpectedly collapsed through root flow.") - } - CollapsibleMargins::Collapse(block_start_margin, block_end_margin) => { - (block_start_margin.collapse(), block_end_margin.collapse()) - } - CollapsibleMargins::None(block_start, block_end) => (block_start, block_end), - }; - - // Shift all kids down (or up, if margins are negative) if necessary. - if block_start_margin_value != Au(0) { - for kid in self.base.child_iter_mut() { - let kid_base = kid.mut_base(); - kid_base.position.start.b = kid_base.position.start.b + block_start_margin_value - } - } - - // FIXME(#2003, pcwalton): The max is taken here so that you can scroll the page, but this - // is not correct behavior according to CSS 2.1 § 10.5. Instead I think we should treat the - // root element as having `overflow: scroll` and use the layers-based scrolling - // infrastructure to make it scrollable. - let viewport_size = - LogicalSize::from_physical(self.fragment.style.writing_mode, - shared_context.viewport_size()); - let block_size = max(viewport_size.block, - self.fragment.border_box.size.block + block_start_margin_value + - block_end_margin_value); - - self.base.position.size.block = block_size; - self.fragment.border_box.size.block = block_size; - } - - // FIXME: Record enough info to deal with fragmented decorations. - // See https://drafts.csswg.org/css-break/#break-decoration - // For borders, this might be `enum FragmentPosition { First, Middle, Last }` - fn clone_with_children(&self, new_children: FlowList) -> BlockFlow { - BlockFlow { - base: self.base.clone_with_children(new_children), - fragment: self.fragment.clone(), - float: self.float.clone(), - ..*self - } - } - - /// Writes in the size of the relative containing block for children. (This information - /// is also needed to handle RTL.) - fn propagate_early_absolute_position_info_to_children(&mut self) { - for kid in self.base.child_iter_mut() { - kid.mut_base().early_absolute_position_info = EarlyAbsolutePositionInfo { - relative_containing_block_size: self.fragment.content_box().size, - relative_containing_block_mode: self.fragment.style().writing_mode, - } - } - } - - /// Assign block-size for current flow. - /// - /// * Collapse margins for flow's children and set in-flow child flows' block offsets now that - /// we know their block-sizes. - /// * Calculate and set the block-size of the current flow. - /// * Calculate block-size, vertical margins, and block offset for the flow's box using CSS § - /// 10.6.7. - /// - /// For absolute flows, we store the calculated content block-size for the flow. We defer the - /// calculation of the other values until a later traversal. - /// - /// When `fragmentation_context` is given (not `None`), this should fit as much of the content - /// as possible within the available block size. - /// If there is more content (that doesn’t fit), this flow is *fragmented* - /// with the extra content moved to another fragment (a flow like this one) which is returned. - /// See `Flow::fragment`. - /// - /// The return value is always `None` when `fragmentation_context` is `None`. - /// - /// `inline(always)` because this is only ever called by in-order or non-in-order top-level - /// methods. - #[inline(always)] - pub fn assign_block_size_block_base(&mut self, - layout_context: &LayoutContext, - mut fragmentation_context: Option, - margins_may_collapse: MarginsMayCollapseFlag) - -> Option> { - let _scope = layout_debug_scope!("assign_block_size_block_base {:x}", - self.base.debug_id()); - - let mut break_at = None; - let content_box = self.fragment.content_box(); - if self.base.restyle_damage.contains(ServoRestyleDamage::REFLOW) { - // Our current border-box position. - let mut cur_b = Au(0); - - // Absolute positioning establishes a block formatting context. Don't propagate floats - // in or out. (But do propagate them between kids.) - if self.base.flags.contains(FlowFlags::IS_ABSOLUTELY_POSITIONED) || - margins_may_collapse != MarginsMayCollapseFlag::MarginsMayCollapse { - self.base.floats = Floats::new(self.fragment.style.writing_mode); - } - - let writing_mode = self.base.floats.writing_mode; - self.base.floats.translate(LogicalSize::new( - writing_mode, -self.fragment.inline_start_offset(), Au(0))); - - // The sum of our block-start border and block-start padding. - let block_start_offset = self.fragment.border_padding.block_start; - translate_including_floats(&mut cur_b, block_start_offset, &mut self.base.floats); - - let can_collapse_block_start_margin_with_kids = - margins_may_collapse == MarginsMayCollapseFlag::MarginsMayCollapse && - !self.base.flags.contains(FlowFlags::IS_ABSOLUTELY_POSITIONED) && - self.fragment.border_padding.block_start == Au(0); - let mut margin_collapse_info = MarginCollapseInfo::initialize_block_start_margin( - &self.fragment, - can_collapse_block_start_margin_with_kids); - - // At this point, `cur_b` is at the content edge of our box. Now iterate over children. - let mut floats = self.base.floats.clone(); - let thread_id = self.base.thread_id; - let (mut had_floated_children, mut had_children_with_clearance) = (false, false); - for (child_index, kid) in self.base.child_iter_mut().enumerate() { - if kid.base().flags.contains(FlowFlags::IS_ABSOLUTELY_POSITIONED) { - // Assume that the *hypothetical box* for an absolute flow starts immediately - // after the margin-end border edge of the previous flow. - if kid.base().flags.contains(FlowFlags::BLOCK_POSITION_IS_STATIC) { - let previous_bottom_margin = margin_collapse_info.current_float_ceiling(); - - kid.mut_base().position.start.b = cur_b + - kid.base().collapsible_margins - .block_start_margin_for_noncollapsible_context() + - previous_bottom_margin - } - kid.place_float_if_applicable(); - if !kid.base().flags.is_float() { - kid.assign_block_size_for_inorder_child_if_necessary(layout_context, - thread_id, - content_box); - } - - // Skip the collapsing and float processing for absolute flow kids and continue - // with the next flow. - continue - } - - let previous_b = cur_b; - if let Some(ctx) = fragmentation_context { - let child_ctx = FragmentationContext { - available_block_size: ctx.available_block_size - cur_b, - this_fragment_is_empty: ctx.this_fragment_is_empty, - }; - if let Some(remaining) = kid.fragment(layout_context, Some(child_ctx)) { - break_at = Some((child_index + 1, Some(remaining))); - } - } - - // Assign block-size now for the child if it might have floats in and we couldn't - // before. - kid.mut_base().floats = floats.clone(); - if kid.base().flags.is_float() { - had_floated_children = true; - kid.mut_base().position.start.b = cur_b; - { - let kid_block = kid.as_mut_block(); - let float_ceiling = margin_collapse_info.current_float_ceiling(); - kid_block.float.as_mut().unwrap().float_ceiling = float_ceiling - } - kid.place_float_if_applicable(); - - let kid_base = kid.mut_base(); - floats = kid_base.floats.clone(); - continue - } - - // If we have clearance, assume there are no floats in. - // - // FIXME(#2008, pcwalton): This could be wrong if we have `clear: left` or `clear: - // right` and there are still floats to impact, of course. But this gets - // complicated with margin collapse. Possibly the right thing to do is to lay out - // the block again in this rare case. (Note that WebKit can lay blocks out twice; - // this may be related, although I haven't looked into it closely.) - if kid.base().flags.clears_floats() { - kid.mut_base().floats = Floats::new(self.fragment.style.writing_mode) - } - - // Lay the child out if this was an in-order traversal. - let need_to_process_child_floats = - kid.assign_block_size_for_inorder_child_if_necessary(layout_context, - thread_id, - content_box); - - if !had_children_with_clearance && - floats.is_present() && - (kid.base().flags.contains(FlowFlags::CLEARS_LEFT) || - kid.base().flags.contains(FlowFlags::CLEARS_RIGHT)) { - had_children_with_clearance = true - } - - // Handle any (possibly collapsed) top margin. - let delta = margin_collapse_info.advance_block_start_margin( - &kid.base().collapsible_margins, - !had_children_with_clearance); - translate_including_floats(&mut cur_b, delta, &mut floats); - - // Collapse-through margins should be placed at the top edge, - // so we'll handle the delta after the bottom margin is processed - if let CollapsibleMargins::CollapseThrough(_) = kid.base().collapsible_margins { - cur_b = cur_b - delta; - } - - // Clear past the floats that came in, if necessary. - let clearance = match (kid.base().flags.contains(FlowFlags::CLEARS_LEFT), - kid.base().flags.contains(FlowFlags::CLEARS_RIGHT)) { - (false, false) => Au(0), - (true, false) => floats.clearance(ClearType::Left), - (false, true) => floats.clearance(ClearType::Right), - (true, true) => floats.clearance(ClearType::Both), - }; - translate_including_floats(&mut cur_b, clearance, &mut floats); - - // At this point, `cur_b` is at the border edge of the child. - kid.mut_base().position.start.b = cur_b; - - // Now pull out the child's outgoing floats. We didn't do this immediately after - // the `assign_block_size_for_inorder_child_if_necessary` call because clearance on - // a block operates on the floats that come *in*, not the floats that go *out*. - if need_to_process_child_floats { - floats = kid.mut_base().floats.clone() - } - - // Move past the child's border box. Do not use the `translate_including_floats` - // function here because the child has already translated floats past its border - // box. - let kid_base = kid.mut_base(); - cur_b = cur_b + kid_base.position.size.block; - - // Handle any (possibly collapsed) block-end margin. - let delta = - margin_collapse_info.advance_block_end_margin(&kid_base.collapsible_margins); - translate_including_floats(&mut cur_b, delta, &mut floats); - - // Collapse-through margin should be placed at the top edge of the flow. - let collapse_delta = match kid_base.collapsible_margins { - CollapsibleMargins::CollapseThrough(_) => { - let delta = margin_collapse_info.current_float_ceiling(); - cur_b = cur_b + delta; - kid_base.position.start.b = kid_base.position.start.b + delta; - delta - } - _ => Au(0) - }; - - if break_at.is_some() { - break - } - - if let Some(ref mut ctx) = fragmentation_context { - if cur_b > ctx.available_block_size && !ctx.this_fragment_is_empty { - break_at = Some((child_index, None)); - cur_b = previous_b; - break - } - ctx.this_fragment_is_empty = false - } - - // For consecutive collapse-through flows, their top margin should be calculated - // from the same baseline. - cur_b = cur_b - collapse_delta; - } - - // Add in our block-end margin and compute our collapsible margins. - let can_collapse_block_end_margin_with_kids = - margins_may_collapse == MarginsMayCollapseFlag::MarginsMayCollapse && - !self.base.flags.contains(FlowFlags::IS_ABSOLUTELY_POSITIONED) && - self.fragment.border_padding.block_end == Au(0); - let (collapsible_margins, delta) = - margin_collapse_info.finish_and_compute_collapsible_margins( - &self.fragment, - self.base.block_container_explicit_block_size, - can_collapse_block_end_margin_with_kids, - !had_floated_children); - self.base.collapsible_margins = collapsible_margins; - translate_including_floats(&mut cur_b, delta, &mut floats); - - let mut block_size = cur_b - block_start_offset; - let is_root = self.is_root(); - - if is_root || self.formatting_context_type() != FormattingContextType::None || - self.base.flags.contains(FlowFlags::IS_ABSOLUTELY_POSITIONED) { - // The content block-size includes all the floats per CSS 2.1 § 10.6.7. The easiest - // way to handle this is to just treat it as clearance. - block_size = block_size + floats.clearance(ClearType::Both); - } - - if self.base.flags.contains(FlowFlags::IS_ABSOLUTELY_POSITIONED) { - // FIXME(#2003, pcwalton): The max is taken here so that you can scroll the page, - // but this is not correct behavior according to CSS 2.1 § 10.5. Instead I think we - // should treat the root element as having `overflow: scroll` and use the layers- - // based scrolling infrastructure to make it scrollable. - if is_root { - let viewport_size = - LogicalSize::from_physical(self.fragment.style.writing_mode, - layout_context.shared_context().viewport_size()); - block_size = max(viewport_size.block, block_size) - } - - // Store the content block-size for use in calculating the absolute flow's - // dimensions later. - // - // FIXME(pcwalton): This looks not idempotent. Is it? - self.fragment.border_box.size.block = block_size; - } - - - if self.base.flags.contains(FlowFlags::IS_ABSOLUTELY_POSITIONED) { - self.propagate_early_absolute_position_info_to_children(); - return None - } - - // Compute any explicitly-specified block size. - // Can't use `for` because we assign to `candidate_block_size_iterator.candidate_value`. - let mut candidate_block_size_iterator = CandidateBSizeIterator::new( - &self.fragment, - self.base.block_container_explicit_block_size); - while let Some(candidate_block_size) = candidate_block_size_iterator.next() { - candidate_block_size_iterator.candidate_value = - match candidate_block_size { - MaybeAuto::Auto => block_size, - MaybeAuto::Specified(value) => value - } - } - - // Adjust `cur_b` as necessary to account for the explicitly-specified block-size. - block_size = candidate_block_size_iterator.candidate_value; - let delta = block_size - (cur_b - block_start_offset); - translate_including_floats(&mut cur_b, delta, &mut floats); - - // Take border and padding into account. - let block_end_offset = self.fragment.border_padding.block_end; - translate_including_floats(&mut cur_b, block_end_offset, &mut floats); - - // Now that `cur_b` is at the block-end of the border box, compute the final border box - // position. - self.fragment.border_box.size.block = cur_b; - self.fragment.border_box.start.b = Au(0); - self.base.position.size.block = cur_b; - - self.propagate_early_absolute_position_info_to_children(); - - // Translate the current set of floats back into the parent coordinate system in the - // inline direction, and store them in the flow so that flows that come later in the - // document can access them. - floats.translate(LogicalSize::new(writing_mode, - self.fragment.inline_start_offset(), - Au(0))); - self.base.floats = floats.clone(); - self.adjust_fragments_for_collapsed_margins_if_root(layout_context.shared_context()); - } else { - // We don't need to reflow, but we still need to perform in-order traversals if - // necessary. - let thread_id = self.base.thread_id; - for kid in self.base.child_iter_mut() { - kid.assign_block_size_for_inorder_child_if_necessary(layout_context, - thread_id, - content_box); - } - } - - if (&*self as &Flow).contains_roots_of_absolute_flow_tree() { - // Assign block-sizes for all flows in this absolute flow tree. - // This is preorder because the block-size of an absolute flow may depend on - // the block-size of its containing block, which may also be an absolute flow. - let assign_abs_b_sizes = AbsoluteAssignBSizesTraversal(layout_context.shared_context()); - assign_abs_b_sizes.traverse_absolute_flows(&mut *self); - } - - // Don't remove the dirty bits yet if we're absolutely-positioned, since our final size - // has not been calculated yet. (See `calculate_absolute_block_size_and_margins` for that.) - // Also don't remove the dirty bits if we're a block formatting context since our inline - // size has not yet been computed. (See `assign_inline_position_for_formatting_context()`.) - if (self.base.flags.is_float() || - self.formatting_context_type() == FormattingContextType::None) && - !self.base.flags.contains(FlowFlags::IS_ABSOLUTELY_POSITIONED) { - self.base.restyle_damage.remove(ServoRestyleDamage::REFLOW_OUT_OF_FLOW | ServoRestyleDamage::REFLOW); - self.fragment.restyle_damage.remove(ServoRestyleDamage::REFLOW_OUT_OF_FLOW | ServoRestyleDamage::REFLOW); - } - - break_at.and_then(|(i, child_remaining)| { - if i == self.base.children.len() && child_remaining.is_none() { - None - } else { - let mut children = self.base.children.split_off(i); - if let Some(child) = child_remaining { - children.push_front_arc(child); - } - Some(Arc::new(self.clone_with_children(children)) as Arc) - } - }) - } - - /// Add placement information about current float flow for use by the parent. - /// - /// Also, use information given by parent about other floats to find out our relative position. - /// - /// This does not give any information about any float descendants because they do not affect - /// elements outside of the subtree rooted at this float. - /// - /// This function is called on a kid flow by a parent. Therefore, `assign_block_size_float` was - /// already called on this kid flow by the traversal function. So, the values used are - /// well-defined. - pub fn place_float(&mut self) { - let block_size = self.fragment.border_box.size.block; - let clearance = match self.fragment.clear() { - None => Au(0), - Some(clear) => self.base.floats.clearance(clear), - }; - - let float_info: FloatedBlockInfo = (**self.float.as_ref().unwrap()).clone(); - - // Our `position` field accounts for positive margins, but not negative margins. (See - // calculation of `extra_inline_size_from_margin` below.) Negative margins must be taken - // into account for float placement, however. So we add them in here. - let inline_size_for_float_placement = self.base.position.size.inline + - min(Au(0), self.fragment.margin.inline_start_end()); - - let info = PlacementInfo { - size: LogicalSize::new( - self.fragment.style.writing_mode, - inline_size_for_float_placement, - block_size + self.fragment.margin.block_start_end()) - .convert(self.fragment.style.writing_mode, self.base.floats.writing_mode), - ceiling: clearance + float_info.float_ceiling, - max_inline_size: float_info.containing_inline_size, - kind: float_info.float_kind, - }; - - // Place the float and return the `Floats` back to the parent flow. - // After, grab the position and use that to set our position. - self.base.floats.add_float(&info); - - // FIXME (mbrubeck) Get the correct container size for self.base.floats; - let container_size = Size2D::new(self.base.block_container_inline_size, Au(0)); - - // Move in from the margin edge, as per CSS 2.1 § 9.5, floats may not overlap anything on - // their margin edges. - let float_offset = self.base.floats.last_float_pos().unwrap() - .convert(self.base.floats.writing_mode, - self.base.writing_mode, - container_size) - .start; - let margin_offset = LogicalPoint::new(self.base.writing_mode, - Au(0), - self.fragment.margin.block_start); - - let mut origin = LogicalPoint::new(self.base.writing_mode, - self.base.position.start.i, - self.base.position.start.b); - origin = origin.add_point(&float_offset).add_point(&margin_offset); - self.base.position = LogicalRect::from_point_size(self.base.writing_mode, - origin, - self.base.position.size); - } - - pub fn explicit_block_containing_size(&self, shared_context: &SharedStyleContext) -> Option { - if self.is_root() || self.is_fixed() { - let viewport_size = LogicalSize::from_physical(self.fragment.style.writing_mode, - shared_context.viewport_size()); - Some(viewport_size.block) - } else if self.base.flags.contains(FlowFlags::IS_ABSOLUTELY_POSITIONED) && - self.base.block_container_explicit_block_size.is_none() { - self.base.absolute_cb.explicit_block_containing_size(shared_context) - } else { - self.base.block_container_explicit_block_size - } - } - - pub fn explicit_block_size(&self, containing_block_size: Option) -> Option { - let content_block_size = self.fragment.style().content_block_size(); - - match (content_block_size, containing_block_size) { - (LengthOrPercentageOrAuto::Calc(calc), _) => { - calc.to_used_value(containing_block_size) - } - (LengthOrPercentageOrAuto::Length(length), _) => Some(Au::from(length)), - (LengthOrPercentageOrAuto::Percentage(percent), Some(container_size)) => { - Some(container_size.scale_by(percent.0)) - } - (LengthOrPercentageOrAuto::Percentage(_), None) | - (LengthOrPercentageOrAuto::Auto, None) => { - None - } - (LengthOrPercentageOrAuto::Auto, Some(container_size)) => { - let (block_start, block_end) = { - let position = self.fragment.style().logical_position(); - (MaybeAuto::from_style(position.block_start, container_size), - MaybeAuto::from_style(position.block_end, container_size)) - }; - - match (block_start, block_end) { - (MaybeAuto::Specified(block_start), MaybeAuto::Specified(block_end)) => { - let available_block_size = container_size - self.fragment.border_padding.block_start_end(); - - // Non-auto margin-block-start and margin-block-end values have already been - // calculated during assign-inline-size. - let margin = self.fragment.style().logical_margin(); - let margin_block_start = match margin.block_start { - LengthOrPercentageOrAuto::Auto => MaybeAuto::Auto, - _ => MaybeAuto::Specified(self.fragment.margin.block_start) - }; - let margin_block_end = match margin.block_end { - LengthOrPercentageOrAuto::Auto => MaybeAuto::Auto, - _ => MaybeAuto::Specified(self.fragment.margin.block_end) - }; - - let margin_block_start = margin_block_start.specified_or_zero(); - let margin_block_end = margin_block_end.specified_or_zero(); - let sum = block_start + block_end + margin_block_start + margin_block_end; - Some(available_block_size - sum) - } - - (_, _) => { - None - } - } - } - } - } - - fn calculate_absolute_block_size_and_margins(&mut self, shared_context: &SharedStyleContext) { - let opaque_self = OpaqueFlow::from_flow(self); - let containing_block_block_size = - self.containing_block_size(&shared_context.viewport_size(), opaque_self).block; - - // This is the stored content block-size value from assign-block-size - let content_block_size = self.fragment.border_box.size.block; - - let mut solution = None; - { - // Non-auto margin-block-start and margin-block-end values have already been - // calculated during assign-inline-size. - let margin = self.fragment.style().logical_margin(); - let margin_block_start = match margin.block_start { - LengthOrPercentageOrAuto::Auto => MaybeAuto::Auto, - _ => MaybeAuto::Specified(self.fragment.margin.block_start) - }; - let margin_block_end = match margin.block_end { - LengthOrPercentageOrAuto::Auto => MaybeAuto::Auto, - _ => MaybeAuto::Specified(self.fragment.margin.block_end) - }; - - let block_start; - let block_end; - { - let position = self.fragment.style().logical_position(); - block_start = MaybeAuto::from_style(position.block_start, - containing_block_block_size); - block_end = MaybeAuto::from_style(position.block_end, containing_block_block_size); - } - - let available_block_size = containing_block_block_size - - self.fragment.border_padding.block_start_end(); - if self.fragment.is_replaced() { - // Calculate used value of block-size just like we do for inline replaced elements. - // TODO: Pass in the containing block block-size when Fragment's - // assign-block-size can handle it correctly. - self.fragment.assign_replaced_block_size_if_necessary(); - // TODO: Right now, this content block-size value includes the - // margin because of erroneous block-size calculation in fragment. - // Check this when that has been fixed. - let block_size_used_val = self.fragment.border_box.size.block; - solution = Some(BSizeConstraintSolution::solve_vertical_constraints_abs_replaced( - block_size_used_val, - margin_block_start, - margin_block_end, - block_start, - block_end, - content_block_size, - available_block_size)) - } else { - let mut candidate_block_size_iterator = - CandidateBSizeIterator::new(&self.fragment, Some(containing_block_block_size)); - - // Can't use `for` because we assign to - // `candidate_block_size_iterator.candidate_value`. - while let Some(block_size_used_val) = candidate_block_size_iterator.next() { - solution = Some( - BSizeConstraintSolution::solve_vertical_constraints_abs_nonreplaced( - block_size_used_val, - margin_block_start, - margin_block_end, - block_start, - block_end, - content_block_size, - available_block_size)); - - candidate_block_size_iterator.candidate_value = - solution.unwrap().block_size; - } - } - } - - let solution = solution.unwrap(); - self.fragment.margin.block_start = solution.margin_block_start; - self.fragment.margin.block_end = solution.margin_block_end; - self.fragment.border_box.start.b = Au(0); - - if !self.base.flags.contains(FlowFlags::BLOCK_POSITION_IS_STATIC) { - self.base.position.start.b = solution.block_start + self.fragment.margin.block_start - } - - let block_size = solution.block_size + self.fragment.border_padding.block_start_end(); - self.fragment.border_box.size.block = block_size; - self.base.position.size.block = block_size; - - self.base.restyle_damage.remove(ServoRestyleDamage::REFLOW_OUT_OF_FLOW | ServoRestyleDamage::REFLOW); - self.fragment.restyle_damage.remove(ServoRestyleDamage::REFLOW_OUT_OF_FLOW | ServoRestyleDamage::REFLOW); - } - - /// Compute inline size based using the `block_container_inline_size` set by the parent flow. - /// - /// This is run in the `AssignISizes` traversal. - fn propagate_and_compute_used_inline_size(&mut self, shared_context: &SharedStyleContext) { - let containing_block_inline_size = self.base.block_container_inline_size; - self.compute_used_inline_size(shared_context, containing_block_inline_size); - if self.base.flags.is_float() { - self.float.as_mut().unwrap().containing_inline_size = containing_block_inline_size - } - } - - /// Assigns the computed inline-start content edge and inline-size to all the children of this - /// block flow. The given `callback`, if supplied, will be called once per child; it is - /// currently used to push down column sizes for tables. - /// - /// `#[inline(always)]` because this is called only from block or table inline-size assignment - /// and the code for block layout is significantly simpler. - #[inline(always)] - pub fn propagate_assigned_inline_size_to_children(&mut self, - shared_context: &SharedStyleContext, - inline_start_content_edge: Au, - inline_end_content_edge: Au, - content_inline_size: Au, - mut callback: F) - where F: FnMut(&mut Flow, - usize, - Au, - WritingMode, - &mut Au, - &mut Au) { - let flags = self.base.flags.clone(); - - let opaque_self = OpaqueFlow::from_flow(self); - - // Calculate non-auto block size to pass to children. - let box_border = match self.fragment.style().get_position().box_sizing { - BoxSizing::BorderBox => self.fragment.border_padding.block_start_end(), - BoxSizing::ContentBox => Au(0), - }; - let parent_container_size = self.explicit_block_containing_size(shared_context); - // https://drafts.csswg.org/css-ui-3/#box-sizing - let mut explicit_content_size = self - .explicit_block_size(parent_container_size) - .map(|x| if x < box_border { Au(0) } else { x - box_border }); - if self.is_root() { explicit_content_size = max(parent_container_size, explicit_content_size); } - // Calculate containing block inline size. - let containing_block_size = if flags.contains(FlowFlags::IS_ABSOLUTELY_POSITIONED) { - self.containing_block_size(&shared_context.viewport_size(), opaque_self).inline - } else { - content_inline_size - }; - // FIXME (mbrubeck): Get correct mode for absolute containing block - let containing_block_mode = self.base.writing_mode; - - let mut inline_start_margin_edge = inline_start_content_edge; - let mut inline_end_margin_edge = inline_end_content_edge; - - let mut iterator = self.base.child_iter_mut().enumerate().peekable(); - while let Some((i, kid)) = iterator.next() { - kid.mut_base().block_container_explicit_block_size = explicit_content_size; - - // The inline-start margin edge of the child flow is at our inline-start content edge, - // and its inline-size is our content inline-size. - let kid_mode = kid.base().writing_mode; - { - // Don't assign positions to children unless they're going to be reflowed. - // Otherwise, the position we assign might be incorrect and never fixed up. (Issue - // #13704.) - // - // For instance, floats have their true inline position calculated in - // `assign_block_size()`, which won't do anything unless `REFLOW` is set. So, if a - // float child does not have `REFLOW` set, we must be careful to avoid touching its - // inline position, as no logic will run afterward to set its true value. - let kid_base = kid.mut_base(); - let reflow_damage = if kid_base.flags.contains(FlowFlags::IS_ABSOLUTELY_POSITIONED) { - ServoRestyleDamage::REFLOW_OUT_OF_FLOW - } else { - ServoRestyleDamage::REFLOW - }; - if kid_base.flags.contains(FlowFlags::INLINE_POSITION_IS_STATIC) && - kid_base.restyle_damage.contains(reflow_damage) { - kid_base.position.start.i = - if kid_mode.is_bidi_ltr() == containing_block_mode.is_bidi_ltr() { - inline_start_content_edge - } else { - // The kid's inline 'start' is at the parent's 'end' - inline_end_content_edge - }; - } - kid_base.block_container_inline_size = content_inline_size; - kid_base.block_container_writing_mode = containing_block_mode; - } - - // Call the callback to propagate extra inline size information down to the child. This - // is currently used for tables. - callback(kid, - i, - content_inline_size, - containing_block_mode, - &mut inline_start_margin_edge, - &mut inline_end_margin_edge); - - // Per CSS 2.1 § 16.3.1, text alignment propagates to all children in flow. - // - // TODO(#2265, pcwalton): Do this in the cascade instead. - let containing_block_text_align = self.fragment.style().get_inheritedtext().text_align; - kid.mut_base().flags.set_text_align(containing_block_text_align); - - // Handle `text-indent` on behalf of any inline children that we have. This is - // necessary because any percentages are relative to the containing block, which only - // we know. - if kid.is_inline_flow() { - kid.as_mut_inline().first_line_indentation = - self.fragment.style().get_inheritedtext().text_indent - .to_used_value(containing_block_size); - } - } - } - - /// Determines the type of formatting context this is. See the definition of - /// `FormattingContextType`. - pub fn formatting_context_type(&self) -> FormattingContextType { - if self.is_inline_flex_item() || self.is_block_flex_item() { - return FormattingContextType::Other - } - let style = self.fragment.style(); - if style.get_box().float != Float::None { - return FormattingContextType::Other - } - match style.get_box().display { - Display::TableCell | - Display::TableCaption | - Display::TableRowGroup | - Display::Table | - Display::InlineBlock | - Display::Flex => { - FormattingContextType::Other - } - _ if style.get_box().overflow_x != StyleOverflow::Visible || - style.get_box().overflow_y != StyleOverflow::Visible || - style.is_multicol() => { - FormattingContextType::Block - } - _ => FormattingContextType::None, - } - } - - /// Per CSS 2.1 § 9.5, block formatting contexts' inline widths and positions are affected by - /// the presence of floats. This is the part of the assign-heights traversal that computes - /// the final inline position and width for such flows. - /// - /// Note that this is part of the assign-block-sizes traversal, not the assign-inline-sizes - /// traversal as one might expect. That is because, in general, float placement cannot occur - /// until heights are assigned. To work around this unfortunate circular dependency, by the - /// time we get here we have already estimated the width of the block formatting context based - /// on the floats we could see at the time of inline-size assignment. The job of this function, - /// therefore, is not only to assign the final size but also to perform the layout again for - /// this block formatting context if our speculation was wrong. - fn assign_inline_position_for_formatting_context(&mut self, - layout_context: &LayoutContext, - content_box: LogicalRect) { - debug_assert_ne!(self.formatting_context_type(), FormattingContextType::None); - - if !self.base.restyle_damage.intersects(ServoRestyleDamage::REFLOW_OUT_OF_FLOW | ServoRestyleDamage::REFLOW) { - return - } - - // We do this first to avoid recomputing our inline size when we propagate it. - self.base.restyle_damage.remove(ServoRestyleDamage::REFLOW_OUT_OF_FLOW | ServoRestyleDamage::REFLOW); - self.fragment.restyle_damage.remove(ServoRestyleDamage::REFLOW_OUT_OF_FLOW | ServoRestyleDamage::REFLOW); - - // The code below would completely wreck the layout if run on a flex item, however: - // * Flex items are always the children of flex containers. - // * Flex containers only contain flex items. - // * Floats cannot intrude into flex containers. - // * Floats cannot escape flex items. - // * Flex items cannot also be floats. - // Therefore, a flex item cannot be impacted by a float. - // See also: https://www.w3.org/TR/css-flexbox-1/#flex-containers - if !self.base.might_have_floats_in() { - return - } - - // If you remove the might_have_floats_in conditional, this will go off. - debug_assert!(!self.is_inline_flex_item()); - - // Compute the available space for us, based on the actual floats. - let rect = self.base.floats.available_rect(Au(0), - self.fragment.border_box.size.block, - content_box.size.inline); - let available_inline_size = if let Some(rect) = rect { - // Offset our position by whatever displacement is needed to not impact the floats. - // Also, account for margins sliding behind floats. - let inline_offset = if self.fragment.margin.inline_start < rect.start.i { - // Do not do anything for negative margins; those are handled separately. - rect.start.i - max(Au(0), self.fragment.margin.inline_start) - } else { - Au(0) - }; - self.base.position.start.i = content_box.start.i + inline_offset; - // Handle the end margin sliding behind the float. - let end = content_box.size.inline - rect.start.i - rect.size.inline; - let inline_end_offset = if self.fragment.margin.inline_end < end { - end - max(Au(0), self.fragment.margin.inline_end) - } else { - Au(0) - }; - content_box.size.inline - inline_offset - inline_end_offset - } else { - content_box.size.inline - } - self.fragment.margin.inline_start_end(); - let max_inline_size = - self.fragment.style().max_inline_size() - .to_used_value(self.base.block_container_inline_size) - .unwrap_or(MAX_AU); - let min_inline_size = - self.fragment.style().min_inline_size().to_used_value(self.base.block_container_inline_size); - let specified_inline_size = self.fragment.style().content_inline_size(); - let container_size = self.base.block_container_inline_size; - let inline_size = - if let MaybeAuto::Specified(size) = MaybeAuto::from_style(specified_inline_size, - container_size) { - match self.fragment.style().get_position().box_sizing { - BoxSizing::BorderBox => size, - BoxSizing::ContentBox => - size + self.fragment.border_padding.inline_start_end(), - } - } else { - max(min_inline_size, min(available_inline_size, max_inline_size)) - }; - self.base.position.size.inline = inline_size + self.fragment.margin.inline_start_end(); - - // If float speculation failed, fixup our layout, and re-layout all the children. - if self.fragment.margin_box_inline_size() != self.base.position.size.inline { - debug!("assign_inline_position_for_formatting_context: float speculation failed"); - // Fix-up our own layout. - // We can't just traverse_flow_tree_preorder ourself, because that would re-run - // float speculation, instead of acting on the actual results. - self.fragment.border_box.size.inline = inline_size; - // Assign final-final inline sizes on all our children. - self.assign_inline_sizes(layout_context); - // Re-run layout on our children. - for child in self.base.child_iter_mut() { - sequential::reflow(child, layout_context, RelayoutMode::Force); - } - // Assign our final-final block size. - self.assign_block_size(layout_context); - } - - debug_assert_eq!(self.fragment.margin_box_inline_size(), self.base.position.size.inline); - } - - fn is_inline_block_or_inline_flex(&self) -> bool { - self.fragment.style().get_box().display == Display::InlineBlock || - self.fragment.style().get_box().display == Display::InlineFlex - } - - /// Computes the content portion (only) of the intrinsic inline sizes of this flow. This is - /// used for calculating shrink-to-fit width. Assumes that intrinsic sizes have already been - /// computed for this flow. - fn content_intrinsic_inline_sizes(&self) -> IntrinsicISizes { - let (border_padding, margin) = self.fragment.surrounding_intrinsic_inline_size(); - IntrinsicISizes { - minimum_inline_size: self.base.intrinsic_inline_sizes.minimum_inline_size - - border_padding - margin, - preferred_inline_size: self.base.intrinsic_inline_sizes.preferred_inline_size - - border_padding - margin, - } - } - - /// Computes intrinsic inline sizes for a block. - pub fn bubble_inline_sizes_for_block(&mut self, consult_children: bool) { - let _scope = layout_debug_scope!("block::bubble_inline_sizes {:x}", self.base.debug_id()); - - let mut flags = self.base.flags; - if self.definitely_has_zero_block_size() { - // This is kind of a hack for Acid2. But it's a harmless one, because (a) this behavior - // is unspecified; (b) it matches the behavior one would intuitively expect, since - // floats don't flow around blocks that take up no space in the block direction. - flags.remove(FlowFlags::CONTAINS_TEXT_OR_REPLACED_FRAGMENTS); - } else if self.fragment.is_text_or_replaced() { - flags.insert(FlowFlags::CONTAINS_TEXT_OR_REPLACED_FRAGMENTS); - } else { - flags.remove(FlowFlags::CONTAINS_TEXT_OR_REPLACED_FRAGMENTS); - for kid in self.base.children.iter() { - if kid.base().flags.contains(FlowFlags::CONTAINS_TEXT_OR_REPLACED_FRAGMENTS) { - flags.insert(FlowFlags::CONTAINS_TEXT_OR_REPLACED_FRAGMENTS); - break - } - } - } - - // Find the maximum inline-size from children. - // - // See: https://lists.w3.org/Archives/Public/www-style/2014Nov/0085.html - // - // FIXME(pcwalton): This doesn't exactly follow that algorithm at the moment. - // FIXME(pcwalton): This should consider all float descendants, not just children. - let mut computation = self.fragment.compute_intrinsic_inline_sizes(); - let (mut left_float_width, mut right_float_width) = (Au(0), Au(0)); - let (mut left_float_width_accumulator, mut right_float_width_accumulator) = (Au(0), Au(0)); - let mut preferred_inline_size_of_children_without_text_or_replaced_fragments = Au(0); - for kid in self.base.child_iter_mut() { - if kid.base().flags.contains(FlowFlags::IS_ABSOLUTELY_POSITIONED) || !consult_children { - continue - } - - let child_base = kid.mut_base(); - let float_kind = child_base.flags.float_kind(); - computation.content_intrinsic_sizes.minimum_inline_size = - max(computation.content_intrinsic_sizes.minimum_inline_size, - child_base.intrinsic_inline_sizes.minimum_inline_size); - - if child_base.flags.contains(FlowFlags::CLEARS_LEFT) { - left_float_width = max(left_float_width, left_float_width_accumulator); - left_float_width_accumulator = Au(0) - } - if child_base.flags.contains(FlowFlags::CLEARS_RIGHT) { - right_float_width = max(right_float_width, right_float_width_accumulator); - right_float_width_accumulator = Au(0) - } - - match (float_kind, child_base.flags.contains(FlowFlags::CONTAINS_TEXT_OR_REPLACED_FRAGMENTS)) { - (Float::None, true) => { - computation.content_intrinsic_sizes.preferred_inline_size = - max(computation.content_intrinsic_sizes.preferred_inline_size, - child_base.intrinsic_inline_sizes.preferred_inline_size); - } - (Float::None, false) => { - preferred_inline_size_of_children_without_text_or_replaced_fragments = max( - preferred_inline_size_of_children_without_text_or_replaced_fragments, - child_base.intrinsic_inline_sizes.preferred_inline_size) - } - (Float::Left, _) => { - left_float_width_accumulator = left_float_width_accumulator + - child_base.intrinsic_inline_sizes.preferred_inline_size; - } - (Float::Right, _) => { - right_float_width_accumulator = right_float_width_accumulator + - child_base.intrinsic_inline_sizes.preferred_inline_size; - } - } - } - - left_float_width = max(left_float_width, left_float_width_accumulator); - right_float_width = max(right_float_width, right_float_width_accumulator); - - computation.content_intrinsic_sizes.preferred_inline_size = - computation.content_intrinsic_sizes.preferred_inline_size + left_float_width + - right_float_width; - computation.content_intrinsic_sizes.preferred_inline_size = - max(computation.content_intrinsic_sizes.preferred_inline_size, - preferred_inline_size_of_children_without_text_or_replaced_fragments); - - self.base.intrinsic_inline_sizes = computation.finish(); - self.base.flags = flags - } - - pub fn overflow_style_may_require_clip_scroll_node(&self) -> bool { - match (self.fragment.style().get_box().overflow_x, - self.fragment.style().get_box().overflow_y) { - (StyleOverflow::Auto, _) | (StyleOverflow::Scroll, _) | (StyleOverflow::Hidden, _) | - (_, StyleOverflow::Auto) | (_, StyleOverflow::Scroll) | (_, StyleOverflow::Hidden) => - true, - (_, _) => false, - } - } - - pub fn compute_inline_sizes(&mut self, shared_context: &SharedStyleContext) { - if !self.base.restyle_damage.intersects(ServoRestyleDamage::REFLOW_OUT_OF_FLOW | ServoRestyleDamage::REFLOW) { - return - } - - debug!("assign_inline_sizes({}): assigning inline_size for flow", - if self.base.flags.is_float() { - "float" - } else { - "block" - }); - - self.base.floats = Floats::new(self.base.writing_mode); - - self.initialize_container_size_for_root(shared_context); - - // Our inline-size was set to the inline-size of the containing block by the flow's parent. - // Now compute the real value. - self.propagate_and_compute_used_inline_size(shared_context); - - self.guess_inline_size_for_block_formatting_context_if_necessary() - } - - /// If this is the root flow, initialize values that would normally be set by the parent. - /// - /// Should be called during `assign_inline_sizes` for flows that may be the root. - pub fn initialize_container_size_for_root(&mut self, shared_context: &SharedStyleContext) { - if self.is_root() { - debug!("Setting root position"); - self.base.position.start = LogicalPoint::zero(self.base.writing_mode); - self.base.block_container_inline_size = LogicalSize::from_physical( - self.base.writing_mode, shared_context.viewport_size()).inline; - self.base.block_container_writing_mode = self.base.writing_mode; - } - } - - fn guess_inline_size_for_block_formatting_context_if_necessary(&mut self) { - // We don't need to guess anything unless this is a block formatting context. - if self.formatting_context_type() != FormattingContextType::Block { - return - } - - // If `max-width` is set, then don't perform this speculation. We guess that the - // page set `max-width` in order to avoid hitting floats. The search box on Google - // SERPs falls into this category. - if self.fragment.style.max_inline_size() != LengthOrPercentageOrNone::None { - return - } - - // At this point, we know we can't precisely compute the inline-size of this block now, - // because floats might affect it. Speculate that its inline-size is equal to the - // inline-size computed above minus the inline-size of the previous left and/or right - // floats. - let speculated_left_float_size = if self.fragment.margin.inline_start >= Au(0) && - self.base.speculated_float_placement_in.left > self.fragment.margin.inline_start { - self.base.speculated_float_placement_in.left - self.fragment.margin.inline_start - } else { - Au(0) - }; - let speculated_right_float_size = if self.fragment.margin.inline_end >= Au(0) && - self.base.speculated_float_placement_in.right > self.fragment.margin.inline_end { - self.base.speculated_float_placement_in.right - self.fragment.margin.inline_end - } else { - Au(0) - }; - self.fragment.border_box.size.inline = self.fragment.border_box.size.inline - - speculated_left_float_size - speculated_right_float_size - } - - fn definitely_has_zero_block_size(&self) -> bool { - if !self.fragment.style.content_block_size().is_definitely_zero() { - return false - } - let border_width = self.fragment.border_width(); - if border_width.block_start != Au(0) || border_width.block_end != Au(0) { - return false - } - let padding = self.fragment.style.logical_padding(); - padding.block_start.is_definitely_zero() && padding.block_end.is_definitely_zero() - } - - pub fn is_inline_flex_item(&self) -> bool { - self.fragment.flags.contains(FragmentFlags::IS_INLINE_FLEX_ITEM) - } - - pub fn is_block_flex_item(&self) -> bool { - self.fragment.flags.contains(FragmentFlags::IS_BLOCK_FLEX_ITEM) - } - - pub fn mark_scrolling_overflow(&mut self, has_scrolling_overflow: bool) { - if has_scrolling_overflow { - self.flags.insert(BlockFlowFlags::HAS_SCROLLING_OVERFLOW); - } else { - self.flags.remove(BlockFlowFlags::HAS_SCROLLING_OVERFLOW); - } - } - - pub fn has_scrolling_overflow(&self) -> bool { - self.flags.contains(BlockFlowFlags::HAS_SCROLLING_OVERFLOW) - } - - // Return offset from original position because of `position: sticky`. - pub fn sticky_position(&self) -> SideOffsets2D { - let containing_block_size = &self.base.early_absolute_position_info - .relative_containing_block_size; - let writing_mode = self.base.early_absolute_position_info.relative_containing_block_mode; - let offsets = self.fragment.style().logical_position(); - let as_margins = LogicalMargin::new(writing_mode, - MaybeAuto::from_style(offsets.block_start, containing_block_size.inline), - MaybeAuto::from_style(offsets.inline_end, containing_block_size.inline), - MaybeAuto::from_style(offsets.block_end, containing_block_size.inline), - MaybeAuto::from_style(offsets.inline_start, containing_block_size.inline)); - as_margins.to_physical(writing_mode) - } - - pub fn background_border_section(&self) -> DisplayListSection { - if self.base.flags.is_float() { - DisplayListSection::BackgroundAndBorders - } else if self.base - .flags - .contains(FlowFlags::IS_ABSOLUTELY_POSITIONED) - { - if self.fragment.establishes_stacking_context() { - DisplayListSection::BackgroundAndBorders - } else { - DisplayListSection::BlockBackgroundsAndBorders - } - } else { - DisplayListSection::BlockBackgroundsAndBorders - } - } -} - -impl Flow for BlockFlow { - fn class(&self) -> FlowClass { - FlowClass::Block - } - - fn as_mut_block(&mut self) -> &mut BlockFlow { - self - } - - fn as_block(&self) -> &BlockFlow { - self - } - - /// Pass 1 of reflow: computes minimum and preferred inline-sizes. - /// - /// Recursively (bottom-up) determine the flow's minimum and preferred inline-sizes. When - /// called on this flow, all child flows have had their minimum and preferred inline-sizes set. - /// This function must decide minimum/preferred inline-sizes based on its children's - /// inline-sizes and the dimensions of any fragments it is responsible for flowing. - fn bubble_inline_sizes(&mut self) { - // If this block has a fixed width, just use that for the minimum and preferred width, - // rather than bubbling up children inline width. - let consult_children = match self.fragment.style().get_position().width { - LengthOrPercentageOrAuto::Length(_) => false, - _ => true, - }; - self.bubble_inline_sizes_for_block(consult_children); - self.fragment.restyle_damage.remove(ServoRestyleDamage::BUBBLE_ISIZES); - } - - /// Recursively (top-down) determines the actual inline-size of child contexts and fragments. - /// When called on this context, the context has had its inline-size set by the parent context. - /// - /// Dual fragments consume some inline-size first, and the remainder is assigned to all child - /// (block) contexts. - fn assign_inline_sizes(&mut self, layout_context: &LayoutContext) { - let _scope = layout_debug_scope!("block::assign_inline_sizes {:x}", self.base.debug_id()); - - let shared_context = layout_context.shared_context(); - self.compute_inline_sizes(shared_context); - - // Move in from the inline-start border edge. - let inline_start_content_edge = self.fragment.border_box.start.i + - self.fragment.border_padding.inline_start; - - let padding_and_borders = self.fragment.border_padding.inline_start_end(); - - // Distance from the inline-end margin edge to the inline-end content edge. - let inline_end_content_edge = - self.fragment.margin.inline_end + - self.fragment.border_padding.inline_end; - - let content_inline_size = self.fragment.border_box.size.inline - padding_and_borders; - - self.propagate_assigned_inline_size_to_children(shared_context, - inline_start_content_edge, - inline_end_content_edge, - content_inline_size, - |_, _, _, _, _, _| {}); - } - - fn place_float_if_applicable<'a>(&mut self) { - if self.base.flags.is_float() { - self.place_float(); - } - } - - fn assign_block_size_for_inorder_child_if_necessary(&mut self, - layout_context: &LayoutContext, - parent_thread_id: u8, - content_box: LogicalRect) - -> bool { - if self.base.flags.is_float() { - return false - } - - let is_formatting_context = self.formatting_context_type() != FormattingContextType::None; - if !self.base.flags.contains(FlowFlags::IS_ABSOLUTELY_POSITIONED) && is_formatting_context { - self.assign_inline_position_for_formatting_context(layout_context, content_box); - } - - if (self as &Flow).floats_might_flow_through() { - self.base.thread_id = parent_thread_id; - if self.base.restyle_damage.intersects(ServoRestyleDamage::REFLOW_OUT_OF_FLOW | - ServoRestyleDamage::REFLOW) { - self.assign_block_size(layout_context); - // Don't remove the restyle damage; `assign_block_size` decides whether that is - // appropriate (which in the case of e.g. absolutely-positioned flows, it is not). - } - return true - } - - if is_formatting_context { - // If this is a formatting context and definitely did not have floats in, then we must - // translate the floats past us. - let writing_mode = self.base.floats.writing_mode; - let delta = self.base.position.size.block; - self.base.floats.translate(LogicalSize::new(writing_mode, Au(0), -delta)); - return true - } - - false - } - - fn assign_block_size(&mut self, ctx: &LayoutContext) { - let remaining = Flow::fragment(self, ctx, None); - debug_assert!(remaining.is_none()); - } - - fn fragment(&mut self, layout_context: &LayoutContext, - fragmentation_context: Option) - -> Option> { - if self.fragment.is_replaced() { - let _scope = layout_debug_scope!("assign_replaced_block_size_if_necessary {:x}", - self.base.debug_id()); - - // Assign block-size for fragment if it is an image fragment. - self.fragment.assign_replaced_block_size_if_necessary(); - if !self.base.flags.contains(FlowFlags::IS_ABSOLUTELY_POSITIONED) { - self.base.position.size.block = self.fragment.border_box.size.block; - let mut block_start = AdjoiningMargins::from_margin(self.fragment.margin.block_start); - let block_end = AdjoiningMargins::from_margin(self.fragment.margin.block_end); - if self.fragment.border_box.size.block == Au(0) { - block_start.union(block_end); - self.base.collapsible_margins = CollapsibleMargins::CollapseThrough(block_start); - } else { - self.base.collapsible_margins = CollapsibleMargins::Collapse(block_start, block_end); - } - self.base.restyle_damage.remove(ServoRestyleDamage::REFLOW_OUT_OF_FLOW | ServoRestyleDamage::REFLOW); - self.fragment.restyle_damage.remove(ServoRestyleDamage::REFLOW_OUT_OF_FLOW | - ServoRestyleDamage::REFLOW); - } - None - } else if self.is_root() || - self.formatting_context_type() != FormattingContextType::None || - self.base.flags.contains(FlowFlags::MARGINS_CANNOT_COLLAPSE) { - // Root element margins should never be collapsed according to CSS § 8.3.1. - debug!("assign_block_size: assigning block_size for root flow {:?}", - self.base().debug_id()); - self.assign_block_size_block_base( - layout_context, - fragmentation_context, - MarginsMayCollapseFlag::MarginsMayNotCollapse) - } else { - debug!("assign_block_size: assigning block_size for block {:?}", - self.base().debug_id()); - self.assign_block_size_block_base( - layout_context, - fragmentation_context, - MarginsMayCollapseFlag::MarginsMayCollapse) - } - } - - fn compute_stacking_relative_position(&mut self, _layout_context: &LayoutContext) { - // FIXME (mbrubeck): Get the real container size, taking the container writing mode into - // account. Must handle vertical writing modes. - let container_size = Size2D::new(self.base.block_container_inline_size, Au(0)); - - if self.is_root() { - self.base.clip = Rect::max_rect(); - } - - if self.base.flags.contains(FlowFlags::IS_ABSOLUTELY_POSITIONED) { - let position_start = self.base.position.start.to_physical(self.base.writing_mode, - container_size); - - // Compute our position relative to the nearest ancestor stacking context. This will be - // passed down later as part of containing block details for absolute descendants. - let absolute_stacking_relative_position = if self.is_fixed() { - // The viewport is initially at (0, 0). - position_start - } else { - // Absolute position of the containing block + position of absolute - // flow w.r.t. the containing block. - self.base - .late_absolute_position_info - .stacking_relative_position_of_absolute_containing_block + position_start.to_vector() - }; - - if !self.base.writing_mode.is_vertical() { - if !self.base.flags.contains(FlowFlags::INLINE_POSITION_IS_STATIC) { - self.base.stacking_relative_position.x = absolute_stacking_relative_position.x - } - if !self.base.flags.contains(FlowFlags::BLOCK_POSITION_IS_STATIC) { - self.base.stacking_relative_position.y = absolute_stacking_relative_position.y - } - } else { - if !self.base.flags.contains(FlowFlags::INLINE_POSITION_IS_STATIC) { - self.base.stacking_relative_position.y = absolute_stacking_relative_position.y - } - if !self.base.flags.contains(FlowFlags::BLOCK_POSITION_IS_STATIC) { - self.base.stacking_relative_position.x = absolute_stacking_relative_position.x - } - } - } - - // For relatively-positioned descendants, the containing block formed by a block is just - // the content box. The containing block for absolutely-positioned descendants, on the - // other hand, is established in other circumstances (see `is_absolute_containing_block'). - let relative_offset = - self.fragment.relative_position(&self.base - .early_absolute_position_info - .relative_containing_block_size); - if self.is_absolute_containing_block() { - let border_box_origin = (self.fragment.border_box - - self.fragment.style.logical_border_width()).start; - self.base - .late_absolute_position_info - .stacking_relative_position_of_absolute_containing_block = - self.base.stacking_relative_position.to_point() + - (border_box_origin + relative_offset).to_physical(self.base.writing_mode, - container_size).to_vector() - } - - // Compute absolute position info for children. - let stacking_relative_position_of_absolute_containing_block_for_children = - if self.fragment.establishes_stacking_context() { - let logical_border_width = self.fragment.style().logical_border_width(); - let position = LogicalPoint::new(self.base.writing_mode, - logical_border_width.inline_start, - logical_border_width.block_start); - let position = position.to_physical(self.base.writing_mode, container_size); - - // Some blocks establish a stacking context, but not a containing block for - // absolutely positioned elements. An example of this might be a block that has - // `position: static` and `opacity` set. In these cases, absolutely-positioned - // children will not be positioned relative to us but will instead be positioned - // relative to our containing block. - if self.is_absolute_containing_block() { - position - } else { - position - self.base.stacking_relative_position - } - } else { - self.base - .late_absolute_position_info - .stacking_relative_position_of_absolute_containing_block - }; - let late_absolute_position_info_for_children = LateAbsolutePositionInfo { - stacking_relative_position_of_absolute_containing_block: - stacking_relative_position_of_absolute_containing_block_for_children, - }; - let container_size_for_children = - self.base.position.size.to_physical(self.base.writing_mode); - - // Compute the origin and clipping rectangle for children. - let relative_offset = relative_offset.to_physical(self.base.writing_mode).to_vector(); - let is_stacking_context = self.fragment.establishes_stacking_context(); - let origin_for_children = if is_stacking_context { - // We establish a stacking context, so the position of our children is vertically - // correct, but has to be adjusted to accommodate horizontal margins. (Note the - // calculation involving `position` below and recall that inline-direction flow - // positions are relative to the edges of the margin box.) - // - // FIXME(pcwalton): Is this vertical-writing-direction-safe? - let margin = self.fragment.margin.to_physical(self.base.writing_mode); - Point2D::new(-margin.left, Au(0)) - } else { - self.base.stacking_relative_position.to_point() + relative_offset - }; - - // Process children. - for kid in self.base.child_iter_mut() { - if kid.base().flags.contains(FlowFlags::INLINE_POSITION_IS_STATIC) || - kid.base().flags.contains(FlowFlags::BLOCK_POSITION_IS_STATIC) { - let kid_base = kid.mut_base(); - let physical_position = kid_base.position.to_physical(kid_base.writing_mode, - container_size_for_children); - - // Set the inline and block positions as necessary. - if !kid_base.writing_mode.is_vertical() { - if kid_base.flags.contains(FlowFlags::INLINE_POSITION_IS_STATIC) { - kid_base.stacking_relative_position.x = origin_for_children.x + - physical_position.origin.x - } - if kid_base.flags.contains(FlowFlags::BLOCK_POSITION_IS_STATIC) { - kid_base.stacking_relative_position.y = origin_for_children.y + - physical_position.origin.y - } - } else { - if kid_base.flags.contains(FlowFlags::INLINE_POSITION_IS_STATIC) { - kid_base.stacking_relative_position.y = origin_for_children.y + - physical_position.origin.y - } - if kid_base.flags.contains(FlowFlags::BLOCK_POSITION_IS_STATIC) { - kid_base.stacking_relative_position.x = origin_for_children.x + - physical_position.origin.x - } - } - } - - kid.mut_base().late_absolute_position_info = - late_absolute_position_info_for_children; - } - } - - fn mark_as_root(&mut self) { - self.flags.insert(BlockFlowFlags::IS_ROOT) - } - - fn is_root(&self) -> bool { - self.flags.contains(BlockFlowFlags::IS_ROOT) - } - - /// The 'position' property of this flow. - fn positioning(&self) -> Position { - self.fragment.style.get_box().position - } - - /// Return the dimensions of the containing block generated by this flow for absolutely- - /// positioned descendants. For block flows, this is the padding box. - fn generated_containing_block_size(&self, _: OpaqueFlow) -> LogicalSize { - (self.fragment.border_box - self.fragment.style().logical_border_width()).size - } - - /// Returns true if this flow contains fragments that are roots of an absolute flow tree. - fn contains_roots_of_absolute_flow_tree(&self) -> bool { - self.contains_relatively_positioned_fragments() || self.is_root() || - self.fragment.has_filter_transform_or_perspective() - } - - /// Returns true if this is an absolute containing block. - fn is_absolute_containing_block(&self) -> bool { - self.contains_positioned_fragments() || self.fragment.has_filter_transform_or_perspective() - } - - fn update_late_computed_inline_position_if_necessary(&mut self, inline_position: Au) { - if self.base.flags.contains(FlowFlags::IS_ABSOLUTELY_POSITIONED) && - self.fragment.style().logical_position().inline_start == - LengthOrPercentageOrAuto::Auto && - self.fragment.style().logical_position().inline_end == - LengthOrPercentageOrAuto::Auto { - self.base.position.start.i = inline_position - } - } - - fn update_late_computed_block_position_if_necessary(&mut self, block_position: Au) { - if self.base.flags.contains(FlowFlags::IS_ABSOLUTELY_POSITIONED) && - self.fragment.style().logical_position().block_start == - LengthOrPercentageOrAuto::Auto && - self.fragment.style().logical_position().block_end == - LengthOrPercentageOrAuto::Auto { - self.base.position.start.b = block_position - } - } - - fn collect_stacking_contexts(&mut self, state: &mut StackingContextCollectionState) { - self.collect_stacking_contexts_for_block(state, StackingContextCollectionFlags::empty()); - } - - fn build_display_list(&mut self, state: &mut DisplayListBuildState) { - self.build_display_list_for_block(state, BorderPaintingMode::Separate); - } - - fn repair_style(&mut self, new_style: &::ServoArc) { - self.fragment.repair_style(new_style) - } - - fn compute_overflow(&self) -> Overflow { - let flow_size = self.base.position.size.to_physical(self.base.writing_mode); - let overflow = self.fragment.compute_overflow(&flow_size, - &self.base - .early_absolute_position_info - .relative_containing_block_size); - overflow - } - - fn iterate_through_fragment_border_boxes(&self, - iterator: &mut FragmentBorderBoxIterator, - level: i32, - stacking_context_position: &Point2D) { - if !iterator.should_process(&self.fragment) { - return - } - - iterator.process(&self.fragment, - level, - &self.fragment - .stacking_relative_border_box(&self.base.stacking_relative_position, - &self.base - .early_absolute_position_info - .relative_containing_block_size, - self.base - .early_absolute_position_info - .relative_containing_block_mode, - CoordinateSystem::Own) - .translate(&stacking_context_position.to_vector())); - } - - fn mutate_fragments(&mut self, mutator: &mut FnMut(&mut Fragment)) { - (*mutator)(&mut self.fragment) - } - - fn print_extra_flow_children(&self, print_tree: &mut PrintTree) { - print_tree.add_item(format!("↑↑ Fragment for block:{:?}", self.fragment)); - } -} - -impl fmt::Debug for BlockFlow { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, - "{:?}({:x}) {:?}", - self.class(), - self.base.debug_id(), - self.base) - } -} - -/// The inputs for the inline-sizes-and-margins constraint equation. -#[derive(Clone, Copy, Debug)] -pub struct ISizeConstraintInput { - pub computed_inline_size: MaybeAuto, - pub inline_start_margin: MaybeAuto, - pub inline_end_margin: MaybeAuto, - pub inline_start: MaybeAuto, - pub inline_end: MaybeAuto, - pub text_align: TextAlign, - pub available_inline_size: Au, -} - -impl ISizeConstraintInput { - pub fn new(computed_inline_size: MaybeAuto, - inline_start_margin: MaybeAuto, - inline_end_margin: MaybeAuto, - inline_start: MaybeAuto, - inline_end: MaybeAuto, - text_align: TextAlign, - available_inline_size: Au) - -> ISizeConstraintInput { - ISizeConstraintInput { - computed_inline_size: computed_inline_size, - inline_start_margin: inline_start_margin, - inline_end_margin: inline_end_margin, - inline_start: inline_start, - inline_end: inline_end, - text_align: text_align, - available_inline_size: available_inline_size, - } - } -} - -/// The solutions for the inline-size-and-margins constraint equation. -#[derive(Clone, Copy, Debug)] -pub struct ISizeConstraintSolution { - pub inline_start: Au, - pub inline_size: Au, - pub margin_inline_start: Au, - pub margin_inline_end: Au -} - -impl ISizeConstraintSolution { - pub fn new(inline_size: Au, margin_inline_start: Au, margin_inline_end: Au) - -> ISizeConstraintSolution { - ISizeConstraintSolution { - inline_start: Au(0), - inline_size: inline_size, - margin_inline_start: margin_inline_start, - margin_inline_end: margin_inline_end, - } - } - - fn for_absolute_flow(inline_start: Au, - inline_size: Au, - margin_inline_start: Au, - margin_inline_end: Au) - -> ISizeConstraintSolution { - ISizeConstraintSolution { - inline_start: inline_start, - inline_size: inline_size, - margin_inline_start: margin_inline_start, - margin_inline_end: margin_inline_end, - } - } -} - -// Trait to encapsulate the ISize and Margin calculation. -// -// CSS Section 10.3 -pub trait ISizeAndMarginsComputer { - /// Instructs the fragment to compute its border and padding. - fn compute_border_and_padding(&self, block: &mut BlockFlow, containing_block_inline_size: Au) { - block.fragment.compute_border_and_padding(containing_block_inline_size); - } - - /// Compute the inputs for the ISize constraint equation. - /// - /// This is called only once to compute the initial inputs. For calculations involving - /// minimum and maximum inline-size, we don't need to recompute these. - fn compute_inline_size_constraint_inputs(&self, - block: &mut BlockFlow, - parent_flow_inline_size: Au, - shared_context: &SharedStyleContext) - -> ISizeConstraintInput { - let containing_block_inline_size = - self.containing_block_inline_size(block, parent_flow_inline_size, shared_context); - - block.fragment.compute_block_direction_margins(containing_block_inline_size); - block.fragment.compute_inline_direction_margins(containing_block_inline_size); - self.compute_border_and_padding(block, containing_block_inline_size); - - let mut computed_inline_size = self.initial_computed_inline_size(block, - parent_flow_inline_size, - shared_context); - let style = block.fragment.style(); - match (computed_inline_size, style.get_position().box_sizing) { - (MaybeAuto::Specified(size), BoxSizing::BorderBox) => { - computed_inline_size = - MaybeAuto::Specified(size - block.fragment.border_padding.inline_start_end()) - } - (MaybeAuto::Auto, BoxSizing::BorderBox) | - (_, BoxSizing::ContentBox) => {} - } - - let margin = style.logical_margin(); - let position = style.logical_position(); - - let available_inline_size = containing_block_inline_size - - block.fragment.border_padding.inline_start_end(); - ISizeConstraintInput::new(computed_inline_size, - MaybeAuto::from_style(margin.inline_start, - containing_block_inline_size), - MaybeAuto::from_style(margin.inline_end, - containing_block_inline_size), - MaybeAuto::from_style(position.inline_start, - containing_block_inline_size), - MaybeAuto::from_style(position.inline_end, - containing_block_inline_size), - style.get_inheritedtext().text_align, - available_inline_size) - } - - /// Set the used values for inline-size and margins from the relevant constraint equation. - /// This is called only once. - /// - /// Set: - /// * Used values for content inline-size, inline-start margin, and inline-end margin for this - /// flow's box; - /// * Inline-start coordinate of this flow's box; - /// * Inline-start coordinate of the flow with respect to its containing block (if this is an - /// absolute flow). - fn set_inline_size_constraint_solutions(&self, - block: &mut BlockFlow, - solution: ISizeConstraintSolution) { - let inline_size; - let extra_inline_size_from_margin; - { - let block_mode = block.base.writing_mode; - - // FIXME (mbrubeck): Get correct containing block for positioned blocks? - let container_mode = block.base.block_container_writing_mode; - let container_size = block.base.block_container_inline_size; - - let fragment = block.fragment(); - fragment.margin.inline_start = solution.margin_inline_start; - fragment.margin.inline_end = solution.margin_inline_end; - - // The associated fragment has the border box of this flow. - inline_size = solution.inline_size + fragment.border_padding.inline_start_end(); - fragment.border_box.size.inline = inline_size; - - // Start border edge. - // FIXME (mbrubeck): Handle vertical writing modes. - fragment.border_box.start.i = - if container_mode.is_bidi_ltr() == block_mode.is_bidi_ltr() { - fragment.margin.inline_start - } else { - // The parent's "start" direction is the child's "end" direction. - container_size - inline_size - fragment.margin.inline_end - }; - - // To calculate the total size of this block, we also need to account for any - // additional size contribution from positive margins. Negative margins means the block - // isn't made larger at all by the margin. - extra_inline_size_from_margin = max(Au(0), fragment.margin.inline_start) + - max(Au(0), fragment.margin.inline_end); - } - - // We also resize the block itself, to ensure that overflow is not calculated - // as the inline-size of our parent. We might be smaller and we might be larger if we - // overflow. - block.mut_base().position.size.inline = inline_size + extra_inline_size_from_margin; - } - - /// Set the inline coordinate of the given flow if it is absolutely positioned. - fn set_inline_position_of_flow_if_necessary(&self, - _: &mut BlockFlow, - _: ISizeConstraintSolution) {} - - /// Solve the inline-size and margins constraints for this block flow. - fn solve_inline_size_constraints(&self, - block: &mut BlockFlow, - input: &ISizeConstraintInput) - -> ISizeConstraintSolution; - - fn initial_computed_inline_size(&self, - block: &mut BlockFlow, - parent_flow_inline_size: Au, - shared_context: &SharedStyleContext) - -> MaybeAuto { - MaybeAuto::from_style(block.fragment().style().content_inline_size(), - self.containing_block_inline_size(block, - parent_flow_inline_size, - shared_context)) - } - - fn containing_block_inline_size(&self, - _: &mut BlockFlow, - parent_flow_inline_size: Au, - _: &SharedStyleContext) - -> Au { - parent_flow_inline_size - } - - /// Compute the used value of inline-size, taking care of min-inline-size and max-inline-size. - /// - /// CSS Section 10.4: Minimum and Maximum inline-sizes - fn compute_used_inline_size(&self, - block: &mut BlockFlow, - shared_context: &SharedStyleContext, - parent_flow_inline_size: Au) { - let mut input = self.compute_inline_size_constraint_inputs(block, - parent_flow_inline_size, - shared_context); - - let containing_block_inline_size = - self.containing_block_inline_size(block, parent_flow_inline_size, shared_context); - - let mut solution = self.solve_inline_size_constraints(block, &input); - - // If the tentative used inline-size is greater than 'max-inline-size', inline-size should - // be recalculated, but this time using the computed value of 'max-inline-size' as the - // computed value for 'inline-size'. - match block.fragment().style().max_inline_size().to_used_value(containing_block_inline_size) { - Some(max_inline_size) if max_inline_size < solution.inline_size => { - input.computed_inline_size = MaybeAuto::Specified(max_inline_size); - solution = self.solve_inline_size_constraints(block, &input); - } - _ => {} - } - - // If the resulting inline-size is smaller than 'min-inline-size', inline-size should be - // recalculated, but this time using the value of 'min-inline-size' as the computed value - // for 'inline-size'. - let computed_min_inline_size = - block.fragment().style().min_inline_size().to_used_value(containing_block_inline_size); - if computed_min_inline_size > solution.inline_size { - input.computed_inline_size = MaybeAuto::Specified(computed_min_inline_size); - solution = self.solve_inline_size_constraints(block, &input); - } - - self.set_inline_size_constraint_solutions(block, solution); - self.set_inline_position_of_flow_if_necessary(block, solution); - } - - /// Computes inline-start and inline-end margins and inline-size. - /// - /// This is used by both replaced and non-replaced Blocks. - /// - /// CSS 2.1 Section 10.3.3. - /// Constraint Equation: margin-inline-start + margin-inline-end + inline-size = - /// available_inline-size - /// where available_inline-size = CB inline-size - (horizontal border + padding) - fn solve_block_inline_size_constraints(&self, - block: &mut BlockFlow, - input: &ISizeConstraintInput) - -> ISizeConstraintSolution { - let (computed_inline_size, inline_start_margin, inline_end_margin, available_inline_size) = - (input.computed_inline_size, - input.inline_start_margin, - input.inline_end_margin, - input.available_inline_size); - - // Check for direction of parent flow (NOT Containing Block) - let block_mode = block.base.writing_mode; - let container_mode = block.base.block_container_writing_mode; - let block_align = block.base.flags.text_align(); - - // FIXME (mbrubeck): Handle vertical writing modes. - let parent_has_same_direction = container_mode.is_bidi_ltr() == block_mode.is_bidi_ltr(); - - // If inline-size is not 'auto', and inline-size + margins > available_inline-size, all - // 'auto' margins are treated as 0. - let (inline_start_margin, inline_end_margin) = match computed_inline_size { - MaybeAuto::Auto => (inline_start_margin, inline_end_margin), - MaybeAuto::Specified(inline_size) => { - let inline_start = inline_start_margin.specified_or_zero(); - let inline_end = inline_end_margin.specified_or_zero(); - - if (inline_start + inline_end + inline_size) > available_inline_size { - (MaybeAuto::Specified(inline_start), MaybeAuto::Specified(inline_end)) - } else { - (inline_start_margin, inline_end_margin) - } - } - }; - - // Invariant: inline-start_margin + inline-size + inline-end_margin == - // available_inline-size - let (inline_start_margin, inline_size, inline_end_margin) = - match (inline_start_margin, computed_inline_size, inline_end_margin) { - // If all have a computed value other than 'auto', the system is over-constrained. - (MaybeAuto::Specified(margin_start), - MaybeAuto::Specified(inline_size), - MaybeAuto::Specified(margin_end)) => { - // servo_left, servo_right, and servo_center are used to implement - // the "align descendants" rule in HTML5 § 14.2. - if block_align == TextAlign::ServoCenter { - // Ignore any existing margins, and make the inline-start and - // inline-end margins equal. - let margin = (available_inline_size - inline_size).scale_by(0.5); - (margin, inline_size, margin) - } else { - let ignore_end_margin = match block_align { - TextAlign::ServoLeft => block_mode.is_bidi_ltr(), - TextAlign::ServoRight => !block_mode.is_bidi_ltr(), - _ => parent_has_same_direction, - }; - if ignore_end_margin { - (margin_start, inline_size, available_inline_size - - (margin_start + inline_size)) - } else { - (available_inline_size - (margin_end + inline_size), - inline_size, - margin_end) - } - } - } - // If exactly one value is 'auto', solve for it - (MaybeAuto::Auto, - MaybeAuto::Specified(inline_size), - MaybeAuto::Specified(margin_end)) => - (available_inline_size - (inline_size + margin_end), inline_size, margin_end), - (MaybeAuto::Specified(margin_start), - MaybeAuto::Auto, - MaybeAuto::Specified(margin_end)) => { - (margin_start, - available_inline_size - (margin_start + margin_end), - margin_end) - } - (MaybeAuto::Specified(margin_start), - MaybeAuto::Specified(inline_size), - MaybeAuto::Auto) => { - (margin_start, - inline_size, - available_inline_size - (margin_start + inline_size)) - } - - // If inline-size is set to 'auto', any other 'auto' value becomes '0', - // and inline-size is solved for - (MaybeAuto::Auto, MaybeAuto::Auto, MaybeAuto::Specified(margin_end)) => { - (Au(0), available_inline_size - margin_end, margin_end) - } - (MaybeAuto::Specified(margin_start), MaybeAuto::Auto, MaybeAuto::Auto) => { - (margin_start, available_inline_size - margin_start, Au(0)) - } - (MaybeAuto::Auto, MaybeAuto::Auto, MaybeAuto::Auto) => { - (Au(0), available_inline_size, Au(0)) - } - - // If inline-start and inline-end margins are auto, they become equal - (MaybeAuto::Auto, MaybeAuto::Specified(inline_size), MaybeAuto::Auto) => { - let margin = (available_inline_size - inline_size).scale_by(0.5); - (margin, inline_size, margin) - } - }; - - ISizeConstraintSolution::new(inline_size, inline_start_margin, inline_end_margin) - } -} - -/// The different types of Blocks. -/// -/// They mainly differ in the way inline-size and block-sizes and margins are calculated -/// for them. -pub struct AbsoluteNonReplaced; -pub struct AbsoluteReplaced; -pub struct BlockNonReplaced; -pub struct BlockReplaced; -pub struct FloatNonReplaced; -pub struct FloatReplaced; -pub struct InlineBlockNonReplaced; -pub struct InlineBlockReplaced; -pub struct InlineFlexItem; - -impl ISizeAndMarginsComputer for AbsoluteNonReplaced { - /// Solve the horizontal constraint equation for absolute non-replaced elements. - /// - /// CSS Section 10.3.7 - /// Constraint equation: - /// inline-start + inline-end + inline-size + margin-inline-start + margin-inline-end - /// = absolute containing block inline-size - (horizontal padding and border) - /// [aka available inline-size] - /// - /// Return the solution for the equation. - fn solve_inline_size_constraints(&self, - block: &mut BlockFlow, - input: &ISizeConstraintInput) - -> ISizeConstraintSolution { - let &ISizeConstraintInput { - computed_inline_size, - inline_start_margin, - inline_end_margin, - inline_start, - inline_end, - available_inline_size, - .. - } = input; - - // Check for direction of parent flow (NOT Containing Block) - let block_mode = block.base.writing_mode; - let container_mode = block.base.block_container_writing_mode; - - // FIXME (mbrubeck): Handle vertical writing modes. - let parent_has_same_direction = container_mode.is_bidi_ltr() == block_mode.is_bidi_ltr(); - - let (inline_start, inline_size, margin_inline_start, margin_inline_end) = - match (inline_start, inline_end, computed_inline_size) { - (MaybeAuto::Auto, MaybeAuto::Auto, MaybeAuto::Auto) => { - let margin_start = inline_start_margin.specified_or_zero(); - let margin_end = inline_end_margin.specified_or_zero(); - // Now it is the same situation as inline-start Specified and inline-end - // and inline-size Auto. - - // Set inline-end to zero to calculate inline-size. - let inline_size = - block.get_shrink_to_fit_inline_size(available_inline_size - - (margin_start + margin_end)); - (Au(0), inline_size, margin_start, margin_end) - } - (MaybeAuto::Specified(inline_start), - MaybeAuto::Specified(inline_end), - MaybeAuto::Specified(inline_size)) => { - match (inline_start_margin, inline_end_margin) { - (MaybeAuto::Auto, MaybeAuto::Auto) => { - let total_margin_val = - available_inline_size - inline_start - inline_end - inline_size; - if total_margin_val < Au(0) { - if parent_has_same_direction { - // margin-inline-start becomes 0 - (inline_start, inline_size, Au(0), total_margin_val) - } else { - // margin-inline-end becomes 0, because it's toward the parent's - // inline-start edge. - (inline_start, inline_size, total_margin_val, Au(0)) - } - } else { - // Equal margins - (inline_start, - inline_size, - total_margin_val.scale_by(0.5), - total_margin_val.scale_by(0.5)) - } - } - (MaybeAuto::Specified(margin_start), MaybeAuto::Auto) => { - let sum = inline_start + inline_end + inline_size + margin_start; - (inline_start, inline_size, margin_start, available_inline_size - sum) - } - (MaybeAuto::Auto, MaybeAuto::Specified(margin_end)) => { - let sum = inline_start + inline_end + inline_size + margin_end; - (inline_start, inline_size, available_inline_size - sum, margin_end) - } - (MaybeAuto::Specified(margin_start), MaybeAuto::Specified(margin_end)) => { - // Values are over-constrained. - let sum = inline_start + inline_size + margin_start + margin_end; - if parent_has_same_direction { - // Ignore value for 'inline-end' - (inline_start, inline_size, margin_start, margin_end) - } else { - // Ignore value for 'inline-start' - (available_inline_size - sum, - inline_size, - margin_start, - margin_end) - } - } - } - } - // For the rest of the cases, auto values for margin are set to 0 - - // If only one is Auto, solve for it - (MaybeAuto::Auto, - MaybeAuto::Specified(inline_end), - MaybeAuto::Specified(inline_size)) => { - let margin_start = inline_start_margin.specified_or_zero(); - let margin_end = inline_end_margin.specified_or_zero(); - let sum = inline_end + inline_size + margin_start + margin_end; - (available_inline_size - sum, inline_size, margin_start, margin_end) - } - (MaybeAuto::Specified(inline_start), - MaybeAuto::Auto, - MaybeAuto::Specified(inline_size)) => { - let margin_start = inline_start_margin.specified_or_zero(); - let margin_end = inline_end_margin.specified_or_zero(); - (inline_start, inline_size, margin_start, margin_end) - } - (MaybeAuto::Specified(inline_start), - MaybeAuto::Specified(inline_end), - MaybeAuto::Auto) => { - let margin_start = inline_start_margin.specified_or_zero(); - let margin_end = inline_end_margin.specified_or_zero(); - let sum = inline_start + inline_end + margin_start + margin_end; - (inline_start, available_inline_size - sum, margin_start, margin_end) - } - - // If inline-size is auto, then inline-size is shrink-to-fit. Solve for the - // non-auto value. - (MaybeAuto::Specified(inline_start), MaybeAuto::Auto, MaybeAuto::Auto) => { - let margin_start = inline_start_margin.specified_or_zero(); - let margin_end = inline_end_margin.specified_or_zero(); - // Set inline-end to zero to calculate inline-size - let inline_size = - block.get_shrink_to_fit_inline_size(available_inline_size - - (margin_start + margin_end)); - (inline_start, inline_size, margin_start, margin_end) - } - (MaybeAuto::Auto, MaybeAuto::Specified(inline_end), MaybeAuto::Auto) => { - let margin_start = inline_start_margin.specified_or_zero(); - let margin_end = inline_end_margin.specified_or_zero(); - // Set inline-start to zero to calculate inline-size - let inline_size = - block.get_shrink_to_fit_inline_size(available_inline_size - - (margin_start + margin_end)); - let sum = inline_end + inline_size + margin_start + margin_end; - (available_inline_size - sum, inline_size, margin_start, margin_end) - } - - (MaybeAuto::Auto, MaybeAuto::Auto, MaybeAuto::Specified(inline_size)) => { - let margin_start = inline_start_margin.specified_or_zero(); - let margin_end = inline_end_margin.specified_or_zero(); - // Setting 'inline-start' to static position because direction is 'ltr'. - // TODO: Handle 'rtl' when it is implemented. - (Au(0), inline_size, margin_start, margin_end) - } - }; - ISizeConstraintSolution::for_absolute_flow(inline_start, - inline_size, - margin_inline_start, - margin_inline_end) - } - - fn containing_block_inline_size(&self, - block: &mut BlockFlow, - _: Au, - shared_context: &SharedStyleContext) - -> Au { - let opaque_block = OpaqueFlow::from_flow(block); - block.containing_block_size(&shared_context.viewport_size(), opaque_block).inline - } - - fn set_inline_position_of_flow_if_necessary(&self, - block: &mut BlockFlow, - solution: ISizeConstraintSolution) { - // Set the inline position of the absolute flow wrt to its containing block. - if !block.base.flags.contains(FlowFlags::INLINE_POSITION_IS_STATIC) { - block.base.position.start.i = solution.inline_start; - } - } -} - -impl ISizeAndMarginsComputer for AbsoluteReplaced { - /// Solve the horizontal constraint equation for absolute replaced elements. - /// - /// CSS Section 10.3.8 - /// Constraint equation: - /// inline-start + inline-end + inline-size + margin-inline-start + margin-inline-end - /// = absolute containing block inline-size - (horizontal padding and border) - /// [aka available_inline-size] - /// - /// Return the solution for the equation. - fn solve_inline_size_constraints(&self, _: &mut BlockFlow, input: &ISizeConstraintInput) - -> ISizeConstraintSolution { - let &ISizeConstraintInput { - computed_inline_size, - inline_start_margin, - inline_end_margin, - inline_start, - inline_end, - available_inline_size, - .. - } = input; - // TODO: Check for direction of static-position Containing Block (aka - // parent flow, _not_ the actual Containing Block) when right-to-left - // is implemented - // Assume direction is 'ltr' for now - // TODO: Handle all the cases for 'rtl' direction. - - let inline_size = match computed_inline_size { - MaybeAuto::Specified(w) => w, - _ => panic!("{} {}", - "The used value for inline_size for absolute replaced flow", - "should have already been calculated by now.") - }; - - let (inline_start, inline_size, margin_inline_start, margin_inline_end) = - match (inline_start, inline_end) { - (MaybeAuto::Auto, MaybeAuto::Auto) => { - let margin_start = inline_start_margin.specified_or_zero(); - let margin_end = inline_end_margin.specified_or_zero(); - (Au(0), inline_size, margin_start, margin_end) - } - // If only one is Auto, solve for it - (MaybeAuto::Auto, MaybeAuto::Specified(inline_end)) => { - let margin_start = inline_start_margin.specified_or_zero(); - let margin_end = inline_end_margin.specified_or_zero(); - let sum = inline_end + inline_size + margin_start + margin_end; - (available_inline_size - sum, inline_size, margin_start, margin_end) - } - (MaybeAuto::Specified(inline_start), MaybeAuto::Auto) => { - let margin_start = inline_start_margin.specified_or_zero(); - let margin_end = inline_end_margin.specified_or_zero(); - (inline_start, inline_size, margin_start, margin_end) - } - (MaybeAuto::Specified(inline_start), MaybeAuto::Specified(inline_end)) => { - match (inline_start_margin, inline_end_margin) { - (MaybeAuto::Auto, MaybeAuto::Auto) => { - let total_margin_val = available_inline_size - inline_start - - inline_end - inline_size; - if total_margin_val < Au(0) { - // margin-inline-start becomes 0 because direction is 'ltr'. - (inline_start, inline_size, Au(0), total_margin_val) - } else { - // Equal margins - (inline_start, - inline_size, - total_margin_val.scale_by(0.5), - total_margin_val.scale_by(0.5)) - } - } - (MaybeAuto::Specified(margin_start), MaybeAuto::Auto) => { - let sum = inline_start + inline_end + inline_size + margin_start; - (inline_start, inline_size, margin_start, available_inline_size - sum) - } - (MaybeAuto::Auto, MaybeAuto::Specified(margin_end)) => { - let sum = inline_start + inline_end + inline_size + margin_end; - (inline_start, inline_size, available_inline_size - sum, margin_end) - } - (MaybeAuto::Specified(margin_start), MaybeAuto::Specified(margin_end)) => { - // Values are over-constrained. - // Ignore value for 'inline-end' cos direction is 'ltr'. - (inline_start, inline_size, margin_start, margin_end) - } - } - } - }; - ISizeConstraintSolution::for_absolute_flow(inline_start, - inline_size, - margin_inline_start, - margin_inline_end) - } - - /// Calculate used value of inline-size just like we do for inline replaced elements. - fn initial_computed_inline_size(&self, - block: &mut BlockFlow, - _: Au, - shared_context: &SharedStyleContext) - -> MaybeAuto { - let opaque_block = OpaqueFlow::from_flow(block); - let containing_block_inline_size = - block.containing_block_size(&shared_context.viewport_size(), opaque_block).inline; - let container_block_size = block.explicit_block_containing_size(shared_context); - let fragment = block.fragment(); - fragment.assign_replaced_inline_size_if_necessary(containing_block_inline_size, container_block_size); - // For replaced absolute flow, the rest of the constraint solving will - // take inline-size to be specified as the value computed here. - MaybeAuto::Specified(fragment.content_box().size.inline) - } - - fn containing_block_inline_size(&self, - block: &mut BlockFlow, - _: Au, - shared_context: &SharedStyleContext) - -> Au { - let opaque_block = OpaqueFlow::from_flow(block); - block.containing_block_size(&shared_context.viewport_size(), opaque_block).inline - } - - fn set_inline_position_of_flow_if_necessary(&self, - block: &mut BlockFlow, - solution: ISizeConstraintSolution) { - // Set the x-coordinate of the absolute flow wrt to its containing block. - block.base.position.start.i = solution.inline_start; - } -} - -impl ISizeAndMarginsComputer for BlockNonReplaced { - /// Compute inline-start and inline-end margins and inline-size. - fn solve_inline_size_constraints(&self, - block: &mut BlockFlow, - input: &ISizeConstraintInput) - -> ISizeConstraintSolution { - self.solve_block_inline_size_constraints(block, input) - } -} - -impl ISizeAndMarginsComputer for BlockReplaced { - /// Compute inline-start and inline-end margins and inline-size. - /// - /// ISize has already been calculated. We now calculate the margins just - /// like for non-replaced blocks. - fn solve_inline_size_constraints(&self, - block: &mut BlockFlow, - input: &ISizeConstraintInput) - -> ISizeConstraintSolution { - match input.computed_inline_size { - MaybeAuto::Specified(_) => {}, - MaybeAuto::Auto => { - panic!("BlockReplaced: inline_size should have been computed by now") - } - }; - self.solve_block_inline_size_constraints(block, input) - } - - /// Calculate used value of inline-size just like we do for inline replaced elements. - fn initial_computed_inline_size(&self, - block: &mut BlockFlow, - parent_flow_inline_size: Au, - shared_context: &SharedStyleContext) - -> MaybeAuto { - let container_block_size = block.explicit_block_containing_size(shared_context); - let fragment = block.fragment(); - fragment.assign_replaced_inline_size_if_necessary(parent_flow_inline_size, container_block_size); - // For replaced block flow, the rest of the constraint solving will - // take inline-size to be specified as the value computed here. - MaybeAuto::Specified(fragment.content_box().size.inline) - } - -} - -impl ISizeAndMarginsComputer for FloatNonReplaced { - /// CSS Section 10.3.5 - /// - /// If inline-size is computed as 'auto', the used value is the 'shrink-to-fit' inline-size. - fn solve_inline_size_constraints(&self, - block: &mut BlockFlow, - input: &ISizeConstraintInput) - -> ISizeConstraintSolution { - let (computed_inline_size, inline_start_margin, inline_end_margin, available_inline_size) = - (input.computed_inline_size, - input.inline_start_margin, - input.inline_end_margin, - input.available_inline_size); - let margin_inline_start = inline_start_margin.specified_or_zero(); - let margin_inline_end = inline_end_margin.specified_or_zero(); - let available_inline_size_float = available_inline_size - margin_inline_start - - margin_inline_end; - let shrink_to_fit = block.get_shrink_to_fit_inline_size(available_inline_size_float); - let inline_size = computed_inline_size.specified_or_default(shrink_to_fit); - debug!("assign_inline_sizes_float -- inline_size: {:?}", inline_size); - ISizeConstraintSolution::new(inline_size, margin_inline_start, margin_inline_end) - } -} - -impl ISizeAndMarginsComputer for FloatReplaced { - /// CSS Section 10.3.5 - /// - /// If inline-size is computed as 'auto', the used value is the 'shrink-to-fit' inline-size. - fn solve_inline_size_constraints(&self, _: &mut BlockFlow, input: &ISizeConstraintInput) - -> ISizeConstraintSolution { - let (computed_inline_size, inline_start_margin, inline_end_margin) = - (input.computed_inline_size, input.inline_start_margin, input.inline_end_margin); - let margin_inline_start = inline_start_margin.specified_or_zero(); - let margin_inline_end = inline_end_margin.specified_or_zero(); - let inline_size = match computed_inline_size { - MaybeAuto::Specified(w) => w, - MaybeAuto::Auto => panic!("FloatReplaced: inline_size should have been computed by now") - }; - debug!("assign_inline_sizes_float -- inline_size: {:?}", inline_size); - ISizeConstraintSolution::new(inline_size, margin_inline_start, margin_inline_end) - } - - /// Calculate used value of inline-size just like we do for inline replaced elements. - fn initial_computed_inline_size(&self, - block: &mut BlockFlow, - parent_flow_inline_size: Au, - shared_context: &SharedStyleContext) - -> MaybeAuto { - let container_block_size = block.explicit_block_containing_size(shared_context); - let fragment = block.fragment(); - fragment.assign_replaced_inline_size_if_necessary(parent_flow_inline_size, container_block_size); - // For replaced block flow, the rest of the constraint solving will - // take inline-size to be specified as the value computed here. - MaybeAuto::Specified(fragment.content_box().size.inline) - } -} - -impl ISizeAndMarginsComputer for InlineBlockNonReplaced { - /// Compute inline-start and inline-end margins and inline-size. - fn solve_inline_size_constraints(&self, - block: &mut BlockFlow, - input: &ISizeConstraintInput) - -> ISizeConstraintSolution { - let (computed_inline_size, - inline_start_margin, - inline_end_margin, - available_inline_size) = - (input.computed_inline_size, - input.inline_start_margin, - input.inline_end_margin, - input.available_inline_size); - - // For inline-blocks, `auto` margins compute to 0. - let inline_start_margin = inline_start_margin.specified_or_zero(); - let inline_end_margin = inline_end_margin.specified_or_zero(); - - // If inline-size is set to 'auto', and this is an inline block, use the - // shrink to fit algorithm (see CSS 2.1 § 10.3.9) - let inline_size = match computed_inline_size { - MaybeAuto::Auto => { - block.get_shrink_to_fit_inline_size(available_inline_size - (inline_start_margin + - inline_end_margin)) - } - MaybeAuto::Specified(inline_size) => inline_size, - }; - - ISizeConstraintSolution::new(inline_size, inline_start_margin, inline_end_margin) - } -} - -impl ISizeAndMarginsComputer for InlineBlockReplaced { - /// Compute inline-start and inline-end margins and inline-size. - /// - /// ISize has already been calculated. We now calculate the margins just - /// like for non-replaced blocks. - fn solve_inline_size_constraints(&self, - block: &mut BlockFlow, - input: &ISizeConstraintInput) - -> ISizeConstraintSolution { - debug_assert!(match input.computed_inline_size { - MaybeAuto::Specified(_) => true, - MaybeAuto::Auto => false, - }); - - let (computed_inline_size, - inline_start_margin, - inline_end_margin, - available_inline_size) = - (input.computed_inline_size, - input.inline_start_margin, - input.inline_end_margin, - input.available_inline_size); - - // For inline-blocks, `auto` margins compute to 0. - let inline_start_margin = inline_start_margin.specified_or_zero(); - let inline_end_margin = inline_end_margin.specified_or_zero(); - - // If inline-size is set to 'auto', and this is an inline block, use the - // shrink to fit algorithm (see CSS 2.1 § 10.3.9) - let inline_size = match computed_inline_size { - MaybeAuto::Auto => { - block.get_shrink_to_fit_inline_size(available_inline_size - (inline_start_margin + - inline_end_margin)) - } - MaybeAuto::Specified(inline_size) => inline_size, - }; - - ISizeConstraintSolution::new(inline_size, inline_start_margin, inline_end_margin) - } - - /// Calculate used value of inline-size just like we do for inline replaced elements. - fn initial_computed_inline_size(&self, - block: &mut BlockFlow, - parent_flow_inline_size: Au, - shared_context: &SharedStyleContext) - -> MaybeAuto { - let container_block_size = block.explicit_block_containing_size(shared_context); - let fragment = block.fragment(); - fragment.assign_replaced_inline_size_if_necessary(parent_flow_inline_size, container_block_size); - // For replaced block flow, the rest of the constraint solving will - // take inline-size to be specified as the value computed here. - MaybeAuto::Specified(fragment.content_box().size.inline) - } -} - -impl ISizeAndMarginsComputer for InlineFlexItem { - // Replace the default method directly to prevent recalculating and setting margins again - // which has already been set by its parent. - fn compute_used_inline_size(&self, - block: &mut BlockFlow, - shared_context: &SharedStyleContext, - parent_flow_inline_size: Au) { - let container_block_size = block.explicit_block_containing_size(shared_context); - block.fragment.assign_replaced_inline_size_if_necessary(parent_flow_inline_size, - container_block_size); - } - - // The used inline size and margins are set by parent flex flow, do nothing here. - fn solve_inline_size_constraints(&self, - block: &mut BlockFlow, - _: &ISizeConstraintInput) - -> ISizeConstraintSolution { - let fragment = block.fragment(); - ISizeConstraintSolution::new(fragment.border_box.size.inline, - fragment.margin.inline_start, - fragment.margin.inline_end) - } -} diff --git a/servo/components/layout/construct.rs b/servo/components/layout/construct.rs deleted file mode 100644 index dcbe79e3e8c2..000000000000 --- a/servo/components/layout/construct.rs +++ /dev/null @@ -1,2200 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -//! Creates flows and fragments from a DOM tree via a bottom-up, incremental traversal of the DOM. -//! -//! Each step of the traversal considers the node and existing flow, if there is one. If a node is -//! not dirty and an existing flow exists, then the traversal reuses that flow. Otherwise, it -//! proceeds to construct either a flow or a `ConstructionItem`. A construction item is a piece of -//! intermediate data that goes with a DOM node and hasn't found its "home" yet-maybe it's a box, -//! maybe it's an absolute or fixed position thing that hasn't found its containing block yet. -//! Construction items bubble up the tree from children to parents until they find their homes. - -#![deny(unsafe_code)] - -use ServoArc; -use block::BlockFlow; -use context::{LayoutContext, with_thread_local_font_context}; -use data::{LayoutDataFlags, LayoutData}; -use flex::FlexFlow; -use floats::FloatKind; -use flow::{AbsoluteDescendants, Flow, FlowClass, GetBaseFlow, ImmutableFlowUtils}; -use flow::{FlowFlags, MutableFlowUtils, MutableOwnedFlowUtils}; -use flow_ref::FlowRef; -use fragment::{CanvasFragmentInfo, ImageFragmentInfo, InlineAbsoluteFragmentInfo, SvgFragmentInfo}; -use fragment::{Fragment, GeneratedContentInfo, IframeFragmentInfo, FragmentFlags}; -use fragment::{InlineAbsoluteHypotheticalFragmentInfo, TableColumnFragmentInfo}; -use fragment::{InlineBlockFragmentInfo, SpecificFragmentInfo, UnscannedTextFragmentInfo}; -use fragment::WhitespaceStrippingResult; -use gfx::display_list::OpaqueNode; -use inline::{InlineFlow, InlineFragmentNodeInfo, InlineFragmentNodeFlags}; -use linked_list::prepend_from; -use list_item::{ListItemFlow, ListStyleTypeContent}; -use multicol::{MulticolColumnFlow, MulticolFlow}; -use parallel; -use script_layout_interface::{LayoutElementType, LayoutNodeType, is_image_data}; -use script_layout_interface::wrapper_traits::{PseudoElementType, ThreadSafeLayoutElement, ThreadSafeLayoutNode}; -use servo_config::opts; -use servo_url::ServoUrl; -use std::collections::LinkedList; -use std::marker::PhantomData; -use std::mem; -use std::sync::Arc; -use std::sync::atomic::Ordering; -use style::computed_values::caption_side::T as CaptionSide; -use style::computed_values::display::T as Display; -use style::computed_values::empty_cells::T as EmptyCells; -use style::computed_values::float::T as Float; -use style::computed_values::list_style_position::T as ListStylePosition; -use style::computed_values::position::T as Position; -use style::context::SharedStyleContext; -use style::dom::TElement; -use style::logical_geometry::Direction; -use style::properties::ComputedValues; -use style::selector_parser::{PseudoElement, RestyleDamage}; -use style::servo::restyle_damage::ServoRestyleDamage; -use style::values::computed::counters::ContentItem; -use style::values::generics::url::UrlOrNone as ImageUrlOrNone; -use table::TableFlow; -use table_caption::TableCaptionFlow; -use table_cell::TableCellFlow; -use table_colgroup::TableColGroupFlow; -use table_row::TableRowFlow; -use table_rowgroup::TableRowGroupFlow; -use table_wrapper::TableWrapperFlow; -use text::TextRunScanner; -use traversal::PostorderNodeMutTraversal; -use wrapper::{LayoutNodeLayoutData, TextContent, ThreadSafeLayoutNodeHelpers}; - -/// The results of flow construction for a DOM node. -#[derive(Clone)] -pub enum ConstructionResult { - /// This node contributes nothing at all (`display: none`). Alternately, this is what newly - /// created nodes have their `ConstructionResult` set to. - None, - - /// This node contributed a flow at the proper position in the tree. - /// Nothing more needs to be done for this node. It has bubbled up fixed - /// and absolute descendant flows that have a containing block above it. - Flow(FlowRef, AbsoluteDescendants), - - /// This node contributed some object or objects that will be needed to construct a proper flow - /// later up the tree, but these objects have not yet found their home. - ConstructionItem(ConstructionItem), -} - -impl ConstructionResult { - pub fn get(&mut self) -> ConstructionResult { - // FIXME(pcwalton): Stop doing this with inline fragments. Cloning fragments is very - // inefficient! - (*self).clone() - } - - pub fn debug_id(&self) -> usize { - match *self { - ConstructionResult::None => 0, - ConstructionResult::ConstructionItem(_) => 0, - ConstructionResult::Flow(ref flow_ref, _) => flow_ref.base().debug_id(), - } - } -} - -/// Represents the output of flow construction for a DOM node that has not yet resulted in a -/// complete flow. Construction items bubble up the tree until they find a `Flow` to be attached -/// to. -#[derive(Clone)] -pub enum ConstructionItem { - /// Inline fragments and associated {ib} splits that have not yet found flows. - InlineFragments(InlineFragmentsConstructionResult), - /// Potentially ignorable whitespace. - /// - /// FIXME(emilio): How could whitespace have any PseudoElementType other - /// than Normal? - Whitespace(OpaqueNode, PseudoElementType, ServoArc, RestyleDamage), - /// TableColumn Fragment - TableColumnFragment(Fragment), -} - -/// Represents inline fragments and {ib} splits that are bubbling up from an inline. -#[derive(Clone)] -pub struct InlineFragmentsConstructionResult { - /// Any {ib} splits that we're bubbling up. - pub splits: LinkedList, - - /// Any fragments that succeed the {ib} splits. - pub fragments: IntermediateInlineFragments, -} - -/// Represents an {ib} split that has not yet found the containing block that it belongs to. This -/// is somewhat tricky. An example may be helpful. For this DOM fragment: -/// -/// ```html -/// -/// A -///
B
-/// C -///
-/// ``` -/// -/// The resulting `ConstructionItem` for the outer `span` will be: -/// -/// ```rust,ignore -/// ConstructionItem::InlineFragments( -/// InlineFragmentsConstructionResult { -/// splits: linked_list![ -/// InlineBlockSplit { -/// predecessors: IntermediateInlineFragments { -/// fragments: linked_list![A], -/// absolute_descendents: AbsoluteDescendents { -/// descendant_links: vec![] -/// }, -/// }, -/// flow: B, -/// } -/// ], -/// fragments: linked_list![C], -/// }, -/// ) -/// ``` -#[derive(Clone)] -pub struct InlineBlockSplit { - /// The inline fragments that precede the flow. - pub predecessors: IntermediateInlineFragments, - - /// The flow that caused this {ib} split. - pub flow: FlowRef, -} - -impl InlineBlockSplit { - /// Flushes the given accumulator to the new split and makes a new accumulator to hold any - /// subsequent fragments. - fn new( - fragment_accumulator: &mut InlineFragmentsAccumulator, - node: &ConcreteThreadSafeLayoutNode, - style_context: &SharedStyleContext, - flow: FlowRef, - ) -> InlineBlockSplit { - fragment_accumulator.enclosing_node.as_mut().expect( - "enclosing_node is None; Are {ib} splits being generated outside of an inline node?" - ).flags.remove(InlineFragmentNodeFlags::LAST_FRAGMENT_OF_ELEMENT); - - let split = InlineBlockSplit { - predecessors: mem::replace( - fragment_accumulator, - InlineFragmentsAccumulator::from_inline_node( - node, - style_context, - )).to_intermediate_inline_fragments::(style_context), - flow: flow, - }; - - fragment_accumulator.enclosing_node.as_mut().unwrap().flags.remove( - InlineFragmentNodeFlags::FIRST_FRAGMENT_OF_ELEMENT); - - split - } -} - -/// Holds inline fragments and absolute descendants. -#[derive(Clone)] -pub struct IntermediateInlineFragments { - /// The list of fragments. - pub fragments: LinkedList, - - /// The list of absolute descendants of those inline fragments. - pub absolute_descendants: AbsoluteDescendants, -} - -impl IntermediateInlineFragments { - fn new() -> IntermediateInlineFragments { - IntermediateInlineFragments { - fragments: LinkedList::new(), - absolute_descendants: AbsoluteDescendants::new(), - } - } - - fn is_empty(&self) -> bool { - self.fragments.is_empty() && self.absolute_descendants.is_empty() - } - - fn push_all(&mut self, mut other: IntermediateInlineFragments) { - self.fragments.append(&mut other.fragments); - self.absolute_descendants.push_descendants(other.absolute_descendants); - } -} - -/// Holds inline fragments that we're gathering for children of an inline node. -struct InlineFragmentsAccumulator { - /// The list of fragments. - fragments: IntermediateInlineFragments, - - /// Information about the inline box directly enclosing the fragments being gathered, if any. - /// - /// `inline::InlineFragmentNodeInfo` also stores flags indicating whether a fragment is the - /// first and/or last of the corresponding inline box. This `InlineFragmentsAccumulator` may - /// represent only one side of an {ib} split, so we store these flags as if it represented only - /// one fragment. `to_intermediate_inline_fragments` later splits this hypothetical fragment - /// into pieces, leaving the `FIRST_FRAGMENT_OF_ELEMENT` and `LAST_FRAGMENT_OF_ELEMENT` flags, - /// if present, on the first and last fragments of the output. - enclosing_node: Option, - - /// Restyle damage to use for fragments created in this node. - restyle_damage: RestyleDamage, - - /// Bidi control characters to insert before and after these fragments. - bidi_control_chars: Option<(&'static str, &'static str)>, -} - -impl InlineFragmentsAccumulator { - fn new() -> InlineFragmentsAccumulator { - InlineFragmentsAccumulator { - fragments: IntermediateInlineFragments::new(), - enclosing_node: None, - bidi_control_chars: None, - restyle_damage: RestyleDamage::empty(), - } - } - - fn from_inline_node(node: &N, style_context: &SharedStyleContext) -> InlineFragmentsAccumulator - where N: ThreadSafeLayoutNode { - InlineFragmentsAccumulator { - fragments: IntermediateInlineFragments::new(), - enclosing_node: Some(InlineFragmentNodeInfo { - address: node.opaque(), - pseudo: node.get_pseudo_element_type(), - style: node.style(style_context), - selected_style: node.selected_style(), - flags: InlineFragmentNodeFlags::FIRST_FRAGMENT_OF_ELEMENT | - InlineFragmentNodeFlags::LAST_FRAGMENT_OF_ELEMENT, - }), - bidi_control_chars: None, - restyle_damage: node.restyle_damage(), - } - } - - fn push(&mut self, fragment: Fragment) { - self.fragments.fragments.push_back(fragment) - } - - fn push_all(&mut self, mut fragments: IntermediateInlineFragments) { - self.fragments.fragments.append(&mut fragments.fragments); - self.fragments.absolute_descendants.push_descendants(fragments.absolute_descendants); - } - - fn to_intermediate_inline_fragments( - self, - context: &SharedStyleContext, - ) -> IntermediateInlineFragments - where - N: ThreadSafeLayoutNode, - { - let InlineFragmentsAccumulator { - mut fragments, - enclosing_node, - bidi_control_chars, - restyle_damage, - } = self; - if let Some(mut enclosing_node) = enclosing_node { - let fragment_count = fragments.fragments.len(); - for (index, fragment) in fragments.fragments.iter_mut().enumerate() { - let mut enclosing_node = enclosing_node.clone(); - if index != 0 { - enclosing_node.flags.remove(InlineFragmentNodeFlags::FIRST_FRAGMENT_OF_ELEMENT) - } - if index != fragment_count - 1 { - enclosing_node.flags.remove(InlineFragmentNodeFlags::LAST_FRAGMENT_OF_ELEMENT) - } - fragment.add_inline_context_style(enclosing_node); - } - - // Control characters are later discarded in transform_text, so they don't affect the - // is_first/is_last styles above. - enclosing_node.flags.remove(InlineFragmentNodeFlags::FIRST_FRAGMENT_OF_ELEMENT | - InlineFragmentNodeFlags::LAST_FRAGMENT_OF_ELEMENT); - - if let Some((start, end)) = bidi_control_chars { - fragments.fragments.push_front( - control_chars_to_fragment::( - &enclosing_node, - context, - start, - restyle_damage, - ) - ); - fragments.fragments.push_back( - control_chars_to_fragment::( - &enclosing_node, - context, - end, - restyle_damage, - ) - ); - } - } - fragments - } -} - -/// An object that knows how to create flows. -pub struct FlowConstructor<'a, N: ThreadSafeLayoutNode> { - /// The layout context. - pub layout_context: &'a LayoutContext<'a>, - /// Satisfy the compiler about the unused parameters, which we use to improve the ergonomics of - /// the ensuing impl {} by removing the need to parameterize all the methods individually. - phantom2: PhantomData, -} - -impl<'a, ConcreteThreadSafeLayoutNode: ThreadSafeLayoutNode> - FlowConstructor<'a, ConcreteThreadSafeLayoutNode> { - /// Creates a new flow constructor. - pub fn new(layout_context: &'a LayoutContext<'a>) -> Self { - FlowConstructor { - layout_context: layout_context, - phantom2: PhantomData, - } - } - - #[inline] - fn style_context(&self) -> &SharedStyleContext { - self.layout_context.shared_context() - } - - #[inline] - fn set_flow_construction_result(&self, - node: &ConcreteThreadSafeLayoutNode, - result: ConstructionResult) { - node.set_flow_construction_result(result); - } - - /// Builds the fragment for the given block or subclass thereof. - fn build_fragment_for_block(&self, node: &ConcreteThreadSafeLayoutNode) -> Fragment { - let specific_fragment_info = match node.type_id() { - Some(LayoutNodeType::Element(LayoutElementType::HTMLIFrameElement)) => { - SpecificFragmentInfo::Iframe(IframeFragmentInfo::new(node)) - } - Some(LayoutNodeType::Element(LayoutElementType::HTMLImageElement)) => { - let image_info = Box::new(ImageFragmentInfo::new( - node.image_url(), node, &self.layout_context - )); - SpecificFragmentInfo::Image(image_info) - } - Some(LayoutNodeType::Element(LayoutElementType::HTMLObjectElement)) => { - let image_info = Box::new(ImageFragmentInfo::new( - node.object_data(), node, &self.layout_context - )); - SpecificFragmentInfo::Image(image_info) - } - Some(LayoutNodeType::Element(LayoutElementType::HTMLTableElement)) => { - SpecificFragmentInfo::TableWrapper - } - Some(LayoutNodeType::Element(LayoutElementType::HTMLTableColElement)) => { - SpecificFragmentInfo::TableColumn(TableColumnFragmentInfo::new(node)) - } - Some(LayoutNodeType::Element(LayoutElementType::HTMLTableCellElement)) => { - SpecificFragmentInfo::TableCell - } - Some(LayoutNodeType::Element(LayoutElementType::HTMLTableRowElement)) | - Some(LayoutNodeType::Element(LayoutElementType::HTMLTableSectionElement)) => { - SpecificFragmentInfo::TableRow - } - Some(LayoutNodeType::Element(LayoutElementType::HTMLCanvasElement)) => { - let data = node.canvas_data().unwrap(); - SpecificFragmentInfo::Canvas(Box::new(CanvasFragmentInfo::new(data))) - } - Some(LayoutNodeType::Element(LayoutElementType::SVGSVGElement)) => { - let data = node.svg_data().unwrap(); - SpecificFragmentInfo::Svg(Box::new(SvgFragmentInfo::new(data))) - } - _ => { - // This includes pseudo-elements. - SpecificFragmentInfo::Generic - } - }; - - Fragment::new(node, specific_fragment_info, self.layout_context) - } - - /// Creates an inline flow from a set of inline fragments, then adds it as a child of the given - /// flow or pushes it onto the given flow list. - /// - /// `#[inline(always)]` because this is performance critical and LLVM will not inline it - /// otherwise. - #[inline(always)] - fn flush_inline_fragments_to_flow( - &mut self, - fragment_accumulator: InlineFragmentsAccumulator, - flow: &mut FlowRef, - absolute_descendants: &mut AbsoluteDescendants, - legalizer: &mut Legalizer, - node: &ConcreteThreadSafeLayoutNode, - ) { - let mut fragments = - fragment_accumulator.to_intermediate_inline_fragments::( - self.style_context(), - ); - if fragments.is_empty() { - return - }; - - strip_ignorable_whitespace_from_start(&mut fragments.fragments); - strip_ignorable_whitespace_from_end(&mut fragments.fragments); - if fragments.fragments.is_empty() { - absolute_descendants.push_descendants(fragments.absolute_descendants); - return - } - - // Build a list of all the inline-block fragments before fragments is moved. - let mut inline_block_flows = vec!(); - for fragment in &fragments.fragments { - match fragment.specific { - SpecificFragmentInfo::InlineBlock(ref info) => { - inline_block_flows.push(info.flow_ref.clone()) - } - SpecificFragmentInfo::InlineAbsoluteHypothetical(ref info) => { - inline_block_flows.push(info.flow_ref.clone()) - } - SpecificFragmentInfo::InlineAbsolute(ref info) => { - inline_block_flows.push(info.flow_ref.clone()) - } - _ => {} - } - } - - // We must scan for runs before computing minimum ascent and descent because scanning - // for runs might collapse so much whitespace away that only hypothetical fragments - // remain. In that case the inline flow will compute its ascent and descent to be zero. - let scanned_fragments = - with_thread_local_font_context(self.layout_context, |font_context| { - TextRunScanner::new().scan_for_runs(font_context, - mem::replace(&mut fragments.fragments, LinkedList::new())) - }); - let mut inline_flow_ref = - FlowRef::new(Arc::new(InlineFlow::from_fragments(scanned_fragments, - node.style(self.style_context()).writing_mode))); - - // Add all the inline-block fragments as children of the inline flow. - for inline_block_flow in &inline_block_flows { - inline_flow_ref.add_new_child(inline_block_flow.clone()); - } - - // Set up absolute descendants as necessary. - // - // The inline flow itself may need to become the containing block for absolute descendants - // in order to handle cases like: - // - //
- // - // - // - //
- // - // See the comment above `flow::AbsoluteDescendantInfo` for more information. - inline_flow_ref.take_applicable_absolute_descendants(&mut fragments.absolute_descendants); - absolute_descendants.push_descendants(fragments.absolute_descendants); - - { - // FIXME(#6503): Use Arc::get_mut().unwrap() here. - let inline_flow = FlowRef::deref_mut(&mut inline_flow_ref).as_mut_inline(); - inline_flow.minimum_line_metrics = - with_thread_local_font_context(self.layout_context, |font_context| { - inline_flow.minimum_line_metrics(font_context, &node.style(self.style_context())) - }); - } - - inline_flow_ref.finish(); - legalizer.add_child::( - self.style_context(), - flow, - inline_flow_ref, - ) - } - - fn build_block_flow_using_construction_result_of_child( - &mut self, - flow: &mut FlowRef, - node: &ConcreteThreadSafeLayoutNode, - kid: ConcreteThreadSafeLayoutNode, - inline_fragment_accumulator: &mut InlineFragmentsAccumulator, - abs_descendants: &mut AbsoluteDescendants, - legalizer: &mut Legalizer) { - match kid.get_construction_result() { - ConstructionResult::None => {} - ConstructionResult::Flow(kid_flow, kid_abs_descendants) => { - // If kid_flow is TableCaptionFlow, kid_flow should be added under - // TableWrapperFlow. - if flow.is_table() && kid_flow.is_table_caption() { - let construction_result = - ConstructionResult::Flow(kid_flow, AbsoluteDescendants::new()); - self.set_flow_construction_result(&kid, construction_result) - } else { - if !kid_flow.base().flags.contains(FlowFlags::IS_ABSOLUTELY_POSITIONED) { - // Flush any inline fragments that we were gathering up. This allows us to - // handle {ib} splits. - let old_inline_fragment_accumulator = - mem::replace(inline_fragment_accumulator, - InlineFragmentsAccumulator::new()); - self.flush_inline_fragments_to_flow(old_inline_fragment_accumulator, - flow, - abs_descendants, - legalizer, - node); - } - legalizer.add_child::( - self.style_context(), - flow, - kid_flow, - ) - } - abs_descendants.push_descendants(kid_abs_descendants); - } - ConstructionResult::ConstructionItem(ConstructionItem::InlineFragments( - InlineFragmentsConstructionResult { - splits, - fragments: successor_fragments, - })) => { - // Add any {ib} splits. - for split in splits { - // Pull apart the {ib} split object and push its predecessor fragments - // onto the list. - let InlineBlockSplit { - predecessors, - flow: kid_flow - } = split; - inline_fragment_accumulator.push_all(predecessors); - - // Flush any inline fragments that we were gathering up. - debug!("flushing {} inline box(es) to flow A", - inline_fragment_accumulator.fragments.fragments.len()); - let old_inline_fragment_accumulator = - mem::replace(inline_fragment_accumulator, - InlineFragmentsAccumulator::new()); - let absolute_descendants = - &mut inline_fragment_accumulator.fragments.absolute_descendants; - self.flush_inline_fragments_to_flow(old_inline_fragment_accumulator, - flow, - absolute_descendants, - legalizer, - node); - - // Push the flow generated by the {ib} split onto our list of flows. - legalizer.add_child::( - self.style_context(), - flow, - kid_flow, - ) - } - - // Add the fragments to the list we're maintaining. - inline_fragment_accumulator.push_all(successor_fragments); - } - ConstructionResult::ConstructionItem(ConstructionItem::Whitespace( - whitespace_node, - whitespace_pseudo, - whitespace_style, - whitespace_damage)) => { - // Add whitespace results. They will be stripped out later on when - // between block elements, and retained when between inline elements. - let fragment_info = SpecificFragmentInfo::UnscannedText( - Box::new(UnscannedTextFragmentInfo::new(Box::::from(" "), None)) - ); - let fragment = Fragment::from_opaque_node_and_style(whitespace_node, - whitespace_pseudo, - whitespace_style, - node.selected_style(), - whitespace_damage, - fragment_info); - inline_fragment_accumulator.fragments.fragments.push_back(fragment); - } - ConstructionResult::ConstructionItem(ConstructionItem::TableColumnFragment(_)) => { - // TODO: Implement anonymous table objects for missing parents - // CSS 2.1 § 17.2.1, step 3-2 - } - } - } - - /// Constructs a block flow, beginning with the given `initial_fragments` if present and then - /// appending the construction results of children to the child list of the block flow. {ib} - /// splits and absolutely-positioned descendants are handled correctly. - fn build_flow_for_block_starting_with_fragments( - &mut self, - mut flow: FlowRef, - node: &ConcreteThreadSafeLayoutNode, - initial_fragments: IntermediateInlineFragments) - -> ConstructionResult { - // Gather up fragments for the inline flows we might need to create. - let mut inline_fragment_accumulator = InlineFragmentsAccumulator::new(); - - inline_fragment_accumulator.fragments.push_all(initial_fragments); - - // List of absolute descendants, in tree order. - let mut abs_descendants = AbsoluteDescendants::new(); - let mut legalizer = Legalizer::new(); - if !node.is_replaced_content() { - for kid in node.children() { - if kid.get_pseudo_element_type() != PseudoElementType::Normal { - self.process(&kid); - } - - self.build_block_flow_using_construction_result_of_child( - &mut flow, - node, - kid, - &mut inline_fragment_accumulator, - &mut abs_descendants, - &mut legalizer); - } - } - - // Perform a final flush of any inline fragments that we were gathering up to handle {ib} - // splits, after stripping ignorable whitespace. - self.flush_inline_fragments_to_flow(inline_fragment_accumulator, - &mut flow, - &mut abs_descendants, - &mut legalizer, - node); - - // The flow is done. - legalizer.finish(&mut flow); - flow.finish(); - - // Set up the absolute descendants. - if flow.is_absolute_containing_block() { - // This is the containing block for all the absolute descendants. - flow.set_absolute_descendants(abs_descendants); - - abs_descendants = AbsoluteDescendants::new(); - if flow.base().flags.contains(FlowFlags::IS_ABSOLUTELY_POSITIONED) { - // This is now the only absolute flow in the subtree which hasn't yet - // reached its CB. - abs_descendants.push(flow.clone()); - } - } - ConstructionResult::Flow(flow, abs_descendants) - } - - /// Constructs a flow for the given block node and its children. This method creates an - /// initial fragment as appropriate and then dispatches to - /// `build_flow_for_block_starting_with_fragments`. Currently the following kinds of flows get - /// initial content: - /// - /// * Generated content gets the initial content specified by the `content` attribute of the - /// CSS. - /// * `` and `",k.noCloneChecked=!!b.cloneNode(!0).lastChild.defaultValue,c.appendChild(b),b.innerHTML="",k.checkClone=b.cloneNode(!0).cloneNode(!0).lastChild.checked,k.noCloneEvent=!0,b.attachEvent&&(b.attachEvent("onclick",function(){k.noCloneEvent=!1}),b.cloneNode(!0).click()),null==k.deleteExpando){k.deleteExpando=!0;try{delete b.test}catch(d){k.deleteExpando=!1}}}(),function(){var b,c,d=y.createElement("div");for(b in{submit:!0,change:!0,focusin:!0})c="on"+b,(k[b+"Bubbles"]=c in a)||(d.setAttribute(c,"t"),k[b+"Bubbles"]=d.attributes[c].expando===!1);d=null}();var X=/^(?:input|select|textarea)$/i,Y=/^key/,Z=/^(?:mouse|pointer|contextmenu)|click/,$=/^(?:focusinfocus|focusoutblur)$/,_=/^([^.]*)(?:\.(.+)|)$/;function ab(){return!0}function bb(){return!1}function cb(){try{return y.activeElement}catch(a){}}m.event={global:{},add:function(a,b,c,d,e){var f,g,h,i,j,k,l,n,o,p,q,r=m._data(a);if(r){c.handler&&(i=c,c=i.handler,e=i.selector),c.guid||(c.guid=m.guid++),(g=r.events)||(g=r.events={}),(k=r.handle)||(k=r.handle=function(a){return typeof m===K||a&&m.event.triggered===a.type?void 0:m.event.dispatch.apply(k.elem,arguments)},k.elem=a),b=(b||"").match(E)||[""],h=b.length;while(h--)f=_.exec(b[h])||[],o=q=f[1],p=(f[2]||"").split(".").sort(),o&&(j=m.event.special[o]||{},o=(e?j.delegateType:j.bindType)||o,j=m.event.special[o]||{},l=m.extend({type:o,origType:q,data:d,handler:c,guid:c.guid,selector:e,needsContext:e&&m.expr.match.needsContext.test(e),namespace:p.join(".")},i),(n=g[o])||(n=g[o]=[],n.delegateCount=0,j.setup&&j.setup.call(a,d,p,k)!==!1||(a.addEventListener?a.addEventListener(o,k,!1):a.attachEvent&&a.attachEvent("on"+o,k))),j.add&&(j.add.call(a,l),l.handler.guid||(l.handler.guid=c.guid)),e?n.splice(n.delegateCount++,0,l):n.push(l),m.event.global[o]=!0);a=null}},remove:function(a,b,c,d,e){var f,g,h,i,j,k,l,n,o,p,q,r=m.hasData(a)&&m._data(a);if(r&&(k=r.events)){b=(b||"").match(E)||[""],j=b.length;while(j--)if(h=_.exec(b[j])||[],o=q=h[1],p=(h[2]||"").split(".").sort(),o){l=m.event.special[o]||{},o=(d?l.delegateType:l.bindType)||o,n=k[o]||[],h=h[2]&&new RegExp("(^|\\.)"+p.join("\\.(?:.*\\.|)")+"(\\.|$)"),i=f=n.length;while(f--)g=n[f],!e&&q!==g.origType||c&&c.guid!==g.guid||h&&!h.test(g.namespace)||d&&d!==g.selector&&("**"!==d||!g.selector)||(n.splice(f,1),g.selector&&n.delegateCount--,l.remove&&l.remove.call(a,g));i&&!n.length&&(l.teardown&&l.teardown.call(a,p,r.handle)!==!1||m.removeEvent(a,o,r.handle),delete k[o])}else for(o in k)m.event.remove(a,o+b[j],c,d,!0);m.isEmptyObject(k)&&(delete r.handle,m._removeData(a,"events"))}},trigger:function(b,c,d,e){var f,g,h,i,k,l,n,o=[d||y],p=j.call(b,"type")?b.type:b,q=j.call(b,"namespace")?b.namespace.split("."):[];if(h=l=d=d||y,3!==d.nodeType&&8!==d.nodeType&&!$.test(p+m.event.triggered)&&(p.indexOf(".")>=0&&(q=p.split("."),p=q.shift(),q.sort()),g=p.indexOf(":")<0&&"on"+p,b=b[m.expando]?b:new m.Event(p,"object"==typeof b&&b),b.isTrigger=e?2:3,b.namespace=q.join("."),b.namespace_re=b.namespace?new RegExp("(^|\\.)"+q.join("\\.(?:.*\\.|)")+"(\\.|$)"):null,b.result=void 0,b.target||(b.target=d),c=null==c?[b]:m.makeArray(c,[b]),k=m.event.special[p]||{},e||!k.trigger||k.trigger.apply(d,c)!==!1)){if(!e&&!k.noBubble&&!m.isWindow(d)){for(i=k.delegateType||p,$.test(i+p)||(h=h.parentNode);h;h=h.parentNode)o.push(h),l=h;l===(d.ownerDocument||y)&&o.push(l.defaultView||l.parentWindow||a)}n=0;while((h=o[n++])&&!b.isPropagationStopped())b.type=n>1?i:k.bindType||p,f=(m._data(h,"events")||{})[b.type]&&m._data(h,"handle"),f&&f.apply(h,c),f=g&&h[g],f&&f.apply&&m.acceptData(h)&&(b.result=f.apply(h,c),b.result===!1&&b.preventDefault());if(b.type=p,!e&&!b.isDefaultPrevented()&&(!k._default||k._default.apply(o.pop(),c)===!1)&&m.acceptData(d)&&g&&d[p]&&!m.isWindow(d)){l=d[g],l&&(d[g]=null),m.event.triggered=p;try{d[p]()}catch(r){}m.event.triggered=void 0,l&&(d[g]=l)}return b.result}},dispatch:function(a){a=m.event.fix(a);var b,c,e,f,g,h=[],i=d.call(arguments),j=(m._data(this,"events")||{})[a.type]||[],k=m.event.special[a.type]||{};if(i[0]=a,a.delegateTarget=this,!k.preDispatch||k.preDispatch.call(this,a)!==!1){h=m.event.handlers.call(this,a,j),b=0;while((f=h[b++])&&!a.isPropagationStopped()){a.currentTarget=f.elem,g=0;while((e=f.handlers[g++])&&!a.isImmediatePropagationStopped())(!a.namespace_re||a.namespace_re.test(e.namespace))&&(a.handleObj=e,a.data=e.data,c=((m.event.special[e.origType]||{}).handle||e.handler).apply(f.elem,i),void 0!==c&&(a.result=c)===!1&&(a.preventDefault(),a.stopPropagation()))}return k.postDispatch&&k.postDispatch.call(this,a),a.result}},handlers:function(a,b){var c,d,e,f,g=[],h=b.delegateCount,i=a.target;if(h&&i.nodeType&&(!a.button||"click"!==a.type))for(;i!=this;i=i.parentNode||this)if(1===i.nodeType&&(i.disabled!==!0||"click"!==a.type)){for(e=[],f=0;h>f;f++)d=b[f],c=d.selector+" ",void 0===e[c]&&(e[c]=d.needsContext?m(c,this).index(i)>=0:m.find(c,this,null,[i]).length),e[c]&&e.push(d);e.length&&g.push({elem:i,handlers:e})}return h]","i"),hb=/^\s+/,ib=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/gi,jb=/<([\w:]+)/,kb=/\s*$/g,rb={option:[1,""],legend:[1,"
","
"],area:[1,"",""],param:[1,"",""],thead:[1,"","
"],tr:[2,"","
"],col:[2,"","
"],td:[3,"","
"],_default:k.htmlSerialize?[0,"",""]:[1,"X
","
"]},sb=db(y),tb=sb.appendChild(y.createElement("div"));rb.optgroup=rb.option,rb.tbody=rb.tfoot=rb.colgroup=rb.caption=rb.thead,rb.th=rb.td;function ub(a,b){var c,d,e=0,f=typeof a.getElementsByTagName!==K?a.getElementsByTagName(b||"*"):typeof a.querySelectorAll!==K?a.querySelectorAll(b||"*"):void 0;if(!f)for(f=[],c=a.childNodes||a;null!=(d=c[e]);e++)!b||m.nodeName(d,b)?f.push(d):m.merge(f,ub(d,b));return void 0===b||b&&m.nodeName(a,b)?m.merge([a],f):f}function vb(a){W.test(a.type)&&(a.defaultChecked=a.checked)}function wb(a,b){return m.nodeName(a,"table")&&m.nodeName(11!==b.nodeType?b:b.firstChild,"tr")?a.getElementsByTagName("tbody")[0]||a.appendChild(a.ownerDocument.createElement("tbody")):a}function xb(a){return a.type=(null!==m.find.attr(a,"type"))+"/"+a.type,a}function yb(a){var b=pb.exec(a.type);return b?a.type=b[1]:a.removeAttribute("type"),a}function zb(a,b){for(var c,d=0;null!=(c=a[d]);d++)m._data(c,"globalEval",!b||m._data(b[d],"globalEval"))}function Ab(a,b){if(1===b.nodeType&&m.hasData(a)){var c,d,e,f=m._data(a),g=m._data(b,f),h=f.events;if(h){delete g.handle,g.events={};for(c in h)for(d=0,e=h[c].length;e>d;d++)m.event.add(b,c,h[c][d])}g.data&&(g.data=m.extend({},g.data))}}function Bb(a,b){var c,d,e;if(1===b.nodeType){if(c=b.nodeName.toLowerCase(),!k.noCloneEvent&&b[m.expando]){e=m._data(b);for(d in e.events)m.removeEvent(b,d,e.handle);b.removeAttribute(m.expando)}"script"===c&&b.text!==a.text?(xb(b).text=a.text,yb(b)):"object"===c?(b.parentNode&&(b.outerHTML=a.outerHTML),k.html5Clone&&a.innerHTML&&!m.trim(b.innerHTML)&&(b.innerHTML=a.innerHTML)):"input"===c&&W.test(a.type)?(b.defaultChecked=b.checked=a.checked,b.value!==a.value&&(b.value=a.value)):"option"===c?b.defaultSelected=b.selected=a.defaultSelected:("input"===c||"textarea"===c)&&(b.defaultValue=a.defaultValue)}}m.extend({clone:function(a,b,c){var d,e,f,g,h,i=m.contains(a.ownerDocument,a);if(k.html5Clone||m.isXMLDoc(a)||!gb.test("<"+a.nodeName+">")?f=a.cloneNode(!0):(tb.innerHTML=a.outerHTML,tb.removeChild(f=tb.firstChild)),!(k.noCloneEvent&&k.noCloneChecked||1!==a.nodeType&&11!==a.nodeType||m.isXMLDoc(a)))for(d=ub(f),h=ub(a),g=0;null!=(e=h[g]);++g)d[g]&&Bb(e,d[g]);if(b)if(c)for(h=h||ub(a),d=d||ub(f),g=0;null!=(e=h[g]);g++)Ab(e,d[g]);else Ab(a,f);return d=ub(f,"script"),d.length>0&&zb(d,!i&&ub(a,"script")),d=h=e=null,f},buildFragment:function(a,b,c,d){for(var e,f,g,h,i,j,l,n=a.length,o=db(b),p=[],q=0;n>q;q++)if(f=a[q],f||0===f)if("object"===m.type(f))m.merge(p,f.nodeType?[f]:f);else if(lb.test(f)){h=h||o.appendChild(b.createElement("div")),i=(jb.exec(f)||["",""])[1].toLowerCase(),l=rb[i]||rb._default,h.innerHTML=l[1]+f.replace(ib,"<$1>")+l[2],e=l[0];while(e--)h=h.lastChild;if(!k.leadingWhitespace&&hb.test(f)&&p.push(b.createTextNode(hb.exec(f)[0])),!k.tbody){f="table"!==i||kb.test(f)?""!==l[1]||kb.test(f)?0:h:h.firstChild,e=f&&f.childNodes.length;while(e--)m.nodeName(j=f.childNodes[e],"tbody")&&!j.childNodes.length&&f.removeChild(j)}m.merge(p,h.childNodes),h.textContent="";while(h.firstChild)h.removeChild(h.firstChild);h=o.lastChild}else p.push(b.createTextNode(f));h&&o.removeChild(h),k.appendChecked||m.grep(ub(p,"input"),vb),q=0;while(f=p[q++])if((!d||-1===m.inArray(f,d))&&(g=m.contains(f.ownerDocument,f),h=ub(o.appendChild(f),"script"),g&&zb(h),c)){e=0;while(f=h[e++])ob.test(f.type||"")&&c.push(f)}return h=null,o},cleanData:function(a,b){for(var d,e,f,g,h=0,i=m.expando,j=m.cache,l=k.deleteExpando,n=m.event.special;null!=(d=a[h]);h++)if((b||m.acceptData(d))&&(f=d[i],g=f&&j[f])){if(g.events)for(e in g.events)n[e]?m.event.remove(d,e):m.removeEvent(d,e,g.handle);j[f]&&(delete j[f],l?delete d[i]:typeof d.removeAttribute!==K?d.removeAttribute(i):d[i]=null,c.push(f))}}}),m.fn.extend({text:function(a){return V(this,function(a){return void 0===a?m.text(this):this.empty().append((this[0]&&this[0].ownerDocument||y).createTextNode(a))},null,a,arguments.length)},append:function(){return this.domManip(arguments,function(a){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var b=wb(this,a);b.appendChild(a)}})},prepend:function(){return this.domManip(arguments,function(a){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var b=wb(this,a);b.insertBefore(a,b.firstChild)}})},before:function(){return this.domManip(arguments,function(a){this.parentNode&&this.parentNode.insertBefore(a,this)})},after:function(){return this.domManip(arguments,function(a){this.parentNode&&this.parentNode.insertBefore(a,this.nextSibling)})},remove:function(a,b){for(var c,d=a?m.filter(a,this):this,e=0;null!=(c=d[e]);e++)b||1!==c.nodeType||m.cleanData(ub(c)),c.parentNode&&(b&&m.contains(c.ownerDocument,c)&&zb(ub(c,"script")),c.parentNode.removeChild(c));return this},empty:function(){for(var a,b=0;null!=(a=this[b]);b++){1===a.nodeType&&m.cleanData(ub(a,!1));while(a.firstChild)a.removeChild(a.firstChild);a.options&&m.nodeName(a,"select")&&(a.options.length=0)}return this},clone:function(a,b){return a=null==a?!1:a,b=null==b?a:b,this.map(function(){return m.clone(this,a,b)})},html:function(a){return V(this,function(a){var b=this[0]||{},c=0,d=this.length;if(void 0===a)return 1===b.nodeType?b.innerHTML.replace(fb,""):void 0;if(!("string"!=typeof a||mb.test(a)||!k.htmlSerialize&&gb.test(a)||!k.leadingWhitespace&&hb.test(a)||rb[(jb.exec(a)||["",""])[1].toLowerCase()])){a=a.replace(ib,"<$1>");try{for(;d>c;c++)b=this[c]||{},1===b.nodeType&&(m.cleanData(ub(b,!1)),b.innerHTML=a);b=0}catch(e){}}b&&this.empty().append(a)},null,a,arguments.length)},replaceWith:function(){var a=arguments[0];return this.domManip(arguments,function(b){a=this.parentNode,m.cleanData(ub(this)),a&&a.replaceChild(b,this)}),a&&(a.length||a.nodeType)?this:this.remove()},detach:function(a){return this.remove(a,!0)},domManip:function(a,b){a=e.apply([],a);var c,d,f,g,h,i,j=0,l=this.length,n=this,o=l-1,p=a[0],q=m.isFunction(p);if(q||l>1&&"string"==typeof p&&!k.checkClone&&nb.test(p))return this.each(function(c){var d=n.eq(c);q&&(a[0]=p.call(this,c,d.html())),d.domManip(a,b)});if(l&&(i=m.buildFragment(a,this[0].ownerDocument,!1,this),c=i.firstChild,1===i.childNodes.length&&(i=c),c)){for(g=m.map(ub(i,"script"),xb),f=g.length;l>j;j++)d=i,j!==o&&(d=m.clone(d,!0,!0),f&&m.merge(g,ub(d,"script"))),b.call(this[j],d,j);if(f)for(h=g[g.length-1].ownerDocument,m.map(g,yb),j=0;f>j;j++)d=g[j],ob.test(d.type||"")&&!m._data(d,"globalEval")&&m.contains(h,d)&&(d.src?m._evalUrl&&m._evalUrl(d.src):m.globalEval((d.text||d.textContent||d.innerHTML||"").replace(qb,"")));i=c=null}return this}}),m.each({appendTo:"append",prependTo:"prepend",insertBefore:"before",insertAfter:"after",replaceAll:"replaceWith"},function(a,b){m.fn[a]=function(a){for(var c,d=0,e=[],g=m(a),h=g.length-1;h>=d;d++)c=d===h?this:this.clone(!0),m(g[d])[b](c),f.apply(e,c.get());return this.pushStack(e)}});var Cb,Db={};function Eb(b,c){var d,e=m(c.createElement(b)).appendTo(c.body),f=a.getDefaultComputedStyle&&(d=a.getDefaultComputedStyle(e[0]))?d.display:m.css(e[0],"display");return e.detach(),f}function Fb(a){var b=y,c=Db[a];return c||(c=Eb(a,b),"none"!==c&&c||(Cb=(Cb||m(" - diff --git a/servo/tests/html/incremental_float.html b/servo/tests/html/incremental_float.html deleted file mode 100644 index f1d0adc08d87..000000000000 --- a/servo/tests/html/incremental_float.html +++ /dev/null @@ -1,20 +0,0 @@ - - -
- -
-

Mouse over the preceding gray square. It should change color but remain in place.

- diff --git a/servo/tests/html/incremental_inline_line_flush_mode.html b/servo/tests/html/incremental_inline_line_flush_mode.html deleted file mode 100644 index 508c6878b8ae..000000000000 --- a/servo/tests/html/incremental_inline_line_flush_mode.html +++ /dev/null @@ -1,6 +0,0 @@ - - -
-Foo
Bar
- diff --git a/servo/tests/html/inline-block-split-2.html b/servo/tests/html/inline-block-split-2.html deleted file mode 100644 index e17ad7d327b9..000000000000 --- a/servo/tests/html/inline-block-split-2.html +++ /dev/null @@ -1,20 +0,0 @@ - - - -Anonymous text interrupted by a block - - - -

-This is anonymous text before the SPAN. -This is the content of SPAN. -This is anonymous text after the SPAN. -

-

- - - diff --git a/servo/tests/html/inline-block-split-3.html b/servo/tests/html/inline-block-split-3.html deleted file mode 100644 index 726fcaa5469a..000000000000 --- a/servo/tests/html/inline-block-split-3.html +++ /dev/null @@ -1,20 +0,0 @@ - - - -Anonymous text interrupted by a block - - - -

-This is anonymous text

before the SPAN. -This is the content of SPAN. -This is anonymous text after the SPAN. -

-

- - - diff --git a/servo/tests/html/inline-block-split-float.html b/servo/tests/html/inline-block-split-float.html deleted file mode 100644 index 4fddc940880c..000000000000 --- a/servo/tests/html/inline-block-split-float.html +++ /dev/null @@ -1,24 +0,0 @@ - - - -Float {ib} split - - - -This is anonymous text before the DIV.
This is the content of DIV.
This is anonymous text after the DIV.

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nunc gravida metus ac nisl faucibus imperdiet. Curabitur vitae nisl vitae mi viverra vehicula. Curabitur porta augue nec ante consequat iaculis. Donec accumsan, est eget blandit vestibulum, est tellus auctor est, in sodales justo nulla sit amet massa. Etiam in est felis. Morbi aliquam leo ac dolor suscipit vestibulum. Nam sagittis enim sodales lacus interdum rutrum. Nulla eu diam sit amet nunc imperdiet venenatis id eget ligula. Mauris vulputate viverra diam vel laoreet. Donec pharetra facilisis lorem, ut auctor risus sagittis eget. Nullam imperdiet lacinia justo in mattis. Nam ornare enim eu mauris aliquet ullamcorper. Nulla neque felis, bibendum dapibus eros ac, malesuada pellentesque nunc. Vivamus et purus vel orci feugiat vestibulum eget a erat. - -Praesent a lectus ut mi tempor rhoncus. Curabitur quis mollis libero, sed sagittis risus. Cras eget risus molestie, sollicitudin nunc eu, convallis nisl. Aliquam suscipit ornare lorem, sed sollicitudin diam pharetra eu. Curabitur sit amet ligula malesuada, lobortis dolor in, convallis lorem. Pellentesque porta augue erat, sit amet venenatis enim aliquet in. Donec velit sapien, fringilla ac nisl vitae, cursus auctor elit. Aenean posuere est rhoncus eros adipiscing condimentum. In quis massa tellus. Quisque ultricies tristique nisi in consectetur. Etiam in gravida nibh, facilisis vehicula nisi. Etiam velit sem, sodales sit amet metus laoreet, tristique vestibulum est. Donec porta sollicitudin neque, ut sollicitudin lectus ullamcorper ut. Aenean tincidunt est id odio elementum, eget sollicitudin massa sollicitudin. - -Sed nec mi massa. In consequat in ante sit amet accumsan. Donec fermentum, felis a commodo sagittis, nibh nisi iaculis erat, vitae tempus nisl nunc nec ligula. Etiam quis faucibus lorem. Ut vel auctor leo, blandit ultrices arcu. Praesent vitae porttitor felis. Cras placerat odio a suscipit ornare. Sed iaculis molestie felis, quis gravida nisi pulvinar ac. Vivamus consequat turpis id purus posuere, pulvinar pellentesque massa rutrum. - -Pellentesque venenatis congue turpis non placerat. Quisque tempus ipsum nec velit imperdiet, sed vulputate leo consequat. Phasellus hendrerit metus non eros aliquam, eu ornare ipsum malesuada. Sed vitae dolor suscipit, suscipit nisi nec, dictum risus. Sed accumsan libero eu tincidunt interdum. Pellentesque in ipsum ac lectus gravida cursus et a dolor. Morbi arcu nulla, semper non consectetur elementum, tincidunt pharetra felis. Nunc nunc nulla, scelerisque sed diam eget, faucibus ornare nibh. - -Pellentesque vitae hendrerit arcu. Aliquam rhoncus nisi fermentum nulla adipiscing volutpat. Fusce ut porta eros. Aliquam commodo, neque vitae mattis volutpat, sem nisi laoreet mi, sed laoreet erat orci at sapien. Cras feugiat quis tellus vitae facilisis. Sed a lacus nec nisl facilisis dictum eget elementum diam. Nunc cursus vulputate leo ut placerat. Curabitur congue, erat eu vulputate bibendum, sapien augue pharetra arcu, vel pharetra arcu risus nec mauris.

- diff --git a/servo/tests/html/inline-block-split.html b/servo/tests/html/inline-block-split.html deleted file mode 100644 index 8ec36869035f..000000000000 --- a/servo/tests/html/inline-block-split.html +++ /dev/null @@ -1,13 +0,0 @@ - - - -{ib} split - - -
- Some text -

More text -

- - - diff --git a/servo/tests/html/inline-pseudo-repair-jumpiness.html b/servo/tests/html/inline-pseudo-repair-jumpiness.html deleted file mode 100644 index d95c12f939cc..000000000000 --- a/servo/tests/html/inline-pseudo-repair-jumpiness.html +++ /dev/null @@ -1 +0,0 @@ -a
b diff --git a/servo/tests/html/inline_bg_color_simple.html b/servo/tests/html/inline_bg_color_simple.html deleted file mode 100644 index ab09c8e5d8a3..000000000000 --- a/servo/tests/html/inline_bg_color_simple.html +++ /dev/null @@ -1,11 +0,0 @@ - - - - [block background color test] -

paragraph yellow

- - [inline background color test] - span bluetexttexttextspan yellownested-span redtest finishes - - - diff --git a/servo/tests/html/input_whitespace_regression.html b/servo/tests/html/input_whitespace_regression.html deleted file mode 100644 index 61cc78e73466..000000000000 --- a/servo/tests/html/input_whitespace_regression.html +++ /dev/null @@ -1,7 +0,0 @@ - -Both input elements below should have more than one space between "foo" and "bar": - -
- - -
diff --git a/servo/tests/html/ligatures.html b/servo/tests/html/ligatures.html deleted file mode 100644 index a7ed1765750b..000000000000 --- a/servo/tests/html/ligatures.html +++ /dev/null @@ -1,7 +0,0 @@ - - - -
-A fellow suffix with some waffles sending a letter, while playing a tutti fb fh tf. -
- diff --git a/servo/tests/html/lineheight-simple.css b/servo/tests/html/lineheight-simple.css deleted file mode 100644 index 6baa2fa488a9..000000000000 --- a/servo/tests/html/lineheight-simple.css +++ /dev/null @@ -1,10 +0,0 @@ -#larger1 { - font-size: 20px; - line-height: 2; -} - -#larger2 { - font-size: 30px; - line-height: 3; -} - diff --git a/servo/tests/html/lineheight-simple.html b/servo/tests/html/lineheight-simple.html deleted file mode 100644 index f9c748da88b0..000000000000 --- a/servo/tests/html/lineheight-simple.html +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - -
Regular font Even larger with line-height 2
-
line-height 3!
- - diff --git a/servo/tests/html/linuxcon.html b/servo/tests/html/linuxcon.html deleted file mode 100644 index 4d2c09f4cd6e..000000000000 --- a/servo/tests/html/linuxcon.html +++ /dev/null @@ -1,61 +0,0 @@ - - - - - - -
-
- - frame one -
-
-
-
- - frame two -
-
- - diff --git a/servo/tests/html/lipsum-large.html b/servo/tests/html/lipsum-large.html deleted file mode 100644 index 30a77b4df0da..000000000000 --- a/servo/tests/html/lipsum-large.html +++ /dev/null @@ -1,36 +0,0 @@ - -
- - -Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nunc volutpat feugiat fermentum. Curabitur luctus consequat urna a tincidunt. Nullam vitae velit eu arcu congue volutpat in a diam. Pellentesque lacus ipsum, gravida et tristique sit amet, varius eu ipsum. Duis venenatis sem id nibh commodo tempor. Curabitur risus tellus, cursus quis pellentesque sed, elementum eget neque. Sed ultricies, orci et adipiscing dapibus, mauris nisi condimentum felis, ac euismod tellus nunc vel felis. Aliquam egestas accumsan turpis, a volutpat dui fermentum id. Aliquam erat volutpat. Nunc vel auctor odio. Donec eu posuere dolor. Donec vitae justo purus, nec bibendum lectus. Quisque elit tortor, tristique vel ultricies sed, euismod sed tellus. Nullam dolor purus, porta et hendrerit id, rhoncus eu lectus. Nam vel lorem at dui mattis pretium eget a nisi. - -Quisque eleifend risus non metus gravida ac semper odio aliquam. Praesent sed risus in tellus congue convallis. Quisque et magna tellus, in ornare leo. Nunc tempor interdum tortor, non blandit risus rhoncus et. Aliquam pulvinar est sed massa ornare sit amet ornare ligula commodo. Nunc porta ultricies tempor. Phasellus gravida accumsan auctor. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Proin quis enim tortor. Curabitur pretium diam a arcu rutrum sed sagittis velit placerat. Ut ut mauris quam, luctus iaculis sem. Nulla quis purus quis lacus cursus imperdiet a quis dolor. Nullam hendrerit eros faucibus ante dignissim vel pharetra ligula viverra. Lorem ipsum dolor sit amet, consectetur adipiscing elit. - -Nunc gravida massa quis nisl venenatis interdum. Integer non dui tortor, non volutpat nisi. In porta accumsan scelerisque. Nunc elementum urna non metus scelerisque ac condimentum eros volutpat. Donec eget nibh condimentum quam tempor vulputate non vel turpis. Quisque suscipit blandit mi quis iaculis. Ut iaculis, nisi ac tristique fringilla, nulla dui interdum lectus, a consectetur mi sapien a metus. Cras eu dolor non dolor imperdiet faucibus. Vestibulum porta risus vel neque convallis elementum. Aenean auctor, turpis eu molestie ultrices, mauris felis sodales est, at iaculis augue libero eu turpis. Curabitur sit amet est quis orci volutpat viverra dignissim in elit. Cras suscipit tristique quam in tincidunt. Aliquam imperdiet libero id dolor egestas viverra egestas arcu posuere. Pellentesque enim risus, accumsan quis ullamcorper ac, malesuada vitae leo. - -Cras ullamcorper vestibulum eros nec suscipit. Vivamus tincidunt, metus at tristique sodales, metus massa sagittis elit, eu scelerisque tortor ante ut sapien. Curabitur rutrum fringilla purus, eget commodo neque tincidunt ut. Etiam ac leo sed nisi ultricies ultrices sed in urna. Fusce blandit fermentum ipsum, vitae dapibus eros tempus vel. Praesent ullamcorper nulla sed nisl facilisis aliquam. Mauris consequat dui quis elit pulvinar vitae pellentesque sapien tempor. Sed accumsan consequat tortor, eget hendrerit lectus rhoncus nec. Mauris diam neque, congue ut laoreet a, hendrerit sit amet sem. Donec eget diam orci, ac vehicula orci. Ut sollicitudin ultricies arcu ut faucibus. Nulla felis nisl, auctor eget adipiscing sit amet, sagittis et est. Cras elit nisi, placerat quis tincidunt at, dapibus et arcu. Donec fermentum eleifend pretium. Nullam at posuere nulla. Phasellus at urna a arcu aliquam ullamcorper eget et ligula. - -Curabitur fermentum libero vitae libero mattis pulvinar. Vivamus luctus laoreet vulputate. Nunc dictum eros a nulla fringilla quis vestibulum ante malesuada. Suspendisse aliquam vulputate consequat. Duis eu sem eu justo convallis dictum sed ut arcu. Mauris porttitor nulla a augue iaculis posuere euismod mi scelerisque. Maecenas sodales nisi eu turpis fermentum dapibus. Morbi viverra iaculis magna, sed congue justo semper at. Nunc in mi enim. Ut aliquam mi et ligula molestie ac bibendum leo egestas. Nullam molestie, urna ac interdum auctor, dolor diam aliquam ligula, vitae gravida mi orci a tortor. Donec et felis turpis, id lobortis nunc. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Integer feugiat sagittis dictum. Donec mauris ante, feugiat sed ultricies ut, elementum a purus. Sed porta lectus et sem blandit vehicula. - -Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nunc volutpat feugiat fermentum. Curabitur luctus consequat urna a tincidunt. Nullam vitae velit eu arcu congue volutpat in a diam. Pellentesque lacus ipsum, gravida et tristique sit amet, varius eu ipsum. Duis venenatis sem id nibh commodo tempor. Curabitur risus tellus, cursus quis pellentesque sed, elementum eget neque. Sed ultricies, orci et adipiscing dapibus, mauris nisi condimentum felis, ac euismod tellus nunc vel felis. Aliquam egestas accumsan turpis, a volutpat dui fermentum id. Aliquam erat volutpat. Nunc vel auctor odio. Donec eu posuere dolor. Donec vitae justo purus, nec bibendum lectus. Quisque elit tortor, tristique vel ultricies sed, euismod sed tellus. Nullam dolor purus, porta et hendrerit id, rhoncus eu lectus. Nam vel lorem at dui mattis pretium eget a nisi. - -Quisque eleifend risus non metus gravida ac semper odio aliquam. Praesent sed risus in tellus congue convallis. Quisque et magna tellus, in ornare leo. Nunc tempor interdum tortor, non blandit risus rhoncus et. Aliquam pulvinar est sed massa ornare sit amet ornare ligula commodo. Nunc porta ultricies tempor. Phasellus gravida accumsan auctor. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Proin quis enim tortor. Curabitur pretium diam a arcu rutrum sed sagittis velit placerat. Ut ut mauris quam, luctus iaculis sem. Nulla quis purus quis lacus cursus imperdiet a quis dolor. Nullam hendrerit eros faucibus ante dignissim vel pharetra ligula viverra. Lorem ipsum dolor sit amet, consectetur adipiscing elit. - -Nunc gravida massa quis nisl venenatis interdum. Integer non dui tortor, non volutpat nisi. In porta accumsan scelerisque. Nunc elementum urna non metus scelerisque ac condimentum eros volutpat. Donec eget nibh condimentum quam tempor vulputate non vel turpis. Quisque suscipit blandit mi quis iaculis. Ut iaculis, nisi ac tristique fringilla, nulla dui interdum lectus, a consectetur mi sapien a metus. Cras eu dolor non dolor imperdiet faucibus. Vestibulum porta risus vel neque convallis elementum. Aenean auctor, turpis eu molestie ultrices, mauris felis sodales est, at iaculis augue libero eu turpis. Curabitur sit amet est quis orci volutpat viverra dignissim in elit. Cras suscipit tristique quam in tincidunt. Aliquam imperdiet libero id dolor egestas viverra egestas arcu posuere. Pellentesque enim risus, accumsan quis ullamcorper ac, malesuada vitae leo. - -Cras ullamcorper vestibulum eros nec suscipit. Vivamus tincidunt, metus at tristique sodales, metus massa sagittis elit, eu scelerisque tortor ante ut sapien. Curabitur rutrum fringilla purus, eget commodo neque tincidunt ut. Etiam ac leo sed nisi ultricies ultrices sed in urna. Fusce blandit fermentum ipsum, vitae dapibus eros tempus vel. Praesent ullamcorper nulla sed nisl facilisis aliquam. Mauris consequat dui quis elit pulvinar vitae pellentesque sapien tempor. Sed accumsan consequat tortor, eget hendrerit lectus rhoncus nec. Mauris diam neque, congue ut laoreet a, hendrerit sit amet sem. Donec eget diam orci, ac vehicula orci. Ut sollicitudin ultricies arcu ut faucibus. Nulla felis nisl, auctor eget adipiscing sit amet, sagittis et est. Cras elit nisi, placerat quis tincidunt at, dapibus et arcu. Donec fermentum eleifend pretium. Nullam at posuere nulla. Phasellus at urna a arcu aliquam ullamcorper eget et ligula. - -Curabitur fermentum libero vitae libero mattis pulvinar. Vivamus luctus laoreet vulputate. Nunc dictum eros a nulla fringilla quis vestibulum ante malesuada. Suspendisse aliquam vulputate consequat. Duis eu sem eu justo convallis dictum sed ut arcu. Mauris porttitor nulla a augue iaculis posuere euismod mi scelerisque. Maecenas sodales nisi eu turpis fermentum dapibus. Morbi viverra iaculis magna, sed congue justo semper at. Nunc in mi enim. Ut aliquam mi et ligula molestie ac bibendum leo egestas. Nullam molestie, urna ac interdum auctor, dolor diam aliquam ligula, vitae gravida mi orci a tortor. Donec et felis turpis, id lobortis nunc. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Integer feugiat sagittis dictum. Donec mauris ante, feugiat sed ultricies ut, elementum a purus. Sed porta lectus et sem blandit vehicula. - -Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nunc volutpat feugiat fermentum. Curabitur luctus consequat urna a tincidunt. Nullam vitae velit eu arcu congue volutpat in a diam. Pellentesque lacus ipsum, gravida et tristique sit amet, varius eu ipsum. Duis venenatis sem id nibh commodo tempor. Curabitur risus tellus, cursus quis pellentesque sed, elementum eget neque. Sed ultricies, orci et adipiscing dapibus, mauris nisi condimentum felis, ac euismod tellus nunc vel felis. Aliquam egestas accumsan turpis, a volutpat dui fermentum id. Aliquam erat volutpat. Nunc vel auctor odio. Donec eu posuere dolor. Donec vitae justo purus, nec bibendum lectus. Quisque elit tortor, tristique vel ultricies sed, euismod sed tellus. Nullam dolor purus, porta et hendrerit id, rhoncus eu lectus. Nam vel lorem at dui mattis pretium eget a nisi. - -Quisque eleifend risus non metus gravida ac semper odio aliquam. Praesent sed risus in tellus congue convallis. Quisque et magna tellus, in ornare leo. Nunc tempor interdum tortor, non blandit risus rhoncus et. Aliquam pulvinar est sed massa ornare sit amet ornare ligula commodo. Nunc porta ultricies tempor. Phasellus gravida accumsan auctor. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Proin quis enim tortor. Curabitur pretium diam a arcu rutrum sed sagittis velit placerat. Ut ut mauris quam, luctus iaculis sem. Nulla quis purus quis lacus cursus imperdiet a quis dolor. Nullam hendrerit eros faucibus ante dignissim vel pharetra ligula viverra. Lorem ipsum dolor sit amet, consectetur adipiscing elit. - -Nunc gravida massa quis nisl venenatis interdum. Integer non dui tortor, non volutpat nisi. In porta accumsan scelerisque. Nunc elementum urna non metus scelerisque ac condimentum eros volutpat. Donec eget nibh condimentum quam tempor vulputate non vel turpis. Quisque suscipit blandit mi quis iaculis. Ut iaculis, nisi ac tristique fringilla, nulla dui interdum lectus, a consectetur mi sapien a metus. Cras eu dolor non dolor imperdiet faucibus. Vestibulum porta risus vel neque convallis elementum. Aenean auctor, turpis eu molestie ultrices, mauris felis sodales est, at iaculis augue libero eu turpis. Curabitur sit amet est quis orci volutpat viverra dignissim in elit. Cras suscipit tristique quam in tincidunt. Aliquam imperdiet libero id dolor egestas viverra egestas arcu posuere. Pellentesque enim risus, accumsan quis ullamcorper ac, malesuada vitae leo. - -Cras ullamcorper vestibulum eros nec suscipit. Vivamus tincidunt, metus at tristique sodales, metus massa sagittis elit, eu scelerisque tortor ante ut sapien. Curabitur rutrum fringilla purus, eget commodo neque tincidunt ut. Etiam ac leo sed nisi ultricies ultrices sed in urna. Fusce blandit fermentum ipsum, vitae dapibus eros tempus vel. Praesent ullamcorper nulla sed nisl facilisis aliquam. Mauris consequat dui quis elit pulvinar vitae pellentesque sapien tempor. Sed accumsan consequat tortor, eget hendrerit lectus rhoncus nec. Mauris diam neque, congue ut laoreet a, hendrerit sit amet sem. Donec eget diam orci, ac vehicula orci. Ut sollicitudin ultricies arcu ut faucibus. Nulla felis nisl, auctor eget adipiscing sit amet, sagittis et est. Cras elit nisi, placerat quis tincidunt at, dapibus et arcu. Donec fermentum eleifend pretium. Nullam at posuere nulla. Phasellus at urna a arcu aliquam ullamcorper eget et ligula. - -Curabitur fermentum libero vitae libero mattis pulvinar. Vivamus luctus laoreet vulputate. Nunc dictum eros a nulla fringilla quis vestibulum ante malesuada. Suspendisse aliquam vulputate consequat. Duis eu sem eu justo convallis dictum sed ut arcu. Mauris porttitor nulla a augue iaculis posuere euismod mi scelerisque. Maecenas sodales nisi eu turpis fermentum dapibus. Morbi viverra iaculis magna, sed congue justo semper at. Nunc in mi enim. Ut aliquam mi et ligula molestie ac bibendum leo egestas. Nullam molestie, urna ac interdum auctor, dolor diam aliquam ligula, vitae gravida mi orci a tortor. Donec et felis turpis, id lobortis nunc. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Integer feugiat sagittis dictum. Donec mauris ante, feugiat sed ultricies ut, elementum a purus. Sed porta lectus et sem blandit vehicula. - -
- diff --git a/servo/tests/html/lipsum.html b/servo/tests/html/lipsum.html deleted file mode 100644 index 1adceee1c2ee..000000000000 --- a/servo/tests/html/lipsum.html +++ /dev/null @@ -1,36 +0,0 @@ - -
- - -Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nunc volutpat feugiat fermentum. Curabitur luctus consequat urna a tincidunt. Nullam vitae velit eu arcu congue volutpat in a diam. Pellentesque lacus ipsum, gravida et tristique sit amet, varius eu ipsum. Duis venenatis sem id nibh commodo tempor. Curabitur risus tellus, cursus quis pellentesque sed, elementum eget neque. Sed ultricies, orci et adipiscing dapibus, mauris nisi condimentum felis, ac euismod tellus nunc vel felis. Aliquam egestas accumsan turpis, a volutpat dui fermentum id. Aliquam erat volutpat. Nunc vel auctor odio. Donec eu posuere dolor. Donec vitae justo purus, nec bibendum lectus. Quisque elit tortor, tristique vel ultricies sed, euismod sed tellus. Nullam dolor purus, porta et hendrerit id, rhoncus eu lectus. Nam vel lorem at dui mattis pretium eget a nisi. - -Quisque eleifend risus non metus gravida ac semper odio aliquam. Praesent sed risus in tellus congue convallis. Quisque et magna tellus, in ornare leo. Nunc tempor interdum tortor, non blandit risus rhoncus et. Aliquam pulvinar est sed massa ornare sit amet ornare ligula commodo. Nunc porta ultricies tempor. Phasellus gravida accumsan auctor. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Proin quis enim tortor. Curabitur pretium diam a arcu rutrum sed sagittis velit placerat. Ut ut mauris quam, luctus iaculis sem. Nulla quis purus quis lacus cursus imperdiet a quis dolor. Nullam hendrerit eros faucibus ante dignissim vel pharetra ligula viverra. Lorem ipsum dolor sit amet, consectetur adipiscing elit. - -Nunc gravida massa quis nisl venenatis interdum. Integer non dui tortor, non volutpat nisi. In porta accumsan scelerisque. Nunc elementum urna non metus scelerisque ac condimentum eros volutpat. Donec eget nibh condimentum quam tempor vulputate non vel turpis. Quisque suscipit blandit mi quis iaculis. Ut iaculis, nisi ac tristique fringilla, nulla dui interdum lectus, a consectetur mi sapien a metus. Cras eu dolor non dolor imperdiet faucibus. Vestibulum porta risus vel neque convallis elementum. Aenean auctor, turpis eu molestie ultrices, mauris felis sodales est, at iaculis augue libero eu turpis. Curabitur sit amet est quis orci volutpat viverra dignissim in elit. Cras suscipit tristique quam in tincidunt. Aliquam imperdiet libero id dolor egestas viverra egestas arcu posuere. Pellentesque enim risus, accumsan quis ullamcorper ac, malesuada vitae leo. - -Cras ullamcorper vestibulum eros nec suscipit. Vivamus tincidunt, metus at tristique sodales, metus massa sagittis elit, eu scelerisque tortor ante ut sapien. Curabitur rutrum fringilla purus, eget commodo neque tincidunt ut. Etiam ac leo sed nisi ultricies ultrices sed in urna. Fusce blandit fermentum ipsum, vitae dapibus eros tempus vel. Praesent ullamcorper nulla sed nisl facilisis aliquam. Mauris consequat dui quis elit pulvinar vitae pellentesque sapien tempor. Sed accumsan consequat tortor, eget hendrerit lectus rhoncus nec. Mauris diam neque, congue ut laoreet a, hendrerit sit amet sem. Donec eget diam orci, ac vehicula orci. Ut sollicitudin ultricies arcu ut faucibus. Nulla felis nisl, auctor eget adipiscing sit amet, sagittis et est. Cras elit nisi, placerat quis tincidunt at, dapibus et arcu. Donec fermentum eleifend pretium. Nullam at posuere nulla. Phasellus at urna a arcu aliquam ullamcorper eget et ligula. - -Curabitur fermentum libero vitae libero mattis pulvinar. Vivamus luctus laoreet vulputate. Nunc dictum eros a nulla fringilla quis vestibulum ante malesuada. Suspendisse aliquam vulputate consequat. Duis eu sem eu justo convallis dictum sed ut arcu. Mauris porttitor nulla a augue iaculis posuere euismod mi scelerisque. Maecenas sodales nisi eu turpis fermentum dapibus. Morbi viverra iaculis magna, sed congue justo semper at. Nunc in mi enim. Ut aliquam mi et ligula molestie ac bibendum leo egestas. Nullam molestie, urna ac interdum auctor, dolor diam aliquam ligula, vitae gravida mi orci a tortor. Donec et felis turpis, id lobortis nunc. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Integer feugiat sagittis dictum. Donec mauris ante, feugiat sed ultricies ut, elementum a purus. Sed porta lectus et sem blandit vehicula. - -Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nunc volutpat feugiat fermentum. Curabitur luctus consequat urna a tincidunt. Nullam vitae velit eu arcu congue volutpat in a diam. Pellentesque lacus ipsum, gravida et tristique sit amet, varius eu ipsum. Duis venenatis sem id nibh commodo tempor. Curabitur risus tellus, cursus quis pellentesque sed, elementum eget neque. Sed ultricies, orci et adipiscing dapibus, mauris nisi condimentum felis, ac euismod tellus nunc vel felis. Aliquam egestas accumsan turpis, a volutpat dui fermentum id. Aliquam erat volutpat. Nunc vel auctor odio. Donec eu posuere dolor. Donec vitae justo purus, nec bibendum lectus. Quisque elit tortor, tristique vel ultricies sed, euismod sed tellus. Nullam dolor purus, porta et hendrerit id, rhoncus eu lectus. Nam vel lorem at dui mattis pretium eget a nisi. - -Quisque eleifend risus non metus gravida ac semper odio aliquam. Praesent sed risus in tellus congue convallis. Quisque et magna tellus, in ornare leo. Nunc tempor interdum tortor, non blandit risus rhoncus et. Aliquam pulvinar est sed massa ornare sit amet ornare ligula commodo. Nunc porta ultricies tempor. Phasellus gravida accumsan auctor. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Proin quis enim tortor. Curabitur pretium diam a arcu rutrum sed sagittis velit placerat. Ut ut mauris quam, luctus iaculis sem. Nulla quis purus quis lacus cursus imperdiet a quis dolor. Nullam hendrerit eros faucibus ante dignissim vel pharetra ligula viverra. Lorem ipsum dolor sit amet, consectetur adipiscing elit. - -Nunc gravida massa quis nisl venenatis interdum. Integer non dui tortor, non volutpat nisi. In porta accumsan scelerisque. Nunc elementum urna non metus scelerisque ac condimentum eros volutpat. Donec eget nibh condimentum quam tempor vulputate non vel turpis. Quisque suscipit blandit mi quis iaculis. Ut iaculis, nisi ac tristique fringilla, nulla dui interdum lectus, a consectetur mi sapien a metus. Cras eu dolor non dolor imperdiet faucibus. Vestibulum porta risus vel neque convallis elementum. Aenean auctor, turpis eu molestie ultrices, mauris felis sodales est, at iaculis augue libero eu turpis. Curabitur sit amet est quis orci volutpat viverra dignissim in elit. Cras suscipit tristique quam in tincidunt. Aliquam imperdiet libero id dolor egestas viverra egestas arcu posuere. Pellentesque enim risus, accumsan quis ullamcorper ac, malesuada vitae leo. - -Cras ullamcorper vestibulum eros nec suscipit. Vivamus tincidunt, metus at tristique sodales, metus massa sagittis elit, eu scelerisque tortor ante ut sapien. Curabitur rutrum fringilla purus, eget commodo neque tincidunt ut. Etiam ac leo sed nisi ultricies ultrices sed in urna. Fusce blandit fermentum ipsum, vitae dapibus eros tempus vel. Praesent ullamcorper nulla sed nisl facilisis aliquam. Mauris consequat dui quis elit pulvinar vitae pellentesque sapien tempor. Sed accumsan consequat tortor, eget hendrerit lectus rhoncus nec. Mauris diam neque, congue ut laoreet a, hendrerit sit amet sem. Donec eget diam orci, ac vehicula orci. Ut sollicitudin ultricies arcu ut faucibus. Nulla felis nisl, auctor eget adipiscing sit amet, sagittis et est. Cras elit nisi, placerat quis tincidunt at, dapibus et arcu. Donec fermentum eleifend pretium. Nullam at posuere nulla. Phasellus at urna a arcu aliquam ullamcorper eget et ligula. - -Curabitur fermentum libero vitae libero mattis pulvinar. Vivamus luctus laoreet vulputate. Nunc dictum eros a nulla fringilla quis vestibulum ante malesuada. Suspendisse aliquam vulputate consequat. Duis eu sem eu justo convallis dictum sed ut arcu. Mauris porttitor nulla a augue iaculis posuere euismod mi scelerisque. Maecenas sodales nisi eu turpis fermentum dapibus. Morbi viverra iaculis magna, sed congue justo semper at. Nunc in mi enim. Ut aliquam mi et ligula molestie ac bibendum leo egestas. Nullam molestie, urna ac interdum auctor, dolor diam aliquam ligula, vitae gravida mi orci a tortor. Donec et felis turpis, id lobortis nunc. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Integer feugiat sagittis dictum. Donec mauris ante, feugiat sed ultricies ut, elementum a purus. Sed porta lectus et sem blandit vehicula. - -Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nunc volutpat feugiat fermentum. Curabitur luctus consequat urna a tincidunt. Nullam vitae velit eu arcu congue volutpat in a diam. Pellentesque lacus ipsum, gravida et tristique sit amet, varius eu ipsum. Duis venenatis sem id nibh commodo tempor. Curabitur risus tellus, cursus quis pellentesque sed, elementum eget neque. Sed ultricies, orci et adipiscing dapibus, mauris nisi condimentum felis, ac euismod tellus nunc vel felis. Aliquam egestas accumsan turpis, a volutpat dui fermentum id. Aliquam erat volutpat. Nunc vel auctor odio. Donec eu posuere dolor. Donec vitae justo purus, nec bibendum lectus. Quisque elit tortor, tristique vel ultricies sed, euismod sed tellus. Nullam dolor purus, porta et hendrerit id, rhoncus eu lectus. Nam vel lorem at dui mattis pretium eget a nisi. - -Quisque eleifend risus non metus gravida ac semper odio aliquam. Praesent sed risus in tellus congue convallis. Quisque et magna tellus, in ornare leo. Nunc tempor interdum tortor, non blandit risus rhoncus et. Aliquam pulvinar est sed massa ornare sit amet ornare ligula commodo. Nunc porta ultricies tempor. Phasellus gravida accumsan auctor. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Proin quis enim tortor. Curabitur pretium diam a arcu rutrum sed sagittis velit placerat. Ut ut mauris quam, luctus iaculis sem. Nulla quis purus quis lacus cursus imperdiet a quis dolor. Nullam hendrerit eros faucibus ante dignissim vel pharetra ligula viverra. Lorem ipsum dolor sit amet, consectetur adipiscing elit. - -Nunc gravida massa quis nisl venenatis interdum. Integer non dui tortor, non volutpat nisi. In porta accumsan scelerisque. Nunc elementum urna non metus scelerisque ac condimentum eros volutpat. Donec eget nibh condimentum quam tempor vulputate non vel turpis. Quisque suscipit blandit mi quis iaculis. Ut iaculis, nisi ac tristique fringilla, nulla dui interdum lectus, a consectetur mi sapien a metus. Cras eu dolor non dolor imperdiet faucibus. Vestibulum porta risus vel neque convallis elementum. Aenean auctor, turpis eu molestie ultrices, mauris felis sodales est, at iaculis augue libero eu turpis. Curabitur sit amet est quis orci volutpat viverra dignissim in elit. Cras suscipit tristique quam in tincidunt. Aliquam imperdiet libero id dolor egestas viverra egestas arcu posuere. Pellentesque enim risus, accumsan quis ullamcorper ac, malesuada vitae leo. - -Cras ullamcorper vestibulum eros nec suscipit. Vivamus tincidunt, metus at tristique sodales, metus massa sagittis elit, eu scelerisque tortor ante ut sapien. Curabitur rutrum fringilla purus, eget commodo neque tincidunt ut. Etiam ac leo sed nisi ultricies ultrices sed in urna. Fusce blandit fermentum ipsum, vitae dapibus eros tempus vel. Praesent ullamcorper nulla sed nisl facilisis aliquam. Mauris consequat dui quis elit pulvinar vitae pellentesque sapien tempor. Sed accumsan consequat tortor, eget hendrerit lectus rhoncus nec. Mauris diam neque, congue ut laoreet a, hendrerit sit amet sem. Donec eget diam orci, ac vehicula orci. Ut sollicitudin ultricies arcu ut faucibus. Nulla felis nisl, auctor eget adipiscing sit amet, sagittis et est. Cras elit nisi, placerat quis tincidunt at, dapibus et arcu. Donec fermentum eleifend pretium. Nullam at posuere nulla. Phasellus at urna a arcu aliquam ullamcorper eget et ligula. - -Curabitur fermentum libero vitae libero mattis pulvinar. Vivamus luctus laoreet vulputate. Nunc dictum eros a nulla fringilla quis vestibulum ante malesuada. Suspendisse aliquam vulputate consequat. Duis eu sem eu justo convallis dictum sed ut arcu. Mauris porttitor nulla a augue iaculis posuere euismod mi scelerisque. Maecenas sodales nisi eu turpis fermentum dapibus. Morbi viverra iaculis magna, sed congue justo semper at. Nunc in mi enim. Ut aliquam mi et ligula molestie ac bibendum leo egestas. Nullam molestie, urna ac interdum auctor, dolor diam aliquam ligula, vitae gravida mi orci a tortor. Donec et felis turpis, id lobortis nunc. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Integer feugiat sagittis dictum. Donec mauris ante, feugiat sed ultricies ut, elementum a purus. Sed porta lectus et sem blandit vehicula. - -
- diff --git a/servo/tests/html/longcat.html b/servo/tests/html/longcat.html deleted file mode 100644 index aad11cd9238c..000000000000 --- a/servo/tests/html/longcat.html +++ /dev/null @@ -1,38 +0,0 @@ - - - - - -

-

-

- - - diff --git a/servo/tests/html/longcatbot.png b/servo/tests/html/longcatbot.png deleted file mode 100644 index e1a4bc00fcf6..000000000000 Binary files a/servo/tests/html/longcatbot.png and /dev/null differ diff --git a/servo/tests/html/longcatmid.png b/servo/tests/html/longcatmid.png deleted file mode 100644 index e1b6f83eea5b..000000000000 Binary files a/servo/tests/html/longcatmid.png and /dev/null differ diff --git a/servo/tests/html/longcattop.png b/servo/tests/html/longcattop.png deleted file mode 100644 index 1d786dc19503..000000000000 Binary files a/servo/tests/html/longcattop.png and /dev/null differ diff --git a/servo/tests/html/lots_of_background_colors.css b/servo/tests/html/lots_of_background_colors.css deleted file mode 100644 index 6c2d2f10c574..000000000000 --- a/servo/tests/html/lots_of_background_colors.css +++ /dev/null @@ -1,16 +0,0 @@ -.green {background-color : green} -.blue {background-color : blue} -.red {background-color : red} -.white {background-color : white} -.black {background-color : black} -.brown {background-color : rgb(200,100,0)} -.gray {background-color : gray} -.lightgray {background-color : rgb(200,200,200)} -.darkgray {background-color : rgb(50,50,50)} -.cyan {background-color : aqua)} -.maroon {background-color : maroon} -.pink {background-color : rgb(255,0,255)} -.orange {background-color : rgb(255,175,0)} -.violet {background-color : rgb(100,0,150)} -.darkgreen {background-color : rgb(0,100,0)} -.darkblue {background-color : navy} diff --git a/servo/tests/html/make-garbage.html b/servo/tests/html/make-garbage.html deleted file mode 100644 index 71675f78ff26..000000000000 --- a/servo/tests/html/make-garbage.html +++ /dev/null @@ -1,21 +0,0 @@ - diff --git a/servo/tests/html/mojira.html b/servo/tests/html/mojira.html deleted file mode 100644 index 8011acd66af1..000000000000 --- a/servo/tests/html/mojira.html +++ /dev/null @@ -1,19 +0,0 @@ - - -Mozilla - Wikipedia - - -

-Manual test to check each link goes to the right place.

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Fragment IdentifierIntended FragmentTest TargetDescription
#topDocumenttest0Top of document
#TOPDocumenttest0Top of document
#Top<p id="Top">test8Id takes precendence over "top"
#sanity-check<p id="sanity-check">test1Sanity check
#has%20space<p id="has space">test2Contains a space
#escaped%20space<p id="escaped%20space">Contains an escaped space. Only decoded fragid is used for ids.
#escaped%20unescaped%20collide<p id="escaped unescaped collide">test4Another element has the same id but pecent-encoded. The decoded one should win.
#name-match<a name="name-match">test5
#name-collide<a id="name-collide">test6Same id as an anchor name. Id should win.
#escaped%20name<a name="escaped%20name">test7Undecoded fragid should be used for anchor names.
- -
-

span id="sanity-check"

SUCCESS test1

-
-
-

span id="has space"

SUCCESS test2

-
-
-

span id="escaped%20space"

FAIL test3

- Not in whatwg spec, but a tolerant implementation would do this to give content creator what they probably intended. -
-
-

span id="escaped unescaped collide"

SUCCESS test4

-
-
-

span id="escaped%20unescaped%20collide"

FAIL test4

- Not in whatwg spec, but a tolerant implementation would do this to give content creator what they probably intended. -
-
- a name="name-match"

SUCCESS test5

-
-
- a name="name-collide"

FAIL test6

- An anchor name and an id have the same value. The id should take precence! -
-
- a id="name-collide"

SUCCESS test6

-
-
- a name="escaped%20name"

SUCCESS test7

-
-
-

p id="Top"

SUCCESS test8

-
-
diff --git a/servo/tests/html/nested-fixed-position.html b/servo/tests/html/nested-fixed-position.html deleted file mode 100644 index 2810dbf85999..000000000000 --- a/servo/tests/html/nested-fixed-position.html +++ /dev/null @@ -1,7 +0,0 @@ - - -
-
- This text should not scroll. -
-
diff --git a/servo/tests/html/object_element.html b/servo/tests/html/object_element.html deleted file mode 100644 index 501e0c049f91..000000000000 --- a/servo/tests/html/object_element.html +++ /dev/null @@ -1,15 +0,0 @@ - - - - - - - - - - ERROR - - - - - diff --git a/servo/tests/html/overflow-box-shadow.html b/servo/tests/html/overflow-box-shadow.html deleted file mode 100644 index fe1e596333d8..000000000000 --- a/servo/tests/html/overflow-box-shadow.html +++ /dev/null @@ -1,32 +0,0 @@ - - - - -
-
-
- diff --git a/servo/tests/html/overflow-bug-0.html b/servo/tests/html/overflow-bug-0.html deleted file mode 100644 index 10e2207ca569..000000000000 --- a/servo/tests/html/overflow-bug-0.html +++ /dev/null @@ -1,18 +0,0 @@ - - - - -
-
- diff --git a/servo/tests/html/overflow-bug-1.html b/servo/tests/html/overflow-bug-1.html deleted file mode 100644 index 1a11bf1320f7..000000000000 --- a/servo/tests/html/overflow-bug-1.html +++ /dev/null @@ -1,29 +0,0 @@ - - - - -
- x -
diff --git a/servo/tests/html/overflow-bug-2.html b/servo/tests/html/overflow-bug-2.html deleted file mode 100644 index 1251b6de34cd..000000000000 --- a/servo/tests/html/overflow-bug-2.html +++ /dev/null @@ -1,28 +0,0 @@ - - - - -
-
-
diff --git a/servo/tests/html/overflow-hidden.html b/servo/tests/html/overflow-hidden.html deleted file mode 100644 index 7a6ace51f7d7..000000000000 --- a/servo/tests/html/overflow-hidden.html +++ /dev/null @@ -1,7 +0,0 @@ -
- - - -
-
- diff --git a/servo/tests/html/overflow_scroll_relative_position.html b/servo/tests/html/overflow_scroll_relative_position.html deleted file mode 100644 index 83c4b8c1675d..000000000000 --- a/servo/tests/html/overflow_scroll_relative_position.html +++ /dev/null @@ -1,38 +0,0 @@ - - - - - - - This element should be scrollable. -
-
-
-
-
-
- - diff --git a/servo/tests/html/overflow_scroll_with_nested_fixed_height.html b/servo/tests/html/overflow_scroll_with_nested_fixed_height.html deleted file mode 100644 index 6807adb18f60..000000000000 --- a/servo/tests/html/overflow_scroll_with_nested_fixed_height.html +++ /dev/null @@ -1,37 +0,0 @@ - - -
This document ought to be scrollable.
-
-Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nunc volutpat feugiat fermentum. Curabitur luctus consequat urna a tincidunt. Nullam vitae velit eu arcu congue volutpat in a diam. Pellentesque lacus ipsum, gravida et tristique sit amet, varius eu ipsum. Duis venenatis sem id nibh commodo tempor. Curabitur risus tellus, cursus quis pellentesque sed, elementum eget neque. Sed ultricies, orci et adipiscing dapibus, mauris nisi condimentum felis, ac euismod tellus nunc vel felis. Aliquam egestas accumsan turpis, a volutpat dui fermentum id. Aliquam erat volutpat. Nunc vel auctor odio. Donec eu posuere dolor. Donec vitae justo purus, nec bibendum lectus. Quisque elit tortor, tristique vel ultricies sed, euismod sed tellus. Nullam dolor purus, porta et hendrerit id, rhoncus eu lectus. Nam vel lorem at dui mattis pretium eget a nisi. - -Quisque eleifend risus non metus gravida ac semper odio aliquam. Praesent sed risus in tellus congue convallis. Quisque et magna tellus, in ornare leo. Nunc tempor interdum tortor, non blandit risus rhoncus et. Aliquam pulvinar est sed massa ornare sit amet ornare ligula commodo. Nunc porta ultricies tempor. Phasellus gravida accumsan auctor. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Proin quis enim tortor. Curabitur pretium diam a arcu rutrum sed sagittis velit placerat. Ut ut mauris quam, luctus iaculis sem. Nulla quis purus quis lacus cursus imperdiet a quis dolor. Nullam hendrerit eros faucibus ante dignissim vel pharetra ligula viverra. Lorem ipsum dolor sit amet, consectetur adipiscing elit. - -Nunc gravida massa quis nisl venenatis interdum. Integer non dui tortor, non volutpat nisi. In porta accumsan scelerisque. Nunc elementum urna non metus scelerisque ac condimentum eros volutpat. Donec eget nibh condimentum quam tempor vulputate non vel turpis. Quisque suscipit blandit mi quis iaculis. Ut iaculis, nisi ac tristique fringilla, nulla dui interdum lectus, a consectetur mi sapien a metus. Cras eu dolor non dolor imperdiet faucibus. Vestibulum porta risus vel neque convallis elementum. Aenean auctor, turpis eu molestie ultrices, mauris felis sodales est, at iaculis augue libero eu turpis. Curabitur sit amet est quis orci volutpat viverra dignissim in elit. Cras suscipit tristique quam in tincidunt. Aliquam imperdiet libero id dolor egestas viverra egestas arcu posuere. Pellentesque enim risus, accumsan quis ullamcorper ac, malesuada vitae leo. - -Cras ullamcorper vestibulum eros nec suscipit. Vivamus tincidunt, metus at tristique sodales, metus massa sagittis elit, eu scelerisque tortor ante ut sapien. Curabitur rutrum fringilla purus, eget commodo neque tincidunt ut. Etiam ac leo sed nisi ultricies ultrices sed in urna. Fusce blandit fermentum ipsum, vitae dapibus eros tempus vel. Praesent ullamcorper nulla sed nisl facilisis aliquam. Mauris consequat dui quis elit pulvinar vitae pellentesque sapien tempor. Sed accumsan consequat tortor, eget hendrerit lectus rhoncus nec. Mauris diam neque, congue ut laoreet a, hendrerit sit amet sem. Donec eget diam orci, ac vehicula orci. Ut sollicitudin ultricies arcu ut faucibus. Nulla felis nisl, auctor eget adipiscing sit amet, sagittis et est. Cras elit nisi, placerat quis tincidunt at, dapibus et arcu. Donec fermentum eleifend pretium. Nullam at posuere nulla. Phasellus at urna a arcu aliquam ullamcorper eget et ligula. - -Curabitur fermentum libero vitae libero mattis pulvinar. Vivamus luctus laoreet vulputate. Nunc dictum eros a nulla fringilla quis vestibulum ante malesuada. Suspendisse aliquam vulputate consequat. Duis eu sem eu justo convallis dictum sed ut arcu. Mauris porttitor nulla a augue iaculis posuere euismod mi scelerisque. Maecenas sodales nisi eu turpis fermentum dapibus. Morbi viverra iaculis magna, sed congue justo semper at. Nunc in mi enim. Ut aliquam mi et ligula molestie ac bibendum leo egestas. Nullam molestie, urna ac interdum auctor, dolor diam aliquam ligula, vitae gravida mi orci a tortor. Donec et felis turpis, id lobortis nunc. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Integer feugiat sagittis dictum. Donec mauris ante, feugiat sed ultricies ut, elementum a purus. Sed porta lectus et sem blandit vehicula. - -Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nunc volutpat feugiat fermentum. Curabitur luctus consequat urna a tincidunt. Nullam vitae velit eu arcu congue volutpat in a diam. Pellentesque lacus ipsum, gravida et tristique sit amet, varius eu ipsum. Duis venenatis sem id nibh commodo tempor. Curabitur risus tellus, cursus quis pellentesque sed, elementum eget neque. Sed ultricies, orci et adipiscing dapibus, mauris nisi condimentum felis, ac euismod tellus nunc vel felis. Aliquam egestas accumsan turpis, a volutpat dui fermentum id. Aliquam erat volutpat. Nunc vel auctor odio. Donec eu posuere dolor. Donec vitae justo purus, nec bibendum lectus. Quisque elit tortor, tristique vel ultricies sed, euismod sed tellus. Nullam dolor purus, porta et hendrerit id, rhoncus eu lectus. Nam vel lorem at dui mattis pretium eget a nisi. - -Quisque eleifend risus non metus gravida ac semper odio aliquam. Praesent sed risus in tellus congue convallis. Quisque et magna tellus, in ornare leo. Nunc tempor interdum tortor, non blandit risus rhoncus et. Aliquam pulvinar est sed massa ornare sit amet ornare ligula commodo. Nunc porta ultricies tempor. Phasellus gravida accumsan auctor. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Proin quis enim tortor. Curabitur pretium diam a arcu rutrum sed sagittis velit placerat. Ut ut mauris quam, luctus iaculis sem. Nulla quis purus quis lacus cursus imperdiet a quis dolor. Nullam hendrerit eros faucibus ante dignissim vel pharetra ligula viverra. Lorem ipsum dolor sit amet, consectetur adipiscing elit. - -Nunc gravida massa quis nisl venenatis interdum. Integer non dui tortor, non volutpat nisi. In porta accumsan scelerisque. Nunc elementum urna non metus scelerisque ac condimentum eros volutpat. Donec eget nibh condimentum quam tempor vulputate non vel turpis. Quisque suscipit blandit mi quis iaculis. Ut iaculis, nisi ac tristique fringilla, nulla dui interdum lectus, a consectetur mi sapien a metus. Cras eu dolor non dolor imperdiet faucibus. Vestibulum porta risus vel neque convallis elementum. Aenean auctor, turpis eu molestie ultrices, mauris felis sodales est, at iaculis augue libero eu turpis. Curabitur sit amet est quis orci volutpat viverra dignissim in elit. Cras suscipit tristique quam in tincidunt. Aliquam imperdiet libero id dolor egestas viverra egestas arcu posuere. Pellentesque enim risus, accumsan quis ullamcorper ac, malesuada vitae leo. - -Cras ullamcorper vestibulum eros nec suscipit. Vivamus tincidunt, metus at tristique sodales, metus massa sagittis elit, eu scelerisque tortor ante ut sapien. Curabitur rutrum fringilla purus, eget commodo neque tincidunt ut. Etiam ac leo sed nisi ultricies ultrices sed in urna. Fusce blandit fermentum ipsum, vitae dapibus eros tempus vel. Praesent ullamcorper nulla sed nisl facilisis aliquam. Mauris consequat dui quis elit pulvinar vitae pellentesque sapien tempor. Sed accumsan consequat tortor, eget hendrerit lectus rhoncus nec. Mauris diam neque, congue ut laoreet a, hendrerit sit amet sem. Donec eget diam orci, ac vehicula orci. Ut sollicitudin ultricies arcu ut faucibus. Nulla felis nisl, auctor eget adipiscing sit amet, sagittis et est. Cras elit nisi, placerat quis tincidunt at, dapibus et arcu. Donec fermentum eleifend pretium. Nullam at posuere nulla. Phasellus at urna a arcu aliquam ullamcorper eget et ligula. - -Curabitur fermentum libero vitae libero mattis pulvinar. Vivamus luctus laoreet vulputate. Nunc dictum eros a nulla fringilla quis vestibulum ante malesuada. Suspendisse aliquam vulputate consequat. Duis eu sem eu justo convallis dictum sed ut arcu. Mauris porttitor nulla a augue iaculis posuere euismod mi scelerisque. Maecenas sodales nisi eu turpis fermentum dapibus. Morbi viverra iaculis magna, sed congue justo semper at. Nunc in mi enim. Ut aliquam mi et ligula molestie ac bibendum leo egestas. Nullam molestie, urna ac interdum auctor, dolor diam aliquam ligula, vitae gravida mi orci a tortor. Donec et felis turpis, id lobortis nunc. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Integer feugiat sagittis dictum. Donec mauris ante, feugiat sed ultricies ut, elementum a purus. Sed porta lectus et sem blandit vehicula. - -Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nunc volutpat feugiat fermentum. Curabitur luctus consequat urna a tincidunt. Nullam vitae velit eu arcu congue volutpat in a diam. Pellentesque lacus ipsum, gravida et tristique sit amet, varius eu ipsum. Duis venenatis sem id nibh commodo tempor. Curabitur risus tellus, cursus quis pellentesque sed, elementum eget neque. Sed ultricies, orci et adipiscing dapibus, mauris nisi condimentum felis, ac euismod tellus nunc vel felis. Aliquam egestas accumsan turpis, a volutpat dui fermentum id. Aliquam erat volutpat. Nunc vel auctor odio. Donec eu posuere dolor. Donec vitae justo purus, nec bibendum lectus. Quisque elit tortor, tristique vel ultricies sed, euismod sed tellus. Nullam dolor purus, porta et hendrerit id, rhoncus eu lectus. Nam vel lorem at dui mattis pretium eget a nisi. - -Quisque eleifend risus non metus gravida ac semper odio aliquam. Praesent sed risus in tellus congue convallis. Quisque et magna tellus, in ornare leo. Nunc tempor interdum tortor, non blandit risus rhoncus et. Aliquam pulvinar est sed massa ornare sit amet ornare ligula commodo. Nunc porta ultricies tempor. Phasellus gravida accumsan auctor. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Proin quis enim tortor. Curabitur pretium diam a arcu rutrum sed sagittis velit placerat. Ut ut mauris quam, luctus iaculis sem. Nulla quis purus quis lacus cursus imperdiet a quis dolor. Nullam hendrerit eros faucibus ante dignissim vel pharetra ligula viverra. Lorem ipsum dolor sit amet, consectetur adipiscing elit. - -Nunc gravida massa quis nisl venenatis interdum. Integer non dui tortor, non volutpat nisi. In porta accumsan scelerisque. Nunc elementum urna non metus scelerisque ac condimentum eros volutpat. Donec eget nibh condimentum quam tempor vulputate non vel turpis. Quisque suscipit blandit mi quis iaculis. Ut iaculis, nisi ac tristique fringilla, nulla dui interdum lectus, a consectetur mi sapien a metus. Cras eu dolor non dolor imperdiet faucibus. Vestibulum porta risus vel neque convallis elementum. Aenean auctor, turpis eu molestie ultrices, mauris felis sodales est, at iaculis augue libero eu turpis. Curabitur sit amet est quis orci volutpat viverra dignissim in elit. Cras suscipit tristique quam in tincidunt. Aliquam imperdiet libero id dolor egestas viverra egestas arcu posuere. Pellentesque enim risus, accumsan quis ullamcorper ac, malesuada vitae leo. - -Cras ullamcorper vestibulum eros nec suscipit. Vivamus tincidunt, metus at tristique sodales, metus massa sagittis elit, eu scelerisque tortor ante ut sapien. Curabitur rutrum fringilla purus, eget commodo neque tincidunt ut. Etiam ac leo sed nisi ultricies ultrices sed in urna. Fusce blandit fermentum ipsum, vitae dapibus eros tempus vel. Praesent ullamcorper nulla sed nisl facilisis aliquam. Mauris consequat dui quis elit pulvinar vitae pellentesque sapien tempor. Sed accumsan consequat tortor, eget hendrerit lectus rhoncus nec. Mauris diam neque, congue ut laoreet a, hendrerit sit amet sem. Donec eget diam orci, ac vehicula orci. Ut sollicitudin ultricies arcu ut faucibus. Nulla felis nisl, auctor eget adipiscing sit amet, sagittis et est. Cras elit nisi, placerat quis tincidunt at, dapibus et arcu. Donec fermentum eleifend pretium. Nullam at posuere nulla. Phasellus at urna a arcu aliquam ullamcorper eget et ligula. - -Curabitur fermentum libero vitae libero mattis pulvinar. Vivamus luctus laoreet vulputate. Nunc dictum eros a nulla fringilla quis vestibulum ante malesuada. Suspendisse aliquam vulputate consequat. Duis eu sem eu justo convallis dictum sed ut arcu. Mauris porttitor nulla a augue iaculis posuere euismod mi scelerisque. Maecenas sodales nisi eu turpis fermentum dapibus. Morbi viverra iaculis magna, sed congue justo semper at. Nunc in mi enim. Ut aliquam mi et ligula molestie ac bibendum leo egestas. Nullam molestie, urna ac interdum auctor, dolor diam aliquam ligula, vitae gravida mi orci a tortor. Donec et felis turpis, id lobortis nunc. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Integer feugiat sagittis dictum. Donec mauris ante, feugiat sed ultricies ut, elementum a purus. Sed porta lectus et sem blandit vehicula. - -
- - diff --git a/servo/tests/html/pair_iterable_perf.html b/servo/tests/html/pair_iterable_perf.html deleted file mode 100644 index f4fefc6ba689..000000000000 --- a/servo/tests/html/pair_iterable_perf.html +++ /dev/null @@ -1,44 +0,0 @@ - - -Value and pair iterable bindings - diff --git a/servo/tests/html/panic.html b/servo/tests/html/panic.html deleted file mode 100644 index d9464846d756..000000000000 --- a/servo/tests/html/panic.html +++ /dev/null @@ -1,16 +0,0 @@ - - - - - - - - - - diff --git a/servo/tests/html/parent.html b/servo/tests/html/parent.html deleted file mode 100644 index 6516089766a2..000000000000 --- a/servo/tests/html/parent.html +++ /dev/null @@ -1,8 +0,0 @@ - - - diff --git a/servo/tests/html/percentage-body-height.html b/servo/tests/html/percentage-body-height.html deleted file mode 100644 index ae45318f91fd..000000000000 --- a/servo/tests/html/percentage-body-height.html +++ /dev/null @@ -1,36 +0,0 @@ - -
- - -Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nunc volutpat feugiat fermentum. Curabitur luctus consequat urna a tincidunt. Nullam vitae velit eu arcu congue volutpat in a diam. Pellentesque lacus ipsum, gravida et tristique sit amet, varius eu ipsum. Duis venenatis sem id nibh commodo tempor. Curabitur risus tellus, cursus quis pellentesque sed, elementum eget neque. Sed ultricies, orci et adipiscing dapibus, mauris nisi condimentum felis, ac euismod tellus nunc vel felis. Aliquam egestas accumsan turpis, a volutpat dui fermentum id. Aliquam erat volutpat. Nunc vel auctor odio. Donec eu posuere dolor. Donec vitae justo purus, nec bibendum lectus. Quisque elit tortor, tristique vel ultricies sed, euismod sed tellus. Nullam dolor purus, porta et hendrerit id, rhoncus eu lectus. Nam vel lorem at dui mattis pretium eget a nisi. - -Quisque eleifend risus non metus gravida ac semper odio aliquam. Praesent sed risus in tellus congue convallis. Quisque et magna tellus, in ornare leo. Nunc tempor interdum tortor, non blandit risus rhoncus et. Aliquam pulvinar est sed massa ornare sit amet ornare ligula commodo. Nunc porta ultricies tempor. Phasellus gravida accumsan auctor. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Proin quis enim tortor. Curabitur pretium diam a arcu rutrum sed sagittis velit placerat. Ut ut mauris quam, luctus iaculis sem. Nulla quis purus quis lacus cursus imperdiet a quis dolor. Nullam hendrerit eros faucibus ante dignissim vel pharetra ligula viverra. Lorem ipsum dolor sit amet, consectetur adipiscing elit. - -Nunc gravida massa quis nisl venenatis interdum. Integer non dui tortor, non volutpat nisi. In porta accumsan scelerisque. Nunc elementum urna non metus scelerisque ac condimentum eros volutpat. Donec eget nibh condimentum quam tempor vulputate non vel turpis. Quisque suscipit blandit mi quis iaculis. Ut iaculis, nisi ac tristique fringilla, nulla dui interdum lectus, a consectetur mi sapien a metus. Cras eu dolor non dolor imperdiet faucibus. Vestibulum porta risus vel neque convallis elementum. Aenean auctor, turpis eu molestie ultrices, mauris felis sodales est, at iaculis augue libero eu turpis. Curabitur sit amet est quis orci volutpat viverra dignissim in elit. Cras suscipit tristique quam in tincidunt. Aliquam imperdiet libero id dolor egestas viverra egestas arcu posuere. Pellentesque enim risus, accumsan quis ullamcorper ac, malesuada vitae leo. - -Cras ullamcorper vestibulum eros nec suscipit. Vivamus tincidunt, metus at tristique sodales, metus massa sagittis elit, eu scelerisque tortor ante ut sapien. Curabitur rutrum fringilla purus, eget commodo neque tincidunt ut. Etiam ac leo sed nisi ultricies ultrices sed in urna. Fusce blandit fermentum ipsum, vitae dapibus eros tempus vel. Praesent ullamcorper nulla sed nisl facilisis aliquam. Mauris consequat dui quis elit pulvinar vitae pellentesque sapien tempor. Sed accumsan consequat tortor, eget hendrerit lectus rhoncus nec. Mauris diam neque, congue ut laoreet a, hendrerit sit amet sem. Donec eget diam orci, ac vehicula orci. Ut sollicitudin ultricies arcu ut faucibus. Nulla felis nisl, auctor eget adipiscing sit amet, sagittis et est. Cras elit nisi, placerat quis tincidunt at, dapibus et arcu. Donec fermentum eleifend pretium. Nullam at posuere nulla. Phasellus at urna a arcu aliquam ullamcorper eget et ligula. - -Curabitur fermentum libero vitae libero mattis pulvinar. Vivamus luctus laoreet vulputate. Nunc dictum eros a nulla fringilla quis vestibulum ante malesuada. Suspendisse aliquam vulputate consequat. Duis eu sem eu justo convallis dictum sed ut arcu. Mauris porttitor nulla a augue iaculis posuere euismod mi scelerisque. Maecenas sodales nisi eu turpis fermentum dapibus. Morbi viverra iaculis magna, sed congue justo semper at. Nunc in mi enim. Ut aliquam mi et ligula molestie ac bibendum leo egestas. Nullam molestie, urna ac interdum auctor, dolor diam aliquam ligula, vitae gravida mi orci a tortor. Donec et felis turpis, id lobortis nunc. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Integer feugiat sagittis dictum. Donec mauris ante, feugiat sed ultricies ut, elementum a purus. Sed porta lectus et sem blandit vehicula. - -Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nunc volutpat feugiat fermentum. Curabitur luctus consequat urna a tincidunt. Nullam vitae velit eu arcu congue volutpat in a diam. Pellentesque lacus ipsum, gravida et tristique sit amet, varius eu ipsum. Duis venenatis sem id nibh commodo tempor. Curabitur risus tellus, cursus quis pellentesque sed, elementum eget neque. Sed ultricies, orci et adipiscing dapibus, mauris nisi condimentum felis, ac euismod tellus nunc vel felis. Aliquam egestas accumsan turpis, a volutpat dui fermentum id. Aliquam erat volutpat. Nunc vel auctor odio. Donec eu posuere dolor. Donec vitae justo purus, nec bibendum lectus. Quisque elit tortor, tristique vel ultricies sed, euismod sed tellus. Nullam dolor purus, porta et hendrerit id, rhoncus eu lectus. Nam vel lorem at dui mattis pretium eget a nisi. - -Quisque eleifend risus non metus gravida ac semper odio aliquam. Praesent sed risus in tellus congue convallis. Quisque et magna tellus, in ornare leo. Nunc tempor interdum tortor, non blandit risus rhoncus et. Aliquam pulvinar est sed massa ornare sit amet ornare ligula commodo. Nunc porta ultricies tempor. Phasellus gravida accumsan auctor. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Proin quis enim tortor. Curabitur pretium diam a arcu rutrum sed sagittis velit placerat. Ut ut mauris quam, luctus iaculis sem. Nulla quis purus quis lacus cursus imperdiet a quis dolor. Nullam hendrerit eros faucibus ante dignissim vel pharetra ligula viverra. Lorem ipsum dolor sit amet, consectetur adipiscing elit. - -Nunc gravida massa quis nisl venenatis interdum. Integer non dui tortor, non volutpat nisi. In porta accumsan scelerisque. Nunc elementum urna non metus scelerisque ac condimentum eros volutpat. Donec eget nibh condimentum quam tempor vulputate non vel turpis. Quisque suscipit blandit mi quis iaculis. Ut iaculis, nisi ac tristique fringilla, nulla dui interdum lectus, a consectetur mi sapien a metus. Cras eu dolor non dolor imperdiet faucibus. Vestibulum porta risus vel neque convallis elementum. Aenean auctor, turpis eu molestie ultrices, mauris felis sodales est, at iaculis augue libero eu turpis. Curabitur sit amet est quis orci volutpat viverra dignissim in elit. Cras suscipit tristique quam in tincidunt. Aliquam imperdiet libero id dolor egestas viverra egestas arcu posuere. Pellentesque enim risus, accumsan quis ullamcorper ac, malesuada vitae leo. - -Cras ullamcorper vestibulum eros nec suscipit. Vivamus tincidunt, metus at tristique sodales, metus massa sagittis elit, eu scelerisque tortor ante ut sapien. Curabitur rutrum fringilla purus, eget commodo neque tincidunt ut. Etiam ac leo sed nisi ultricies ultrices sed in urna. Fusce blandit fermentum ipsum, vitae dapibus eros tempus vel. Praesent ullamcorper nulla sed nisl facilisis aliquam. Mauris consequat dui quis elit pulvinar vitae pellentesque sapien tempor. Sed accumsan consequat tortor, eget hendrerit lectus rhoncus nec. Mauris diam neque, congue ut laoreet a, hendrerit sit amet sem. Donec eget diam orci, ac vehicula orci. Ut sollicitudin ultricies arcu ut faucibus. Nulla felis nisl, auctor eget adipiscing sit amet, sagittis et est. Cras elit nisi, placerat quis tincidunt at, dapibus et arcu. Donec fermentum eleifend pretium. Nullam at posuere nulla. Phasellus at urna a arcu aliquam ullamcorper eget et ligula. - -Curabitur fermentum libero vitae libero mattis pulvinar. Vivamus luctus laoreet vulputate. Nunc dictum eros a nulla fringilla quis vestibulum ante malesuada. Suspendisse aliquam vulputate consequat. Duis eu sem eu justo convallis dictum sed ut arcu. Mauris porttitor nulla a augue iaculis posuere euismod mi scelerisque. Maecenas sodales nisi eu turpis fermentum dapibus. Morbi viverra iaculis magna, sed congue justo semper at. Nunc in mi enim. Ut aliquam mi et ligula molestie ac bibendum leo egestas. Nullam molestie, urna ac interdum auctor, dolor diam aliquam ligula, vitae gravida mi orci a tortor. Donec et felis turpis, id lobortis nunc. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Integer feugiat sagittis dictum. Donec mauris ante, feugiat sed ultricies ut, elementum a purus. Sed porta lectus et sem blandit vehicula. - -Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nunc volutpat feugiat fermentum. Curabitur luctus consequat urna a tincidunt. Nullam vitae velit eu arcu congue volutpat in a diam. Pellentesque lacus ipsum, gravida et tristique sit amet, varius eu ipsum. Duis venenatis sem id nibh commodo tempor. Curabitur risus tellus, cursus quis pellentesque sed, elementum eget neque. Sed ultricies, orci et adipiscing dapibus, mauris nisi condimentum felis, ac euismod tellus nunc vel felis. Aliquam egestas accumsan turpis, a volutpat dui fermentum id. Aliquam erat volutpat. Nunc vel auctor odio. Donec eu posuere dolor. Donec vitae justo purus, nec bibendum lectus. Quisque elit tortor, tristique vel ultricies sed, euismod sed tellus. Nullam dolor purus, porta et hendrerit id, rhoncus eu lectus. Nam vel lorem at dui mattis pretium eget a nisi. - -Quisque eleifend risus non metus gravida ac semper odio aliquam. Praesent sed risus in tellus congue convallis. Quisque et magna tellus, in ornare leo. Nunc tempor interdum tortor, non blandit risus rhoncus et. Aliquam pulvinar est sed massa ornare sit amet ornare ligula commodo. Nunc porta ultricies tempor. Phasellus gravida accumsan auctor. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Proin quis enim tortor. Curabitur pretium diam a arcu rutrum sed sagittis velit placerat. Ut ut mauris quam, luctus iaculis sem. Nulla quis purus quis lacus cursus imperdiet a quis dolor. Nullam hendrerit eros faucibus ante dignissim vel pharetra ligula viverra. Lorem ipsum dolor sit amet, consectetur adipiscing elit. - -Nunc gravida massa quis nisl venenatis interdum. Integer non dui tortor, non volutpat nisi. In porta accumsan scelerisque. Nunc elementum urna non metus scelerisque ac condimentum eros volutpat. Donec eget nibh condimentum quam tempor vulputate non vel turpis. Quisque suscipit blandit mi quis iaculis. Ut iaculis, nisi ac tristique fringilla, nulla dui interdum lectus, a consectetur mi sapien a metus. Cras eu dolor non dolor imperdiet faucibus. Vestibulum porta risus vel neque convallis elementum. Aenean auctor, turpis eu molestie ultrices, mauris felis sodales est, at iaculis augue libero eu turpis. Curabitur sit amet est quis orci volutpat viverra dignissim in elit. Cras suscipit tristique quam in tincidunt. Aliquam imperdiet libero id dolor egestas viverra egestas arcu posuere. Pellentesque enim risus, accumsan quis ullamcorper ac, malesuada vitae leo. - -Cras ullamcorper vestibulum eros nec suscipit. Vivamus tincidunt, metus at tristique sodales, metus massa sagittis elit, eu scelerisque tortor ante ut sapien. Curabitur rutrum fringilla purus, eget commodo neque tincidunt ut. Etiam ac leo sed nisi ultricies ultrices sed in urna. Fusce blandit fermentum ipsum, vitae dapibus eros tempus vel. Praesent ullamcorper nulla sed nisl facilisis aliquam. Mauris consequat dui quis elit pulvinar vitae pellentesque sapien tempor. Sed accumsan consequat tortor, eget hendrerit lectus rhoncus nec. Mauris diam neque, congue ut laoreet a, hendrerit sit amet sem. Donec eget diam orci, ac vehicula orci. Ut sollicitudin ultricies arcu ut faucibus. Nulla felis nisl, auctor eget adipiscing sit amet, sagittis et est. Cras elit nisi, placerat quis tincidunt at, dapibus et arcu. Donec fermentum eleifend pretium. Nullam at posuere nulla. Phasellus at urna a arcu aliquam ullamcorper eget et ligula. - -Curabitur fermentum libero vitae libero mattis pulvinar. Vivamus luctus laoreet vulputate. Nunc dictum eros a nulla fringilla quis vestibulum ante malesuada. Suspendisse aliquam vulputate consequat. Duis eu sem eu justo convallis dictum sed ut arcu. Mauris porttitor nulla a augue iaculis posuere euismod mi scelerisque. Maecenas sodales nisi eu turpis fermentum dapibus. Morbi viverra iaculis magna, sed congue justo semper at. Nunc in mi enim. Ut aliquam mi et ligula molestie ac bibendum leo egestas. Nullam molestie, urna ac interdum auctor, dolor diam aliquam ligula, vitae gravida mi orci a tortor. Donec et felis turpis, id lobortis nunc. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Integer feugiat sagittis dictum. Donec mauris ante, feugiat sed ultricies ut, elementum a purus. Sed porta lectus et sem blandit vehicula. - -
- diff --git a/servo/tests/html/perf-rainbow-hard.html b/servo/tests/html/perf-rainbow-hard.html deleted file mode 100644 index 9189668f10f1..000000000000 --- a/servo/tests/html/perf-rainbow-hard.html +++ /dev/null @@ -1,17303 +0,0 @@ - - - - - what - - - -
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- - - diff --git a/servo/tests/html/perf-rainbow.html b/servo/tests/html/perf-rainbow.html deleted file mode 100644 index 84779379245a..000000000000 --- a/servo/tests/html/perf-rainbow.html +++ /dev/null @@ -1,17302 +0,0 @@ - - - - what - - - -
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- - - diff --git a/servo/tests/html/permission-test.html b/servo/tests/html/permission-test.html deleted file mode 100644 index fa1c9183f981..000000000000 --- a/servo/tests/html/permission-test.html +++ /dev/null @@ -1,37 +0,0 @@ - - -Permission Test - - - - - -

-    
-
-
diff --git a/servo/tests/html/pointer_events.html b/servo/tests/html/pointer_events.html
deleted file mode 100644
index dc1581f98c32..000000000000
--- a/servo/tests/html/pointer_events.html
+++ /dev/null
@@ -1,36 +0,0 @@
-
-
-
-
-
-
-
-
- - - - diff --git a/servo/tests/html/rust-0.png b/servo/tests/html/rust-0.png deleted file mode 100644 index 20d93badf5e2..000000000000 Binary files a/servo/tests/html/rust-0.png and /dev/null differ diff --git a/servo/tests/html/rust-135.png b/servo/tests/html/rust-135.png deleted file mode 100644 index d5a26f62139f..000000000000 Binary files a/servo/tests/html/rust-135.png and /dev/null differ diff --git a/servo/tests/html/rust-180.png b/servo/tests/html/rust-180.png deleted file mode 100644 index af2a0631b133..000000000000 Binary files a/servo/tests/html/rust-180.png and /dev/null differ diff --git a/servo/tests/html/rust-225.png b/servo/tests/html/rust-225.png deleted file mode 100644 index b0a671ea3b18..000000000000 Binary files a/servo/tests/html/rust-225.png and /dev/null differ diff --git a/servo/tests/html/rust-270.png b/servo/tests/html/rust-270.png deleted file mode 100644 index 0c7d1d7f002d..000000000000 Binary files a/servo/tests/html/rust-270.png and /dev/null differ diff --git a/servo/tests/html/rust-315.png b/servo/tests/html/rust-315.png deleted file mode 100644 index 5d15acd0cfbc..000000000000 Binary files a/servo/tests/html/rust-315.png and /dev/null differ diff --git a/servo/tests/html/rust-45.png b/servo/tests/html/rust-45.png deleted file mode 100644 index b7dd1fd9c5a3..000000000000 Binary files a/servo/tests/html/rust-45.png and /dev/null differ diff --git a/servo/tests/html/rust-90.png b/servo/tests/html/rust-90.png deleted file mode 100644 index 25fd8a662513..000000000000 Binary files a/servo/tests/html/rust-90.png and /dev/null differ diff --git a/servo/tests/html/rust-power-of-two.png b/servo/tests/html/rust-power-of-two.png deleted file mode 100644 index b4929ecee011..000000000000 Binary files a/servo/tests/html/rust-power-of-two.png and /dev/null differ diff --git a/servo/tests/html/select.html b/servo/tests/html/select.html deleted file mode 100644 index 83b089baa1b8..000000000000 --- a/servo/tests/html/select.html +++ /dev/null @@ -1,23 +0,0 @@ - -

- - - diff --git a/servo/tests/html/service-worker/dashboard-page.html b/servo/tests/html/service-worker/dashboard-page.html deleted file mode 100644 index 083b0bf013b8..000000000000 --- a/servo/tests/html/service-worker/dashboard-page.html +++ /dev/null @@ -1,14 +0,0 @@ - - - - - Dashboard Page - - -
-Back to home -

The dashboard page

-Servo Project -
- - diff --git a/servo/tests/html/service-worker/dashboard_helper.js b/servo/tests/html/service-worker/dashboard_helper.js deleted file mode 100644 index 2160ed8420cf..000000000000 --- a/servo/tests/html/service-worker/dashboard_helper.js +++ /dev/null @@ -1,3 +0,0 @@ -function status_from_dashboard() { - console.log("Dashboard Service worker is active"); -} \ No newline at end of file diff --git a/servo/tests/html/service-worker/demo_iframe.html b/servo/tests/html/service-worker/demo_iframe.html deleted file mode 100644 index c4da41ffe1fd..000000000000 --- a/servo/tests/html/service-worker/demo_iframe.html +++ /dev/null @@ -1,12 +0,0 @@ - - - - - Servo Browser Engine - - - - - diff --git a/servo/tests/html/service-worker/dummy.js b/servo/tests/html/service-worker/dummy.js deleted file mode 100644 index e9478cb299ec..000000000000 --- a/servo/tests/html/service-worker/dummy.js +++ /dev/null @@ -1,3 +0,0 @@ -function test_importScripts() { - console.log('Hi from dummy.js'); -} \ No newline at end of file diff --git a/servo/tests/html/service-worker/iframe_sw.js b/servo/tests/html/service-worker/iframe_sw.js deleted file mode 100644 index 64adbeaa9ab6..000000000000 --- a/servo/tests/html/service-worker/iframe_sw.js +++ /dev/null @@ -1,11 +0,0 @@ -self.addEventListener('activate', function(e) { - console.log("iframe service worker active"); -}); - -self.addEventListener('fetch', function(e) { - console.log("A fetch event detected by /iframe service worker"); -}); - -self.addEventListener('message', function(e) { - console.log(e.data.payload.msg + ' from '+ e.data.payload.worker_id); -}) diff --git a/servo/tests/html/service-worker/index.html b/servo/tests/html/service-worker/index.html deleted file mode 100644 index 281d8ea000b9..000000000000 --- a/servo/tests/html/service-worker/index.html +++ /dev/null @@ -1,82 +0,0 @@ - - - - - Service Worker Tests - - -

This page tests the registration and initialization of Service Workers in Servo.

- -
- -
- Go to Dashboard - Go to Profile -
- - - - -
- - - diff --git a/servo/tests/html/service-worker/profile.html b/servo/tests/html/service-worker/profile.html deleted file mode 100644 index 80d64df8a0d1..000000000000 --- a/servo/tests/html/service-worker/profile.html +++ /dev/null @@ -1,14 +0,0 @@ - - - - - Profile Page - - -
-Back to home -

The profile page

-Servo Project -
- - diff --git a/servo/tests/html/service-worker/sw.js b/servo/tests/html/service-worker/sw.js deleted file mode 100644 index 04649167e5a8..000000000000 --- a/servo/tests/html/service-worker/sw.js +++ /dev/null @@ -1,11 +0,0 @@ -self.addEventListener('activate', function(e) { - console.log('Root service worker active'); -}); - -self.addEventListener('fetch', function(e) { - console.log("A fetch event detected by / service worker"); -}); - -self.addEventListener('message', function(e) { - console.log(e.data.num); -}) diff --git a/servo/tests/html/service-worker/sw_dashboard.js b/servo/tests/html/service-worker/sw_dashboard.js deleted file mode 100644 index 5789e0fc361a..000000000000 --- a/servo/tests/html/service-worker/sw_dashboard.js +++ /dev/null @@ -1,11 +0,0 @@ -self.addEventListener('activate', function(e) { - console.log('Dashboard service worker active'); -}); - -self.addEventListener('fetch', function(e) { - console.log("A fetch event detected by /dashboard service worker"); -}); - -self.addEventListener('message', function(e) { - console.log(e.data.payload.msg + ' from '+ e.data.payload.worker_id); -}) diff --git a/servo/tests/html/service-worker/sw_profile.js b/servo/tests/html/service-worker/sw_profile.js deleted file mode 100644 index e1871f125c84..000000000000 --- a/servo/tests/html/service-worker/sw_profile.js +++ /dev/null @@ -1,12 +0,0 @@ - -self.addEventListener('activate', function(e) { - console.log("profile service worker active"); -}); - -self.addEventListener('fetch', function(e) { - console.log("A fetch event detected by /profile service worker"); -}); - -self.addEventListener('message', function(e) { - console.log(e.data.payload.msg + ' from '+ e.data.payload.worker_id); -}) diff --git a/servo/tests/html/shadow-hit-test.html b/servo/tests/html/shadow-hit-test.html deleted file mode 100644 index fc9e5d31d7e5..000000000000 --- a/servo/tests/html/shadow-hit-test.html +++ /dev/null @@ -1,24 +0,0 @@ - - - -
-
diff --git a/servo/tests/html/simple-overflow-scroll.html b/servo/tests/html/simple-overflow-scroll.html deleted file mode 100644 index f0a158b7eaac..000000000000 --- a/servo/tests/html/simple-overflow-scroll.html +++ /dev/null @@ -1,49 +0,0 @@ - -
- -
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nunc ultricies tortor eu augue eleifend malesuada. Duis id condimentum urna. Duis vulputate urna a dignissim sodales. Aenean et magna id dui rutrum suscipit. Etiam metus mauris, congue ac suscipit dapibus, mattis non neque. Donec porttitor eros sed mauris tristique, non condimentum augue feugiat. Suspendisse iaculis faucibus nunc at porttitor. Integer convallis enim in feugiat molestie. Ut eget tincidunt mi, vel malesuada lectus. Quisque fermentum neque a sapien interdum consectetur. Nam tincidunt leo sit amet tortor ornare, sit amet ultrices ante semper. Fusce malesuada mi vitae venenatis sagittis. Duis eget urna quam. - -Sed lacinia aliquam tortor quis elementum. Cras vitae mauris erat. Vestibulum posuere justo et dolor condimentum feugiat. Sed at magna nunc. Suspendisse est nunc, ultrices sed enim lobortis, vulputate rutrum mauris. Fusce ultrices eget erat blandit porta. Sed eros nulla, tristique eget porta a, viverra vel velit. Praesent sit amet odio eleifend, tempor arcu ut, elementum tellus. Suspendisse lorem tortor, sodales eget nulla a, rhoncus lobortis magna. Phasellus purus ante, rhoncus a ipsum nec, condimentum lacinia purus. Cras lobortis posuere nisi, vitae dapibus ante feugiat et. Quisque ornare nisi quis erat congue viverra. Vestibulum a nunc odio. - -Sed id venenatis tortor. Curabitur sit amet mauris eget mi semper rutrum vel et odio. Phasellus eu sapien in sem ultricies pretium eu sit amet magna. Nulla finibus nec lorem ac semper. Nulla eleifend eros id fringilla pellentesque. Proin eleifend, sem vel lobortis viverra, massa augue viverra felis, quis ultricies sapien ipsum at magna. Duis rutrum tempus lobortis. Aliquam quis nulla eget velit viverra pretium. Maecenas venenatis nec nisl at pulvinar. Duis in sodales lectus, ac porta augue. - -Sed sed ante aliquam, rutrum nisl quis, fermentum tellus. Proin ac leo molestie, euismod mauris sed, consequat nunc. Vivamus ut leo a nunc pharetra accumsan a non lorem. Aliquam iaculis mattis augue, in eleifend est accumsan vel. Pellentesque efficitur pulvinar leo vel ornare. Pellentesque non fermentum enim, ut efficitur elit. Duis risus quam, congue vel nulla a, blandit egestas erat. Suspendisse at sodales dolor. Vivamus auctor, lorem et ultrices venenatis, erat ex mollis nisi, quis maximus libero quam a libero. - -Curabitur elit lacus, bibendum non tempus a, bibendum sit amet ante. Mauris eget nibh quis leo rhoncus consequat. Integer iaculis sed sapien eu pellentesque. In aliquet elementum lorem, ut consequat elit ultrices id. Phasellus vestibulum ex ex, ac sagittis tortor convallis et. Curabitur placerat id lectus at aliquam. Morbi sed nisl sem. Nam sit amet arcu maximus, volutpat nisl ac, dignissim neque. Etiam nec efficitur libero. Quisque tristique pulvinar est, eget dictum ex vehicula non. Nam dignissim non felis a iaculis. Nullam vel dolor vitae libero aliquet congue. Donec mi eros, semper non lectus at, commodo ullamcorper ligula. Donec commodo, sem vel lacinia porttitor, elit orci maximus felis, eget eleifend est velit id lorem. -
- diff --git a/servo/tests/html/small-layout-test.html b/servo/tests/html/small-layout-test.html deleted file mode 100644 index 4bc0ee50bbf7..000000000000 --- a/servo/tests/html/small-layout-test.html +++ /dev/null @@ -1,9 +0,0 @@ - - - - -
- -
-
- diff --git a/servo/tests/html/small_color_test.css b/servo/tests/html/small_color_test.css deleted file mode 100644 index 014530c86c89..000000000000 --- a/servo/tests/html/small_color_test.css +++ /dev/null @@ -1 +0,0 @@ -img {background-color : red } diff --git a/servo/tests/html/small_color_test.html b/servo/tests/html/small_color_test.html deleted file mode 100644 index 883bb081ba65..000000000000 --- a/servo/tests/html/small_color_test.html +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - diff --git a/servo/tests/html/summit-crash.html b/servo/tests/html/summit-crash.html deleted file mode 100644 index 56360ef28c97..000000000000 --- a/servo/tests/html/summit-crash.html +++ /dev/null @@ -1,15 +0,0 @@ - - - - - - - here be dragons - - diff --git a/servo/tests/html/summit-fail.html b/servo/tests/html/summit-fail.html deleted file mode 100644 index 53c14a2ee5b7..000000000000 --- a/servo/tests/html/summit-fail.html +++ /dev/null @@ -1,36 +0,0 @@ - - - - - - -
- - frame one -
-
- - frame two -
- - diff --git a/servo/tests/html/summit-one.html b/servo/tests/html/summit-one.html deleted file mode 100644 index 7dbaeddc448b..000000000000 --- a/servo/tests/html/summit-one.html +++ /dev/null @@ -1,46 +0,0 @@ - - - - - - -

-

-

- - - diff --git a/servo/tests/html/summit-three.html b/servo/tests/html/summit-three.html deleted file mode 100644 index a4def31fb884..000000000000 --- a/servo/tests/html/summit-three.html +++ /dev/null @@ -1,77 +0,0 @@ - - - - - - -
- - - - diff --git a/servo/tests/html/summit-two.html b/servo/tests/html/summit-two.html deleted file mode 100644 index 7a62296b1304..000000000000 --- a/servo/tests/html/summit-two.html +++ /dev/null @@ -1,27 +0,0 @@ - - - - - - -

- - - diff --git a/servo/tests/html/summit2.html b/servo/tests/html/summit2.html deleted file mode 100644 index 98b0d4a9b0f3..000000000000 --- a/servo/tests/html/summit2.html +++ /dev/null @@ -1,37 +0,0 @@ - - - - - - -
-
- - frame one -
-
- - frame two -
- - diff --git a/servo/tests/html/summit3.html b/servo/tests/html/summit3.html deleted file mode 100644 index 3b7445d7ab0e..000000000000 --- a/servo/tests/html/summit3.html +++ /dev/null @@ -1,63 +0,0 @@ - - - - - - -
- - frame one -
-
-
- - frame two -
-
- - frame three -
-
- - diff --git a/servo/tests/html/test-absolute.css b/servo/tests/html/test-absolute.css deleted file mode 100644 index 0929875f918a..000000000000 --- a/servo/tests/html/test-absolute.css +++ /dev/null @@ -1,7 +0,0 @@ -img { - position: absolute; - top: 200px; - left: 100px; - border-width: 10px; - border-color: blue -} diff --git a/servo/tests/html/test-absolute.html b/servo/tests/html/test-absolute.html deleted file mode 100644 index e98b7fbefc7a..000000000000 --- a/servo/tests/html/test-absolute.html +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - diff --git a/servo/tests/html/test-css-pseudo-root.html b/servo/tests/html/test-css-pseudo-root.html deleted file mode 100644 index f82349d5ea44..000000000000 --- a/servo/tests/html/test-css-pseudo-root.html +++ /dev/null @@ -1,17 +0,0 @@ - - - - - - :root test - - - - The background of the page should be green and you should see not red at all. -

And the background of this sentence should be green too.

- - diff --git a/servo/tests/html/test-iframe.html b/servo/tests/html/test-iframe.html deleted file mode 100644 index b0fd2023de9b..000000000000 --- a/servo/tests/html/test-iframe.html +++ /dev/null @@ -1,2 +0,0 @@ - - diff --git a/servo/tests/html/test-inline.html b/servo/tests/html/test-inline.html deleted file mode 100644 index 57d0018264c9..000000000000 --- a/servo/tests/html/test-inline.html +++ /dev/null @@ -1,6 +0,0 @@ -
- -
- -
-
diff --git a/servo/tests/html/test-inputs.html b/servo/tests/html/test-inputs.html deleted file mode 100644 index 9692634cadc6..000000000000 --- a/servo/tests/html/test-inputs.html +++ /dev/null @@ -1,55 +0,0 @@ - -
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- -
group 1 -
-
-
-
group 2 -
-
-
- diff --git a/servo/tests/html/test-js-alert.html b/servo/tests/html/test-js-alert.html deleted file mode 100644 index 6e00389b059d..000000000000 --- a/servo/tests/html/test-js-alert.html +++ /dev/null @@ -1,8 +0,0 @@ - diff --git a/servo/tests/html/test-js-console.html b/servo/tests/html/test-js-console.html deleted file mode 100644 index 9cd4c19fb6b3..000000000000 --- a/servo/tests/html/test-js-console.html +++ /dev/null @@ -1,7 +0,0 @@ - diff --git a/servo/tests/html/test-js-image.html b/servo/tests/html/test-js-image.html deleted file mode 100644 index 96c755510d18..000000000000 --- a/servo/tests/html/test-js-image.html +++ /dev/null @@ -1,20 +0,0 @@ - - - diff --git a/servo/tests/html/test-js.html b/servo/tests/html/test-js.html deleted file mode 100644 index 40f94281e07c..000000000000 --- a/servo/tests/html/test-js.html +++ /dev/null @@ -1,25 +0,0 @@ -
- -
- -
-
- diff --git a/servo/tests/html/test-lineheight-verticalalign.html b/servo/tests/html/test-lineheight-verticalalign.html deleted file mode 100644 index e9fcd0019f34..000000000000 --- a/servo/tests/html/test-lineheight-verticalalign.html +++ /dev/null @@ -1,13 +0,0 @@ - - - - - -
[line-height 10] - [line-height:3 + vertical-align:top] - [line-height:1 + vertical-align:top] - [Split inline, still line-height 5] -
-
New line, line-height 3
- - diff --git a/servo/tests/html/test-many-images-different.html b/servo/tests/html/test-many-images-different.html deleted file mode 100644 index 7fce43bae3a6..000000000000 --- a/servo/tests/html/test-many-images-different.html +++ /dev/null @@ -1,22 +0,0 @@ - - - -test - - - - - - - - - - - - - - - - - - diff --git a/servo/tests/html/test-many-images.html b/servo/tests/html/test-many-images.html deleted file mode 100644 index 488a5f30743f..000000000000 --- a/servo/tests/html/test-many-images.html +++ /dev/null @@ -1,340 +0,0 @@ - - - -test - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/servo/tests/html/test-synthetic-click-activation.html b/servo/tests/html/test-synthetic-click-activation.html deleted file mode 100644 index 011914895a7a..000000000000 --- a/servo/tests/html/test-synthetic-click-activation.html +++ /dev/null @@ -1,31 +0,0 @@ - -
-
-
-
-
-
group 1 -
-
-
-
group 2 -
-
-
-
-
-Use the buttons below to shift "fake" focus and trigger click events. The first form widget is initually focused. -
-
-
-
- - - diff --git a/servo/tests/html/test-text-break.html b/servo/tests/html/test-text-break.html deleted file mode 100644 index 620a5e4c52c8..000000000000 --- a/servo/tests/html/test-text-break.html +++ /dev/null @@ -1,52 +0,0 @@ -
-Lorem ipsum dolor sit amet, consectetur adipiscing elit. Etiam at -ipsum orci. Ut mauris erat, pretium eu interdum a, feugiat ut -leo. Proin eu purus lorem, scelerisque pretium turpis. Donec tempus -mollis tortor, sed feugiat felis tincidunt ut. Donec elit sem, -condimentum ac pellentesque id, facilisis non erat. Nam neque urna, -interdum non tempor nec, cursus at erat. Pellentesque id diam leo. - -Nullam sit amet pellentesque urna. Sed non vehicula felis. Suspendisse -vitae mattis dolor. Nam euismod, quam ac dapibus dapibus, tellus erat -vulputate purus, at tempus sem sapien quis risus. Aenean tempor -feugiat urna quis viverra. Duis eleifend tortor semper metus fringilla -non rhoncus eros suscipit. Nullam turpis nibh, condimentum sed tempor -sit amet, tristique nec nisi. In cursus sagittis pulvinar. Vestibulum -ut felis at augue sagittis tristique. Aliquam est urna, auctor quis -faucibus ac, lobortis quis felis. Integer orci diam, rutrum eleifend -congue at, viverra id urna. Nam tempor posuere commodo. - -Integer sit amet pretium erat. Nullam mollis egestas orci, at mattis -risus facilisis ut. Cum sociis natoque penatibus et magnis dis -parturient montes, nascetur ridiculus mus. Praesent ligula nisi, -consequat a faucibus ac, pharetra vel enim. Fusce non sem ut nulla -bibendum malesuada suscipit nec felis. Nulla vel quam et risus egestas -facilisis a malesuada ante. Phasellus id convallis nisl. Aenean -posuere elit non metus tempus id ullamcorper orci dignissim. - -Ut tincidunt magna massa, eget sollicitudin nulla. Aliquam venenatis -porttitor tellus, at suscipit mauris dignissim eget. Duis odio mi, -scelerisque eu ornare sed, malesuada ac leo. Aliquam erat -volutpat. Nulla dignissim tristique dolor rutrum viverra. Nam ipsum -quam, bibendum sed sodales laoreet, congue at elit. Aenean nec -ultricies dui. Vivamus arcu lacus, lacinia sit amet congue et, -interdum sed metus. Nam posuere lacus id sapien varius ut imperdiet -purus molestie. Aliquam erat volutpat. Donec et volutpat -turpis. Quisque elementum massa sit amet lorem malesuada id placerat -ipsum gravida. Quisque suscipit arcu vitae risus commodo at laoreet -enim aliquam. Nam euismod dictum ipsum, condimentum commodo augue -bibendum ac. Cras ut urna eu ipsum ornare pretium. Lorem ipsum dolor -sit amet, consectetur adipiscing elit. - -Donec elit quam, dignissim ut pulvinar et, auctor tincidunt -lacus. Aenean non ipsum ornare orci gravida mollis. Vivamus suscipit, -dui sed dapibus fermentum, tellus enim elementum nulla, non gravida -augue urna volutpat quam. Nullam metus quam, vehicula sit amet ornare -eget, auctor a purus. Curabitur lacus eros, suscipit non lobortis non, -tincidunt a risus. Duis laoreet, dolor a aliquam laoreet, lorem turpis -varius eros, nec sodales est felis id metus. Nullam sit amet tincidunt -justo. Nam sit amet arcu bibendum augue sagittis tincidunt non -dignissim lorem. Maecenas quis justo lacus. Nam fringilla ullamcorper -tellus at sollicitudin. -
- diff --git a/servo/tests/html/test-text.html b/servo/tests/html/test-text.html deleted file mode 100644 index f4a73aba7e7f..000000000000 --- a/servo/tests/html/test-text.html +++ /dev/null @@ -1,2 +0,0 @@ -
Hello world!
- diff --git a/servo/tests/html/test-websocket.html b/servo/tests/html/test-websocket.html deleted file mode 100644 index febefc5e0388..000000000000 --- a/servo/tests/html/test-websocket.html +++ /dev/null @@ -1,69 +0,0 @@ - - - - -WebSocket Test - - - -

WebSocket Test

- -
diff --git a/servo/tests/html/test.css b/servo/tests/html/test.css deleted file mode 100644 index 12e7ad86ad00..000000000000 --- a/servo/tests/html/test.css +++ /dev/null @@ -1,13 +0,0 @@ -p {font-size : 12pt} -p img {color : rgb(0,255,0); display : block } -p.blue > p.green + p.red { background-color : blue ;color : green } -img[class] .pastoral *[lang|=en] { display:inline} -.book > #novel + *[type=novella] p { color : blue; color : white } -* {background-color : red} -* * {background-color : lime} -* * * {background-color : yellow} -* * * * {background-color : white} -* * * * * {background-color : rgb(200,0,200)} -div div {background-color : green} -* * div {background-color : blue} -div div div {background-color : rgb(100,100,100)} diff --git a/servo/tests/html/test.html b/servo/tests/html/test.html deleted file mode 100644 index 7d993f11bc3a..000000000000 --- a/servo/tests/html/test.html +++ /dev/null @@ -1,7 +0,0 @@ -
- -
- -
-
-
diff --git a/servo/tests/html/test.js b/servo/tests/html/test.js deleted file mode 100644 index 262c1b4f1b0a..000000000000 --- a/servo/tests/html/test.js +++ /dev/null @@ -1 +0,0 @@ -debug("Hello, world!"); diff --git a/servo/tests/html/test_3d_transform_1.html b/servo/tests/html/test_3d_transform_1.html deleted file mode 100644 index e35a77770184..000000000000 --- a/servo/tests/html/test_3d_transform_1.html +++ /dev/null @@ -1,131 +0,0 @@ - - - - - - - - - - - - - - - - - - - -
perspective: 250px; - perspective: 350px; - perspective: 500px; -
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- - diff --git a/servo/tests/html/test_3d_transform_2.html b/servo/tests/html/test_3d_transform_2.html deleted file mode 100644 index b585831a52cc..000000000000 --- a/servo/tests/html/test_3d_transform_2.html +++ /dev/null @@ -1,81 +0,0 @@ - - - - - - -
-
-
-
-
-
-
-
-
-
- - diff --git a/servo/tests/html/test_3d_transform_zsort.html b/servo/tests/html/test_3d_transform_zsort.html deleted file mode 100644 index 688d717d6593..000000000000 --- a/servo/tests/html/test_3d_transform_zsort.html +++ /dev/null @@ -1,52 +0,0 @@ - - - - - - -
AAA -
-
-
-
- - diff --git a/servo/tests/html/test_UIEvent_resize.html b/servo/tests/html/test_UIEvent_resize.html deleted file mode 100644 index 48d99dc8be64..000000000000 --- a/servo/tests/html/test_UIEvent_resize.html +++ /dev/null @@ -1,23 +0,0 @@ - - - - - - - - - diff --git a/servo/tests/html/test_bg_color.html b/servo/tests/html/test_bg_color.html deleted file mode 100644 index 76c0a0adafd7..000000000000 --- a/servo/tests/html/test_bg_color.html +++ /dev/null @@ -1,23 +0,0 @@ - - - - -
-
- -
- -
-
- - -
- - -
-
- - -
-
- diff --git a/servo/tests/html/test_bg_color_simple.css b/servo/tests/html/test_bg_color_simple.css deleted file mode 100644 index 973174e74747..000000000000 --- a/servo/tests/html/test_bg_color_simple.css +++ /dev/null @@ -1,3 +0,0 @@ -div { - background-color: blue; -} diff --git a/servo/tests/html/test_bg_color_simple.html b/servo/tests/html/test_bg_color_simple.html deleted file mode 100644 index b2526594196e..000000000000 --- a/servo/tests/html/test_bg_color_simple.html +++ /dev/null @@ -1,8 +0,0 @@ - - - - -
- Test -
- diff --git a/servo/tests/html/test_border.html b/servo/tests/html/test_border.html deleted file mode 100755 index 6e8d60f5d1aa..000000000000 --- a/servo/tests/html/test_border.html +++ /dev/null @@ -1,86 +0,0 @@ - - - - - -
none test.
-
hidden test.
-
solid test
-
double test
-
dashed test
-
dotted test
-
groove test
-
ridge test
-
inset test
-
outset test
- -
-
- - diff --git a/servo/tests/html/test_canvas.html b/servo/tests/html/test_canvas.html deleted file mode 100644 index 8a9918af54cb..000000000000 --- a/servo/tests/html/test_canvas.html +++ /dev/null @@ -1,18 +0,0 @@ - - - - - - - diff --git a/servo/tests/html/test_canvas_drawimage_canvas.html b/servo/tests/html/test_canvas_drawimage_canvas.html deleted file mode 100644 index d62baf76a365..000000000000 --- a/servo/tests/html/test_canvas_drawimage_canvas.html +++ /dev/null @@ -1,219 +0,0 @@ - - - - - - - -

DrawImage canvas to canvas

- - - - - diff --git a/servo/tests/html/test_canvas_drawimage_canvas_timed.html b/servo/tests/html/test_canvas_drawimage_canvas_timed.html deleted file mode 100644 index f076bc5b1f89..000000000000 --- a/servo/tests/html/test_canvas_drawimage_canvas_timed.html +++ /dev/null @@ -1,165 +0,0 @@ - - - - - - - -

Timed DrawImage canvas to canvas

-

This text is where the timing result will go...

- - - - - diff --git a/servo/tests/html/test_canvas_drawimage_html_image.html b/servo/tests/html/test_canvas_drawimage_html_image.html deleted file mode 100644 index c317f7895df8..000000000000 --- a/servo/tests/html/test_canvas_drawimage_html_image.html +++ /dev/null @@ -1,209 +0,0 @@ - - - - - - - -

DrawImage canvas to canvas

- - - - - diff --git a/servo/tests/html/test_canvas_filltext.html b/servo/tests/html/test_canvas_filltext.html deleted file mode 100644 index 1a8783d2003e..000000000000 --- a/servo/tests/html/test_canvas_filltext.html +++ /dev/null @@ -1,18 +0,0 @@ - - - - - - - diff --git a/servo/tests/html/test_class_helloworld.html b/servo/tests/html/test_class_helloworld.html deleted file mode 100644 index f527c683b4eb..000000000000 --- a/servo/tests/html/test_class_helloworld.html +++ /dev/null @@ -1,17 +0,0 @@ - - - - - -
-
Hello
-
World
-
Hello
-
World
-
- - diff --git a/servo/tests/html/test_clear.html b/servo/tests/html/test_clear.html deleted file mode 100644 index a9b4ae052b94..000000000000 --- a/servo/tests/html/test_clear.html +++ /dev/null @@ -1,48 +0,0 @@ - - - - - -
-
- -
-
-
-
- - diff --git a/servo/tests/html/test_clear_float.html b/servo/tests/html/test_clear_float.html deleted file mode 100644 index 20bf1128d834..000000000000 --- a/servo/tests/html/test_clear_float.html +++ /dev/null @@ -1,43 +0,0 @@ - - - - - -
-
- -
-
-
- - diff --git a/servo/tests/html/test_close.html b/servo/tests/html/test_close.html deleted file mode 100644 index 7e4fb2a8cb29..000000000000 --- a/servo/tests/html/test_close.html +++ /dev/null @@ -1,5 +0,0 @@ - - - diff --git a/servo/tests/html/test_cssunit_length.html b/servo/tests/html/test_cssunit_length.html deleted file mode 100644 index 8ae817c0b935..000000000000 --- a/servo/tests/html/test_cssunit_length.html +++ /dev/null @@ -1,57 +0,0 @@ - - - - - - -
Hello, 1em
-
Hello, 1pt
-
Hello, 1px
-
Hello, 1mm
-
Hello, 1pc
-
Hello, 1cm
-
Hello, 1in
- - - - diff --git a/servo/tests/html/test_dom_performance.html b/servo/tests/html/test_dom_performance.html deleted file mode 100644 index e4222098f7a5..000000000000 --- a/servo/tests/html/test_dom_performance.html +++ /dev/null @@ -1,70 +0,0 @@ - - - - - - - -
-

Results:

-
Processing...
- - diff --git a/servo/tests/html/test_float_placement.html b/servo/tests/html/test_float_placement.html deleted file mode 100644 index f983c6260e87..000000000000 --- a/servo/tests/html/test_float_placement.html +++ /dev/null @@ -1,62 +0,0 @@ - - - - - -
-
-
-
-
-
-
-
-
-
- - diff --git a/servo/tests/html/test_focus.html b/servo/tests/html/test_focus.html deleted file mode 100644 index 967030b2a78d..000000000000 --- a/servo/tests/html/test_focus.html +++ /dev/null @@ -1,7 +0,0 @@ - - - - diff --git a/servo/tests/html/test_getter_time.html b/servo/tests/html/test_getter_time.html deleted file mode 100644 index da1835578207..000000000000 --- a/servo/tests/html/test_getter_time.html +++ /dev/null @@ -1,17 +0,0 @@ -
- diff --git a/servo/tests/html/test_hammer_layout.css b/servo/tests/html/test_hammer_layout.css deleted file mode 100644 index ba3802d5b75e..000000000000 --- a/servo/tests/html/test_hammer_layout.css +++ /dev/null @@ -1,3 +0,0 @@ -#styled { - color: red; -} diff --git a/servo/tests/html/test_hammer_layout.html b/servo/tests/html/test_hammer_layout.html deleted file mode 100644 index 613450e8fd90..000000000000 --- a/servo/tests/html/test_hammer_layout.html +++ /dev/null @@ -1,22 +0,0 @@ - - - - - - -
This text is unstyled.
- - diff --git a/servo/tests/html/test_htmlelement_style.html b/servo/tests/html/test_htmlelement_style.html deleted file mode 100644 index 778043e8494a..000000000000 --- a/servo/tests/html/test_htmlelement_style.html +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - -
- - - diff --git a/servo/tests/html/test_img_ismap.html b/servo/tests/html/test_img_ismap.html deleted file mode 100644 index 669a941d07d5..000000000000 --- a/servo/tests/html/test_img_ismap.html +++ /dev/null @@ -1,17 +0,0 @@ - - - - - img element ismap activation test - - -

Click my nose to get the coordinates!

- - andreas - -

Nothing happends if you click my nose

- - andreas - - - diff --git a/servo/tests/html/test_inline_border.html b/servo/tests/html/test_inline_border.html deleted file mode 100644 index e4aa9e3b733a..000000000000 --- a/servo/tests/html/test_inline_border.html +++ /dev/null @@ -1,16 +0,0 @@ - - - hi there? - - -

- - - kitty? - - this is em - - -

- - diff --git a/servo/tests/html/test_inline_boxes.html b/servo/tests/html/test_inline_boxes.html deleted file mode 100644 index 0d1bf947688c..000000000000 --- a/servo/tests/html/test_inline_boxes.html +++ /dev/null @@ -1,11 +0,0 @@ - - - - -
-
- -
- -
- diff --git a/servo/tests/html/test_interval.html b/servo/tests/html/test_interval.html deleted file mode 100644 index 3f95b98695a6..000000000000 --- a/servo/tests/html/test_interval.html +++ /dev/null @@ -1,19 +0,0 @@ - - - - - - - diff --git a/servo/tests/html/test_italic_bold.html b/servo/tests/html/test_italic_bold.html deleted file mode 100644 index 6db60c6afcb4..000000000000 --- a/servo/tests/html/test_italic_bold.html +++ /dev/null @@ -1,55 +0,0 @@ - - - -The Book of Mozilla, 11:9 - - - - -

-Mammon slept. And the beast reborn spread over the earth and its numbers -grew legion. And they proclaimed the times and sacrificed crops unto the -fire, with the cunning of foxes. And they built a new world in their own -image as promised by the -sacred words, and spoke - of the beast with their children. Mammon awoke, and lo! it was -naught but a follower. -

- -

-from The Book of Mozilla, 11:9
(10th Edition) -

- - - diff --git a/servo/tests/html/test_linking.css b/servo/tests/html/test_linking.css deleted file mode 100644 index 3445c564d9ed..000000000000 --- a/servo/tests/html/test_linking.css +++ /dev/null @@ -1 +0,0 @@ -img {background-color : green} diff --git a/servo/tests/html/test_local_bookmark.html b/servo/tests/html/test_local_bookmark.html deleted file mode 100755 index 50c80f9bdb32..000000000000 --- a/servo/tests/html/test_local_bookmark.html +++ /dev/null @@ -1,39 +0,0 @@ - - - - - - -
-
1st text
-
2nd text
-
3rd text
-
-
- This is span - This is span -
- [name is "top"] -

- [id is "h3"]
- text - Times New Roman - Verdana - Arial - Courier New - Georgia - Lucida Console -
[id is "num"]
- 1 - 2 -
3
- 4 - 5 -

-

- --- Bottom --- -

- - diff --git a/servo/tests/html/test_mouse_down_mouse_up_click.html b/servo/tests/html/test_mouse_down_mouse_up_click.html deleted file mode 100644 index 29f3ec29cd89..000000000000 --- a/servo/tests/html/test_mouse_down_mouse_up_click.html +++ /dev/null @@ -1,14 +0,0 @@ - - - - diff --git a/servo/tests/html/test_navigate.html b/servo/tests/html/test_navigate.html deleted file mode 100644 index 4e1119999d42..000000000000 --- a/servo/tests/html/test_navigate.html +++ /dev/null @@ -1,2 +0,0 @@ -

This should change when the link is clicked

-Test link
Move
diff --git a/servo/tests/html/test_navigate2.html b/servo/tests/html/test_navigate2.html deleted file mode 100644 index f947c63a54c8..000000000000 --- a/servo/tests/html/test_navigate2.html +++ /dev/null @@ -1,2 +0,0 @@ -

This should not change when the link is clicked

-Test link
Move
diff --git a/servo/tests/html/test_overflow_hidden.html b/servo/tests/html/test_overflow_hidden.html deleted file mode 100644 index df8f72f7b9ff..000000000000 --- a/servo/tests/html/test_overflow_hidden.html +++ /dev/null @@ -1,35 +0,0 @@ - - - - - - - - -
-
-

I didn't like the play, but then I saw - it under adverse conditions - the curtain was up.

- - Groucho Marx -
-
- - diff --git a/servo/tests/html/test_pseudo.html b/servo/tests/html/test_pseudo.html deleted file mode 100644 index bfe528df1459..000000000000 --- a/servo/tests/html/test_pseudo.html +++ /dev/null @@ -1,22 +0,0 @@ - - - - - - - -, S -
, S
-Servo -
R
- - diff --git a/servo/tests/html/test_request_animation_frame.html b/servo/tests/html/test_request_animation_frame.html deleted file mode 100644 index 29ebac99348b..000000000000 --- a/servo/tests/html/test_request_animation_frame.html +++ /dev/null @@ -1,5 +0,0 @@ - diff --git a/servo/tests/html/test_sandboxed.html b/servo/tests/html/test_sandboxed.html deleted file mode 100644 index 5db41761275f..000000000000 --- a/servo/tests/html/test_sandboxed.html +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - diff --git a/servo/tests/html/test_sandboxed_iframe.html b/servo/tests/html/test_sandboxed_iframe.html deleted file mode 100644 index 061ea8c09a52..000000000000 --- a/servo/tests/html/test_sandboxed_iframe.html +++ /dev/null @@ -1,65 +0,0 @@ - - - -

Time required to multiply two 600x600 matrices:

-
- - diff --git a/servo/tests/html/test_slam_layout.css b/servo/tests/html/test_slam_layout.css deleted file mode 100644 index fed7aa97a3a1..000000000000 --- a/servo/tests/html/test_slam_layout.css +++ /dev/null @@ -1,10 +0,0 @@ -#ohhi { - background-color: red; - padding: 6px; -} - -#mark { - background-color: blue; - padding: 12px; -} - diff --git a/servo/tests/html/test_slam_layout.html b/servo/tests/html/test_slam_layout.html deleted file mode 100644 index 49a62263d0af..000000000000 --- a/servo/tests/html/test_slam_layout.html +++ /dev/null @@ -1,24 +0,0 @@ - - - - - -
- - diff --git a/servo/tests/html/test_style.html b/servo/tests/html/test_style.html deleted file mode 100644 index edf5012b3042..000000000000 --- a/servo/tests/html/test_style.html +++ /dev/null @@ -1,12 +0,0 @@ -
test text!
- diff --git a/servo/tests/html/test_target_pseudoselector.html b/servo/tests/html/test_target_pseudoselector.html deleted file mode 100644 index 622e82ea5d4e..000000000000 --- a/servo/tests/html/test_target_pseudoselector.html +++ /dev/null @@ -1,51 +0,0 @@ - - - - - -
- Target Foo By Link - Target Foo By JS -
- -
- - -
- - Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nunc sodales leo in orci pulvinar, ut tincidunt ipsum vestibulum. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Duis et vestibulum metus. Maecenas erat elit, ultrices eu gravida et, sollicitudin ac est. Sed in tellus ut tortor euismod aliquet non egestas metus. Sed pellentesque arcu ut lectus feugiat molestie. Fusce et justo non dui fermentum fermentum. Nunc nec ullamcorper urna. Morbi ultricies ornare arcu nec tincidunt. In sit amet risus lectus. Nam ac lacus urna. Phasellus semper eu enim quis rutrum. Suspendisse convallis orci vel nunc blandit, ut venenatis urna elementum. Curabitur a elit elementum sapien hendrerit laoreet eget in nunc. In vitae tempus neque. - Cras nec porta ipsum. Ut consectetur ut elit ac vestibulum. Suspendisse efficitur congue eros rutrum porta. Suspendisse sit amet tortor id massa varius ultrices. Integer ex nulla, tempus et malesuada sit amet, viverra vel tellus. Fusce dictum risus a sapien feugiat dignissim. Nullam iaculis suscipit ante varius semper. Curabitur ut ipsum mattis, ullamcorper leo a, vulputate arcu. - Fusce a gravida lectus, nec vestibulum enim. Interdum et malesuada fames ac ante ipsum primis in faucibus. Nullam vitae lorem lorem. Maecenas interdum nunc nec ex vulputate, in efficitur purus tempus. Pellentesque lacinia consectetur arcu vel posuere. Suspendisse id mi congue, pellentesque elit eu, pharetra neque. Integer vel dignissim nisi. Nunc sagittis augue et rhoncus dignissim. Donec ut orci ac sapien egestas ultrices. - Aliquam accumsan auctor felis in rhoncus. Cras bibendum pharetra mollis. Donec rhoncus, orci quis varius rutrum, turpis arcu varius augue, pharetra cursus velit sem in nisl. Donec nec nisi quis tortor ultricies mollis eget in urna. Aliquam pellentesque felis ipsum, luctus luctus libero congue eget. In at orci ut magna luctus tristique et sit amet sem. Nam non posuere nisi. Ut ante tellus, accumsan eu ullamcorper egestas, pulvinar laoreet sapien. Nullam pulvinar at tellus et ullamcorper. Proin malesuada purus augue, id aliquet augue fringilla ut. Ut a rutrum libero. Vivamus semper faucibus purus, eu hendrerit velit vehicula a. - Aenean eu commodo lorem. Integer mollis vitae ipsum quis pretium. Nullam nec nisl quis erat dictum tincidunt venenatis sed est. Donec semper viverra tellus, pharetra faucibus arcu pellentesque a. Nullam faucibus efficitur pretium. Nullam risus diam, dictum vel ultricies a, interdum vel lacus. Nullam lacinia quam ac lectus imperdiet, non tincidunt ex pretium. Nullam pretium vehicula faucibus. Aliquam erat volutpat. Pellentesque tortor nisl, egestas a ante et, aliquam suscipit eros. Vestibulum porttitor sem lacus, ac vulputate dui venenatis et. Cras ultrices aliquam est, ac ultrices lorem semper et. Vivamus molestie orci quis justo condimentum tincidunt. Integer ornare pharetra ante tempus elementum. Ut vulputate eleifend dolor, ac sodales velit auctor sed. - -
  • hello
- - - diff --git a/servo/tests/html/test_textarea_input.html b/servo/tests/html/test_textarea_input.html deleted file mode 100644 index be792c026b97..000000000000 --- a/servo/tests/html/test_textarea_input.html +++ /dev/null @@ -1,15 +0,0 @@ - - - - - - - - - diff --git a/servo/tests/html/test_timeout.html b/servo/tests/html/test_timeout.html deleted file mode 100644 index 0ae706f67a76..000000000000 --- a/servo/tests/html/test_timeout.html +++ /dev/null @@ -1,13 +0,0 @@ -
diff --git a/servo/tests/html/test_underline.html b/servo/tests/html/test_underline.html deleted file mode 100644 index 05db4e01358b..000000000000 --- a/servo/tests/html/test_underline.html +++ /dev/null @@ -1,60 +0,0 @@ - - - -The Book of Mozilla, 11:9 - - - - -

-Mammon slept. And the beast reborn spread over the earth and its numbers -grew legion. And they proclaimed the times and sacrificed crops unto the -fire, with the cunning of foxes. And they built a new world in their own -image as promised by the -sacred words, and spoke - of the beast with their children. Mammon awoke, and lo! it was -naught but a follower. -

- -

-from The Book of Mozilla, 11:9
(10th Edition) -

- - - diff --git a/servo/tests/html/test_underline_helloworld.html b/servo/tests/html/test_underline_helloworld.html deleted file mode 100644 index 3613a270e11c..000000000000 --- a/servo/tests/html/test_underline_helloworld.html +++ /dev/null @@ -1,16 +0,0 @@ - - - -The Book of Mozilla, 11:9 - - - - -
-
Hello!
-
World
-
- - diff --git a/servo/tests/html/test_webgl_context_attributes.html b/servo/tests/html/test_webgl_context_attributes.html deleted file mode 100644 index d25ce6a6f2d3..000000000000 --- a/servo/tests/html/test_webgl_context_attributes.html +++ /dev/null @@ -1,39 +0,0 @@ - -WebGL Context Attributes test - diff --git a/servo/tests/html/test_webgl_context_get_parameter.html b/servo/tests/html/test_webgl_context_get_parameter.html deleted file mode 100644 index 06da07f607ce..000000000000 --- a/servo/tests/html/test_webgl_context_get_parameter.html +++ /dev/null @@ -1,12 +0,0 @@ - - -WebGLRenderingContext getParameter test - diff --git a/servo/tests/html/test_webgl_context_getters.html b/servo/tests/html/test_webgl_context_getters.html deleted file mode 100644 index a5025f486f0e..000000000000 --- a/servo/tests/html/test_webgl_context_getters.html +++ /dev/null @@ -1,14 +0,0 @@ - - -WebGLRenderingContext attributes test - diff --git a/servo/tests/html/test_webgl_texture_mipmaps.html b/servo/tests/html/test_webgl_texture_mipmaps.html deleted file mode 100644 index f641ddeceeef..000000000000 --- a/servo/tests/html/test_webgl_texture_mipmaps.html +++ /dev/null @@ -1,160 +0,0 @@ - - - - - WebGL Texture Mipmap - - -
- SEVO -
- - - - - diff --git a/servo/tests/html/test_webgl_triangle.html b/servo/tests/html/test_webgl_triangle.html deleted file mode 100644 index c1559a1b11fd..000000000000 --- a/servo/tests/html/test_webgl_triangle.html +++ /dev/null @@ -1,130 +0,0 @@ - - - - - WebGL Triangle Test - - -
- -
- - - - - diff --git a/servo/tests/html/text_deco_simple.html b/servo/tests/html/text_deco_simple.html deleted file mode 100644 index 73d48199c96e..000000000000 --- a/servo/tests/html/text_deco_simple.html +++ /dev/null @@ -1,17 +0,0 @@ - - - - - - -

none

-

text underline

-

text underline

-

text underline

-

-

text underline pqrstg

-

text overline xxxxxxxxXXXXXXX

-

text line-through xxxxxxxxXXXXX

-

text blink

- - diff --git a/servo/tests/html/text_rendering.html b/servo/tests/html/text_rendering.html deleted file mode 100644 index 13e69236f4fd..000000000000 --- a/servo/tests/html/text_rendering.html +++ /dev/null @@ -1,27 +0,0 @@ - - - - - - -
Harry finally caught the Snitch.
-
Harry finally caught the Snitch.
-
Harry finally caught the Snitch.
- - - diff --git a/servo/tests/html/textarea.html b/servo/tests/html/textarea.html deleted file mode 100644 index 21705f1daabe..000000000000 --- a/servo/tests/html/textarea.html +++ /dev/null @@ -1,25 +0,0 @@ - - - -
- - - - - - diff --git a/servo/tests/html/transition_all.html b/servo/tests/html/transition_all.html deleted file mode 100644 index 1d9a199d5cab..000000000000 --- a/servo/tests/html/transition_all.html +++ /dev/null @@ -1,29 +0,0 @@ - - - - - - -
- - - - - diff --git a/servo/tests/html/transition_multiple.html b/servo/tests/html/transition_multiple.html deleted file mode 100644 index 14d99ddfeff6..000000000000 --- a/servo/tests/html/transition_multiple.html +++ /dev/null @@ -1,28 +0,0 @@ - - - - - - -
- - - - - diff --git a/servo/tests/html/transition_simple.html b/servo/tests/html/transition_simple.html deleted file mode 100644 index 0cfdb0731522..000000000000 --- a/servo/tests/html/transition_simple.html +++ /dev/null @@ -1,96 +0,0 @@ - - - - - - -
-
-
-
-
-
-
-
-
- - - - diff --git a/servo/tests/html/vertical_align_simple.html b/servo/tests/html/vertical_align_simple.html deleted file mode 100644 index a33ca2135ad8..000000000000 --- a/servo/tests/html/vertical_align_simple.html +++ /dev/null @@ -1,24 +0,0 @@ - - - - -

- [test1] baseline -

-

- [test2] vertical-align:top -

-

- [test3] vertical-align:middle -

-

- [test4] vertical-align:bottom -

-

- [test5] img=>text-top -

-

- [test6] img=>text-bottom -

- - diff --git a/servo/tests/html/viewport.html b/servo/tests/html/viewport.html deleted file mode 100644 index bd0dbb8bc65c..000000000000 --- a/servo/tests/html/viewport.html +++ /dev/null @@ -1,42 +0,0 @@ - - - - Test innerHeight - - - - - -
-
-
-
-
-
-
-
-
-
-
-
-
- - -
- - - diff --git a/servo/tests/html/webvr/advanced-mirroring.html b/servo/tests/html/webvr/advanced-mirroring.html deleted file mode 100644 index ffb7ae2d3f88..000000000000 --- a/servo/tests/html/webvr/advanced-mirroring.html +++ /dev/null @@ -1,320 +0,0 @@ - - - - - - - - - - 07 - Advanced Mirroring - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/servo/tests/html/webvr/dynamic-resolution.html b/servo/tests/html/webvr/dynamic-resolution.html deleted file mode 100644 index fe421870187d..000000000000 --- a/servo/tests/html/webvr/dynamic-resolution.html +++ /dev/null @@ -1,312 +0,0 @@ - - - - - - - - - - 08 - Dynamic Resolution - - - - - - - - - - - - - - - - - - - - - - -
- -
- - - diff --git a/servo/tests/html/webvr/js/third-party/gl-matrix-min.js b/servo/tests/html/webvr/js/third-party/gl-matrix-min.js deleted file mode 100644 index 697bb5ceb322..000000000000 --- a/servo/tests/html/webvr/js/third-party/gl-matrix-min.js +++ /dev/null @@ -1,29 +0,0 @@ -/** - * @fileoverview gl-matrix - High performance matrix and vector operations - * @author Brandon Jones - * @author Colin MacKenzie IV - * @version 2.3.2 - */ - -/* Copyright (c) 2015, Brandon Jones, Colin MacKenzie IV. - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. */ - -!function(t,a){if("object"==typeof exports&&"object"==typeof module)module.exports=a();else if("function"==typeof define&&define.amd)define([],a);else{var n=a();for(var r in n)("object"==typeof exports?exports:t)[r]=n[r]}}(this,function(){return function(t){function a(r){if(n[r])return n[r].exports;var o=n[r]={exports:{},id:r,loaded:!1};return t[r].call(o.exports,o,o.exports,a),o.loaded=!0,o.exports}var n={};return a.m=t,a.c=n,a.p="",a(0)}([function(t,a,n){a.glMatrix=n(1),a.mat2=n(2),a.mat2d=n(3),a.mat3=n(4),a.mat4=n(5),a.quat=n(6),a.vec2=n(9),a.vec3=n(7),a.vec4=n(8)},function(t,a){var n={};n.EPSILON=1e-6,n.ARRAY_TYPE="undefined"!=typeof Float32Array?Float32Array:Array,n.RANDOM=Math.random,n.ENABLE_SIMD=!1,n.SIMD_AVAILABLE=n.ARRAY_TYPE===Float32Array&&"SIMD"in this,n.USE_SIMD=n.ENABLE_SIMD&&n.SIMD_AVAILABLE,n.setMatrixArrayType=function(t){n.ARRAY_TYPE=t};var r=Math.PI/180;n.toRadian=function(t){return t*r},n.equals=function(t,a){return Math.abs(t-a)<=n.EPSILON*Math.max(1,Math.abs(t),Math.abs(a))},t.exports=n},function(t,a,n){var r=n(1),o={};o.create=function(){var t=new r.ARRAY_TYPE(4);return t[0]=1,t[1]=0,t[2]=0,t[3]=1,t},o.clone=function(t){var a=new r.ARRAY_TYPE(4);return a[0]=t[0],a[1]=t[1],a[2]=t[2],a[3]=t[3],a},o.copy=function(t,a){return t[0]=a[0],t[1]=a[1],t[2]=a[2],t[3]=a[3],t},o.identity=function(t){return t[0]=1,t[1]=0,t[2]=0,t[3]=1,t},o.fromValues=function(t,a,n,o){var u=new r.ARRAY_TYPE(4);return u[0]=t,u[1]=a,u[2]=n,u[3]=o,u},o.set=function(t,a,n,r,o){return t[0]=a,t[1]=n,t[2]=r,t[3]=o,t},o.transpose=function(t,a){if(t===a){var n=a[1];t[1]=a[2],t[2]=n}else t[0]=a[0],t[1]=a[2],t[2]=a[1],t[3]=a[3];return t},o.invert=function(t,a){var n=a[0],r=a[1],o=a[2],u=a[3],l=n*u-o*r;return l?(l=1/l,t[0]=u*l,t[1]=-r*l,t[2]=-o*l,t[3]=n*l,t):null},o.adjoint=function(t,a){var n=a[0];return t[0]=a[3],t[1]=-a[1],t[2]=-a[2],t[3]=n,t},o.determinant=function(t){return t[0]*t[3]-t[2]*t[1]},o.multiply=function(t,a,n){var r=a[0],o=a[1],u=a[2],l=a[3],e=n[0],M=n[1],s=n[2],i=n[3];return t[0]=r*e+u*M,t[1]=o*e+l*M,t[2]=r*s+u*i,t[3]=o*s+l*i,t},o.mul=o.multiply,o.rotate=function(t,a,n){var r=a[0],o=a[1],u=a[2],l=a[3],e=Math.sin(n),M=Math.cos(n);return t[0]=r*M+u*e,t[1]=o*M+l*e,t[2]=r*-e+u*M,t[3]=o*-e+l*M,t},o.scale=function(t,a,n){var r=a[0],o=a[1],u=a[2],l=a[3],e=n[0],M=n[1];return t[0]=r*e,t[1]=o*e,t[2]=u*M,t[3]=l*M,t},o.fromRotation=function(t,a){var n=Math.sin(a),r=Math.cos(a);return t[0]=r,t[1]=n,t[2]=-n,t[3]=r,t},o.fromScaling=function(t,a){return t[0]=a[0],t[1]=0,t[2]=0,t[3]=a[1],t},o.str=function(t){return"mat2("+t[0]+", "+t[1]+", "+t[2]+", "+t[3]+")"},o.frob=function(t){return Math.sqrt(Math.pow(t[0],2)+Math.pow(t[1],2)+Math.pow(t[2],2)+Math.pow(t[3],2))},o.LDU=function(t,a,n,r){return t[2]=r[2]/r[0],n[0]=r[0],n[1]=r[1],n[3]=r[3]-t[2]*n[1],[t,a,n]},o.add=function(t,a,n){return t[0]=a[0]+n[0],t[1]=a[1]+n[1],t[2]=a[2]+n[2],t[3]=a[3]+n[3],t},o.subtract=function(t,a,n){return t[0]=a[0]-n[0],t[1]=a[1]-n[1],t[2]=a[2]-n[2],t[3]=a[3]-n[3],t},o.sub=o.subtract,o.exactEquals=function(t,a){return t[0]===a[0]&&t[1]===a[1]&&t[2]===a[2]&&t[3]===a[3]},o.equals=function(t,a){var n=t[0],o=t[1],u=t[2],l=t[3],e=a[0],M=a[1],s=a[2],i=a[3];return Math.abs(n-e)<=r.EPSILON*Math.max(1,Math.abs(n),Math.abs(e))&&Math.abs(o-M)<=r.EPSILON*Math.max(1,Math.abs(o),Math.abs(M))&&Math.abs(u-s)<=r.EPSILON*Math.max(1,Math.abs(u),Math.abs(s))&&Math.abs(l-i)<=r.EPSILON*Math.max(1,Math.abs(l),Math.abs(i))},o.multiplyScalar=function(t,a,n){return t[0]=a[0]*n,t[1]=a[1]*n,t[2]=a[2]*n,t[3]=a[3]*n,t},o.multiplyScalarAndAdd=function(t,a,n,r){return t[0]=a[0]+n[0]*r,t[1]=a[1]+n[1]*r,t[2]=a[2]+n[2]*r,t[3]=a[3]+n[3]*r,t},t.exports=o},function(t,a,n){var r=n(1),o={};o.create=function(){var t=new r.ARRAY_TYPE(6);return t[0]=1,t[1]=0,t[2]=0,t[3]=1,t[4]=0,t[5]=0,t},o.clone=function(t){var a=new r.ARRAY_TYPE(6);return a[0]=t[0],a[1]=t[1],a[2]=t[2],a[3]=t[3],a[4]=t[4],a[5]=t[5],a},o.copy=function(t,a){return t[0]=a[0],t[1]=a[1],t[2]=a[2],t[3]=a[3],t[4]=a[4],t[5]=a[5],t},o.identity=function(t){return t[0]=1,t[1]=0,t[2]=0,t[3]=1,t[4]=0,t[5]=0,t},o.fromValues=function(t,a,n,o,u,l){var e=new r.ARRAY_TYPE(6);return e[0]=t,e[1]=a,e[2]=n,e[3]=o,e[4]=u,e[5]=l,e},o.set=function(t,a,n,r,o,u,l){return t[0]=a,t[1]=n,t[2]=r,t[3]=o,t[4]=u,t[5]=l,t},o.invert=function(t,a){var n=a[0],r=a[1],o=a[2],u=a[3],l=a[4],e=a[5],M=n*u-r*o;return M?(M=1/M,t[0]=u*M,t[1]=-r*M,t[2]=-o*M,t[3]=n*M,t[4]=(o*e-u*l)*M,t[5]=(r*l-n*e)*M,t):null},o.determinant=function(t){return t[0]*t[3]-t[1]*t[2]},o.multiply=function(t,a,n){var r=a[0],o=a[1],u=a[2],l=a[3],e=a[4],M=a[5],s=n[0],i=n[1],c=n[2],h=n[3],S=n[4],I=n[5];return t[0]=r*s+u*i,t[1]=o*s+l*i,t[2]=r*c+u*h,t[3]=o*c+l*h,t[4]=r*S+u*I+e,t[5]=o*S+l*I+M,t},o.mul=o.multiply,o.rotate=function(t,a,n){var r=a[0],o=a[1],u=a[2],l=a[3],e=a[4],M=a[5],s=Math.sin(n),i=Math.cos(n);return t[0]=r*i+u*s,t[1]=o*i+l*s,t[2]=r*-s+u*i,t[3]=o*-s+l*i,t[4]=e,t[5]=M,t},o.scale=function(t,a,n){var r=a[0],o=a[1],u=a[2],l=a[3],e=a[4],M=a[5],s=n[0],i=n[1];return t[0]=r*s,t[1]=o*s,t[2]=u*i,t[3]=l*i,t[4]=e,t[5]=M,t},o.translate=function(t,a,n){var r=a[0],o=a[1],u=a[2],l=a[3],e=a[4],M=a[5],s=n[0],i=n[1];return t[0]=r,t[1]=o,t[2]=u,t[3]=l,t[4]=r*s+u*i+e,t[5]=o*s+l*i+M,t},o.fromRotation=function(t,a){var n=Math.sin(a),r=Math.cos(a);return t[0]=r,t[1]=n,t[2]=-n,t[3]=r,t[4]=0,t[5]=0,t},o.fromScaling=function(t,a){return t[0]=a[0],t[1]=0,t[2]=0,t[3]=a[1],t[4]=0,t[5]=0,t},o.fromTranslation=function(t,a){return t[0]=1,t[1]=0,t[2]=0,t[3]=1,t[4]=a[0],t[5]=a[1],t},o.str=function(t){return"mat2d("+t[0]+", "+t[1]+", "+t[2]+", "+t[3]+", "+t[4]+", "+t[5]+")"},o.frob=function(t){return Math.sqrt(Math.pow(t[0],2)+Math.pow(t[1],2)+Math.pow(t[2],2)+Math.pow(t[3],2)+Math.pow(t[4],2)+Math.pow(t[5],2)+1)},o.add=function(t,a,n){return t[0]=a[0]+n[0],t[1]=a[1]+n[1],t[2]=a[2]+n[2],t[3]=a[3]+n[3],t[4]=a[4]+n[4],t[5]=a[5]+n[5],t},o.subtract=function(t,a,n){return t[0]=a[0]-n[0],t[1]=a[1]-n[1],t[2]=a[2]-n[2],t[3]=a[3]-n[3],t[4]=a[4]-n[4],t[5]=a[5]-n[5],t},o.sub=o.subtract,o.multiplyScalar=function(t,a,n){return t[0]=a[0]*n,t[1]=a[1]*n,t[2]=a[2]*n,t[3]=a[3]*n,t[4]=a[4]*n,t[5]=a[5]*n,t},o.multiplyScalarAndAdd=function(t,a,n,r){return t[0]=a[0]+n[0]*r,t[1]=a[1]+n[1]*r,t[2]=a[2]+n[2]*r,t[3]=a[3]+n[3]*r,t[4]=a[4]+n[4]*r,t[5]=a[5]+n[5]*r,t},o.exactEquals=function(t,a){return t[0]===a[0]&&t[1]===a[1]&&t[2]===a[2]&&t[3]===a[3]&&t[4]===a[4]&&t[5]===a[5]},o.equals=function(t,a){var n=t[0],o=t[1],u=t[2],l=t[3],e=t[4],M=t[5],s=a[0],i=a[1],c=a[2],h=a[3],S=a[4],I=a[5];return Math.abs(n-s)<=r.EPSILON*Math.max(1,Math.abs(n),Math.abs(s))&&Math.abs(o-i)<=r.EPSILON*Math.max(1,Math.abs(o),Math.abs(i))&&Math.abs(u-c)<=r.EPSILON*Math.max(1,Math.abs(u),Math.abs(c))&&Math.abs(l-h)<=r.EPSILON*Math.max(1,Math.abs(l),Math.abs(h))&&Math.abs(e-S)<=r.EPSILON*Math.max(1,Math.abs(e),Math.abs(S))&&Math.abs(M-I)<=r.EPSILON*Math.max(1,Math.abs(M),Math.abs(I))},t.exports=o},function(t,a,n){var r=n(1),o={};o.create=function(){var t=new r.ARRAY_TYPE(9);return t[0]=1,t[1]=0,t[2]=0,t[3]=0,t[4]=1,t[5]=0,t[6]=0,t[7]=0,t[8]=1,t},o.fromMat4=function(t,a){return t[0]=a[0],t[1]=a[1],t[2]=a[2],t[3]=a[4],t[4]=a[5],t[5]=a[6],t[6]=a[8],t[7]=a[9],t[8]=a[10],t},o.clone=function(t){var a=new r.ARRAY_TYPE(9);return a[0]=t[0],a[1]=t[1],a[2]=t[2],a[3]=t[3],a[4]=t[4],a[5]=t[5],a[6]=t[6],a[7]=t[7],a[8]=t[8],a},o.copy=function(t,a){return t[0]=a[0],t[1]=a[1],t[2]=a[2],t[3]=a[3],t[4]=a[4],t[5]=a[5],t[6]=a[6],t[7]=a[7],t[8]=a[8],t},o.fromValues=function(t,a,n,o,u,l,e,M,s){var i=new r.ARRAY_TYPE(9);return i[0]=t,i[1]=a,i[2]=n,i[3]=o,i[4]=u,i[5]=l,i[6]=e,i[7]=M,i[8]=s,i},o.set=function(t,a,n,r,o,u,l,e,M,s){return t[0]=a,t[1]=n,t[2]=r,t[3]=o,t[4]=u,t[5]=l,t[6]=e,t[7]=M,t[8]=s,t},o.identity=function(t){return t[0]=1,t[1]=0,t[2]=0,t[3]=0,t[4]=1,t[5]=0,t[6]=0,t[7]=0,t[8]=1,t},o.transpose=function(t,a){if(t===a){var n=a[1],r=a[2],o=a[5];t[1]=a[3],t[2]=a[6],t[3]=n,t[5]=a[7],t[6]=r,t[7]=o}else t[0]=a[0],t[1]=a[3],t[2]=a[6],t[3]=a[1],t[4]=a[4],t[5]=a[7],t[6]=a[2],t[7]=a[5],t[8]=a[8];return t},o.invert=function(t,a){var n=a[0],r=a[1],o=a[2],u=a[3],l=a[4],e=a[5],M=a[6],s=a[7],i=a[8],c=i*l-e*s,h=-i*u+e*M,S=s*u-l*M,I=n*c+r*h+o*S;return I?(I=1/I,t[0]=c*I,t[1]=(-i*r+o*s)*I,t[2]=(e*r-o*l)*I,t[3]=h*I,t[4]=(i*n-o*M)*I,t[5]=(-e*n+o*u)*I,t[6]=S*I,t[7]=(-s*n+r*M)*I,t[8]=(l*n-r*u)*I,t):null},o.adjoint=function(t,a){var n=a[0],r=a[1],o=a[2],u=a[3],l=a[4],e=a[5],M=a[6],s=a[7],i=a[8];return t[0]=l*i-e*s,t[1]=o*s-r*i,t[2]=r*e-o*l,t[3]=e*M-u*i,t[4]=n*i-o*M,t[5]=o*u-n*e,t[6]=u*s-l*M,t[7]=r*M-n*s,t[8]=n*l-r*u,t},o.determinant=function(t){var a=t[0],n=t[1],r=t[2],o=t[3],u=t[4],l=t[5],e=t[6],M=t[7],s=t[8];return a*(s*u-l*M)+n*(-s*o+l*e)+r*(M*o-u*e)},o.multiply=function(t,a,n){var r=a[0],o=a[1],u=a[2],l=a[3],e=a[4],M=a[5],s=a[6],i=a[7],c=a[8],h=n[0],S=n[1],I=n[2],f=n[3],x=n[4],D=n[5],F=n[6],m=n[7],d=n[8];return t[0]=h*r+S*l+I*s,t[1]=h*o+S*e+I*i,t[2]=h*u+S*M+I*c,t[3]=f*r+x*l+D*s,t[4]=f*o+x*e+D*i,t[5]=f*u+x*M+D*c,t[6]=F*r+m*l+d*s,t[7]=F*o+m*e+d*i,t[8]=F*u+m*M+d*c,t},o.mul=o.multiply,o.translate=function(t,a,n){var r=a[0],o=a[1],u=a[2],l=a[3],e=a[4],M=a[5],s=a[6],i=a[7],c=a[8],h=n[0],S=n[1];return t[0]=r,t[1]=o,t[2]=u,t[3]=l,t[4]=e,t[5]=M,t[6]=h*r+S*l+s,t[7]=h*o+S*e+i,t[8]=h*u+S*M+c,t},o.rotate=function(t,a,n){var r=a[0],o=a[1],u=a[2],l=a[3],e=a[4],M=a[5],s=a[6],i=a[7],c=a[8],h=Math.sin(n),S=Math.cos(n);return t[0]=S*r+h*l,t[1]=S*o+h*e,t[2]=S*u+h*M,t[3]=S*l-h*r,t[4]=S*e-h*o,t[5]=S*M-h*u,t[6]=s,t[7]=i,t[8]=c,t},o.scale=function(t,a,n){var r=n[0],o=n[1];return t[0]=r*a[0],t[1]=r*a[1],t[2]=r*a[2],t[3]=o*a[3],t[4]=o*a[4],t[5]=o*a[5],t[6]=a[6],t[7]=a[7],t[8]=a[8],t},o.fromTranslation=function(t,a){return t[0]=1,t[1]=0,t[2]=0,t[3]=0,t[4]=1,t[5]=0,t[6]=a[0],t[7]=a[1],t[8]=1,t},o.fromRotation=function(t,a){var n=Math.sin(a),r=Math.cos(a);return t[0]=r,t[1]=n,t[2]=0,t[3]=-n,t[4]=r,t[5]=0,t[6]=0,t[7]=0,t[8]=1,t},o.fromScaling=function(t,a){return t[0]=a[0],t[1]=0,t[2]=0,t[3]=0,t[4]=a[1],t[5]=0,t[6]=0,t[7]=0,t[8]=1,t},o.fromMat2d=function(t,a){return t[0]=a[0],t[1]=a[1],t[2]=0,t[3]=a[2],t[4]=a[3],t[5]=0,t[6]=a[4],t[7]=a[5],t[8]=1,t},o.fromQuat=function(t,a){var n=a[0],r=a[1],o=a[2],u=a[3],l=n+n,e=r+r,M=o+o,s=n*l,i=r*l,c=r*e,h=o*l,S=o*e,I=o*M,f=u*l,x=u*e,D=u*M;return t[0]=1-c-I,t[3]=i-D,t[6]=h+x,t[1]=i+D,t[4]=1-s-I,t[7]=S-f,t[2]=h-x,t[5]=S+f,t[8]=1-s-c,t},o.normalFromMat4=function(t,a){var n=a[0],r=a[1],o=a[2],u=a[3],l=a[4],e=a[5],M=a[6],s=a[7],i=a[8],c=a[9],h=a[10],S=a[11],I=a[12],f=a[13],x=a[14],D=a[15],F=n*e-r*l,m=n*M-o*l,d=n*s-u*l,b=r*M-o*e,v=r*s-u*e,z=o*s-u*M,p=i*f-c*I,w=i*x-h*I,E=i*D-S*I,A=c*x-h*f,P=c*D-S*f,L=h*D-S*x,q=F*L-m*P+d*A+b*E-v*w+z*p;return q?(q=1/q,t[0]=(e*L-M*P+s*A)*q,t[1]=(M*E-l*L-s*w)*q,t[2]=(l*P-e*E+s*p)*q,t[3]=(o*P-r*L-u*A)*q,t[4]=(n*L-o*E+u*w)*q,t[5]=(r*E-n*P-u*p)*q,t[6]=(f*z-x*v+D*b)*q,t[7]=(x*d-I*z-D*m)*q,t[8]=(I*v-f*d+D*F)*q,t):null},o.str=function(t){return"mat3("+t[0]+", "+t[1]+", "+t[2]+", "+t[3]+", "+t[4]+", "+t[5]+", "+t[6]+", "+t[7]+", "+t[8]+")"},o.frob=function(t){return Math.sqrt(Math.pow(t[0],2)+Math.pow(t[1],2)+Math.pow(t[2],2)+Math.pow(t[3],2)+Math.pow(t[4],2)+Math.pow(t[5],2)+Math.pow(t[6],2)+Math.pow(t[7],2)+Math.pow(t[8],2))},o.add=function(t,a,n){return t[0]=a[0]+n[0],t[1]=a[1]+n[1],t[2]=a[2]+n[2],t[3]=a[3]+n[3],t[4]=a[4]+n[4],t[5]=a[5]+n[5],t[6]=a[6]+n[6],t[7]=a[7]+n[7],t[8]=a[8]+n[8],t},o.subtract=function(t,a,n){return t[0]=a[0]-n[0],t[1]=a[1]-n[1],t[2]=a[2]-n[2],t[3]=a[3]-n[3],t[4]=a[4]-n[4],t[5]=a[5]-n[5],t[6]=a[6]-n[6],t[7]=a[7]-n[7],t[8]=a[8]-n[8],t},o.sub=o.subtract,o.multiplyScalar=function(t,a,n){return t[0]=a[0]*n,t[1]=a[1]*n,t[2]=a[2]*n,t[3]=a[3]*n,t[4]=a[4]*n,t[5]=a[5]*n,t[6]=a[6]*n,t[7]=a[7]*n,t[8]=a[8]*n,t},o.multiplyScalarAndAdd=function(t,a,n,r){return t[0]=a[0]+n[0]*r,t[1]=a[1]+n[1]*r,t[2]=a[2]+n[2]*r,t[3]=a[3]+n[3]*r,t[4]=a[4]+n[4]*r,t[5]=a[5]+n[5]*r,t[6]=a[6]+n[6]*r,t[7]=a[7]+n[7]*r,t[8]=a[8]+n[8]*r,t},o.exactEquals=function(t,a){return t[0]===a[0]&&t[1]===a[1]&&t[2]===a[2]&&t[3]===a[3]&&t[4]===a[4]&&t[5]===a[5]&&t[6]===a[6]&&t[7]===a[7]&&t[8]===a[8]},o.equals=function(t,a){var n=t[0],o=t[1],u=t[2],l=t[3],e=t[4],M=t[5],s=t[6],i=t[7],c=t[8],h=a[0],S=a[1],I=a[2],f=a[3],x=a[4],D=a[5],F=t[6],m=a[7],d=a[8];return Math.abs(n-h)<=r.EPSILON*Math.max(1,Math.abs(n),Math.abs(h))&&Math.abs(o-S)<=r.EPSILON*Math.max(1,Math.abs(o),Math.abs(S))&&Math.abs(u-I)<=r.EPSILON*Math.max(1,Math.abs(u),Math.abs(I))&&Math.abs(l-f)<=r.EPSILON*Math.max(1,Math.abs(l),Math.abs(f))&&Math.abs(e-x)<=r.EPSILON*Math.max(1,Math.abs(e),Math.abs(x))&&Math.abs(M-D)<=r.EPSILON*Math.max(1,Math.abs(M),Math.abs(D))&&Math.abs(s-F)<=r.EPSILON*Math.max(1,Math.abs(s),Math.abs(F))&&Math.abs(i-m)<=r.EPSILON*Math.max(1,Math.abs(i),Math.abs(m))&&Math.abs(c-d)<=r.EPSILON*Math.max(1,Math.abs(c),Math.abs(d))},t.exports=o},function(t,a,n){var r=n(1),o={scalar:{},SIMD:{}};o.create=function(){var t=new r.ARRAY_TYPE(16);return t[0]=1,t[1]=0,t[2]=0,t[3]=0,t[4]=0,t[5]=1,t[6]=0,t[7]=0,t[8]=0,t[9]=0,t[10]=1,t[11]=0,t[12]=0,t[13]=0,t[14]=0,t[15]=1,t},o.clone=function(t){var a=new r.ARRAY_TYPE(16);return a[0]=t[0],a[1]=t[1],a[2]=t[2],a[3]=t[3],a[4]=t[4],a[5]=t[5],a[6]=t[6],a[7]=t[7],a[8]=t[8],a[9]=t[9],a[10]=t[10],a[11]=t[11],a[12]=t[12],a[13]=t[13],a[14]=t[14],a[15]=t[15],a},o.copy=function(t,a){return t[0]=a[0],t[1]=a[1],t[2]=a[2],t[3]=a[3],t[4]=a[4],t[5]=a[5],t[6]=a[6],t[7]=a[7],t[8]=a[8],t[9]=a[9],t[10]=a[10],t[11]=a[11],t[12]=a[12],t[13]=a[13],t[14]=a[14],t[15]=a[15],t},o.fromValues=function(t,a,n,o,u,l,e,M,s,i,c,h,S,I,f,x){var D=new r.ARRAY_TYPE(16);return D[0]=t,D[1]=a,D[2]=n,D[3]=o,D[4]=u,D[5]=l,D[6]=e,D[7]=M,D[8]=s,D[9]=i,D[10]=c,D[11]=h,D[12]=S,D[13]=I,D[14]=f,D[15]=x,D},o.set=function(t,a,n,r,o,u,l,e,M,s,i,c,h,S,I,f,x){return t[0]=a,t[1]=n,t[2]=r,t[3]=o,t[4]=u,t[5]=l,t[6]=e,t[7]=M,t[8]=s,t[9]=i,t[10]=c,t[11]=h,t[12]=S,t[13]=I,t[14]=f,t[15]=x,t},o.identity=function(t){return t[0]=1,t[1]=0,t[2]=0,t[3]=0,t[4]=0,t[5]=1,t[6]=0,t[7]=0,t[8]=0,t[9]=0,t[10]=1,t[11]=0,t[12]=0,t[13]=0,t[14]=0,t[15]=1,t},o.scalar.transpose=function(t,a){if(t===a){var n=a[1],r=a[2],o=a[3],u=a[6],l=a[7],e=a[11];t[1]=a[4],t[2]=a[8],t[3]=a[12],t[4]=n,t[6]=a[9],t[7]=a[13],t[8]=r,t[9]=u,t[11]=a[14],t[12]=o,t[13]=l,t[14]=e}else t[0]=a[0],t[1]=a[4],t[2]=a[8],t[3]=a[12],t[4]=a[1],t[5]=a[5],t[6]=a[9],t[7]=a[13],t[8]=a[2],t[9]=a[6],t[10]=a[10],t[11]=a[14],t[12]=a[3],t[13]=a[7],t[14]=a[11],t[15]=a[15];return t},o.SIMD.transpose=function(t,a){var n,r,o,u,l,e,M,s,i,c;return n=SIMD.Float32x4.load(a,0),r=SIMD.Float32x4.load(a,4),o=SIMD.Float32x4.load(a,8),u=SIMD.Float32x4.load(a,12),l=SIMD.Float32x4.shuffle(n,r,0,1,4,5),e=SIMD.Float32x4.shuffle(o,u,0,1,4,5),M=SIMD.Float32x4.shuffle(l,e,0,2,4,6),s=SIMD.Float32x4.shuffle(l,e,1,3,5,7),SIMD.Float32x4.store(t,0,M),SIMD.Float32x4.store(t,4,s),l=SIMD.Float32x4.shuffle(n,r,2,3,6,7),e=SIMD.Float32x4.shuffle(o,u,2,3,6,7),i=SIMD.Float32x4.shuffle(l,e,0,2,4,6),c=SIMD.Float32x4.shuffle(l,e,1,3,5,7),SIMD.Float32x4.store(t,8,i),SIMD.Float32x4.store(t,12,c),t},o.transpose=r.USE_SIMD?o.SIMD.transpose:o.scalar.transpose,o.scalar.invert=function(t,a){var n=a[0],r=a[1],o=a[2],u=a[3],l=a[4],e=a[5],M=a[6],s=a[7],i=a[8],c=a[9],h=a[10],S=a[11],I=a[12],f=a[13],x=a[14],D=a[15],F=n*e-r*l,m=n*M-o*l,d=n*s-u*l,b=r*M-o*e,v=r*s-u*e,z=o*s-u*M,p=i*f-c*I,w=i*x-h*I,E=i*D-S*I,A=c*x-h*f,P=c*D-S*f,L=h*D-S*x,q=F*L-m*P+d*A+b*E-v*w+z*p;return q?(q=1/q,t[0]=(e*L-M*P+s*A)*q,t[1]=(o*P-r*L-u*A)*q,t[2]=(f*z-x*v+D*b)*q,t[3]=(h*v-c*z-S*b)*q,t[4]=(M*E-l*L-s*w)*q,t[5]=(n*L-o*E+u*w)*q,t[6]=(x*d-I*z-D*m)*q,t[7]=(i*z-h*d+S*m)*q,t[8]=(l*P-e*E+s*p)*q,t[9]=(r*E-n*P-u*p)*q,t[10]=(I*v-f*d+D*F)*q,t[11]=(c*d-i*v-S*F)*q,t[12]=(e*w-l*A-M*p)*q,t[13]=(n*A-r*w+o*p)*q,t[14]=(f*m-I*b-x*F)*q,t[15]=(i*b-c*m+h*F)*q,t):null},o.SIMD.invert=function(t,a){var n,r,o,u,l,e,M,s,i,c,h=SIMD.Float32x4.load(a,0),S=SIMD.Float32x4.load(a,4),I=SIMD.Float32x4.load(a,8),f=SIMD.Float32x4.load(a,12);return l=SIMD.Float32x4.shuffle(h,S,0,1,4,5),r=SIMD.Float32x4.shuffle(I,f,0,1,4,5),n=SIMD.Float32x4.shuffle(l,r,0,2,4,6),r=SIMD.Float32x4.shuffle(r,l,1,3,5,7),l=SIMD.Float32x4.shuffle(h,S,2,3,6,7),u=SIMD.Float32x4.shuffle(I,f,2,3,6,7),o=SIMD.Float32x4.shuffle(l,u,0,2,4,6),u=SIMD.Float32x4.shuffle(u,l,1,3,5,7),l=SIMD.Float32x4.mul(o,u),l=SIMD.Float32x4.swizzle(l,1,0,3,2),e=SIMD.Float32x4.mul(r,l),M=SIMD.Float32x4.mul(n,l),l=SIMD.Float32x4.swizzle(l,2,3,0,1),e=SIMD.Float32x4.sub(SIMD.Float32x4.mul(r,l),e),M=SIMD.Float32x4.sub(SIMD.Float32x4.mul(n,l),M),M=SIMD.Float32x4.swizzle(M,2,3,0,1),l=SIMD.Float32x4.mul(r,o),l=SIMD.Float32x4.swizzle(l,1,0,3,2),e=SIMD.Float32x4.add(SIMD.Float32x4.mul(u,l),e),i=SIMD.Float32x4.mul(n,l),l=SIMD.Float32x4.swizzle(l,2,3,0,1),e=SIMD.Float32x4.sub(e,SIMD.Float32x4.mul(u,l)),i=SIMD.Float32x4.sub(SIMD.Float32x4.mul(n,l),i),i=SIMD.Float32x4.swizzle(i,2,3,0,1),l=SIMD.Float32x4.mul(SIMD.Float32x4.swizzle(r,2,3,0,1),u),l=SIMD.Float32x4.swizzle(l,1,0,3,2),o=SIMD.Float32x4.swizzle(o,2,3,0,1),e=SIMD.Float32x4.add(SIMD.Float32x4.mul(o,l),e),s=SIMD.Float32x4.mul(n,l),l=SIMD.Float32x4.swizzle(l,2,3,0,1),e=SIMD.Float32x4.sub(e,SIMD.Float32x4.mul(o,l)),s=SIMD.Float32x4.sub(SIMD.Float32x4.mul(n,l),s),s=SIMD.Float32x4.swizzle(s,2,3,0,1),l=SIMD.Float32x4.mul(n,r),l=SIMD.Float32x4.swizzle(l,1,0,3,2),s=SIMD.Float32x4.add(SIMD.Float32x4.mul(u,l),s),i=SIMD.Float32x4.sub(SIMD.Float32x4.mul(o,l),i),l=SIMD.Float32x4.swizzle(l,2,3,0,1),s=SIMD.Float32x4.sub(SIMD.Float32x4.mul(u,l),s),i=SIMD.Float32x4.sub(i,SIMD.Float32x4.mul(o,l)),l=SIMD.Float32x4.mul(n,u),l=SIMD.Float32x4.swizzle(l,1,0,3,2),M=SIMD.Float32x4.sub(M,SIMD.Float32x4.mul(o,l)),s=SIMD.Float32x4.add(SIMD.Float32x4.mul(r,l),s),l=SIMD.Float32x4.swizzle(l,2,3,0,1),M=SIMD.Float32x4.add(SIMD.Float32x4.mul(o,l),M),s=SIMD.Float32x4.sub(s,SIMD.Float32x4.mul(r,l)),l=SIMD.Float32x4.mul(n,o),l=SIMD.Float32x4.swizzle(l,1,0,3,2),M=SIMD.Float32x4.add(SIMD.Float32x4.mul(u,l),M),i=SIMD.Float32x4.sub(i,SIMD.Float32x4.mul(r,l)),l=SIMD.Float32x4.swizzle(l,2,3,0,1),M=SIMD.Float32x4.sub(M,SIMD.Float32x4.mul(u,l)),i=SIMD.Float32x4.add(SIMD.Float32x4.mul(r,l),i),c=SIMD.Float32x4.mul(n,e),c=SIMD.Float32x4.add(SIMD.Float32x4.swizzle(c,2,3,0,1),c),c=SIMD.Float32x4.add(SIMD.Float32x4.swizzle(c,1,0,3,2),c),l=SIMD.Float32x4.reciprocalApproximation(c),c=SIMD.Float32x4.sub(SIMD.Float32x4.add(l,l),SIMD.Float32x4.mul(c,SIMD.Float32x4.mul(l,l))),(c=SIMD.Float32x4.swizzle(c,0,0,0,0))?(SIMD.Float32x4.store(t,0,SIMD.Float32x4.mul(c,e)),SIMD.Float32x4.store(t,4,SIMD.Float32x4.mul(c,M)),SIMD.Float32x4.store(t,8,SIMD.Float32x4.mul(c,s)),SIMD.Float32x4.store(t,12,SIMD.Float32x4.mul(c,i)),t):null},o.invert=r.USE_SIMD?o.SIMD.invert:o.scalar.invert,o.scalar.adjoint=function(t,a){var n=a[0],r=a[1],o=a[2],u=a[3],l=a[4],e=a[5],M=a[6],s=a[7],i=a[8],c=a[9],h=a[10],S=a[11],I=a[12],f=a[13],x=a[14],D=a[15];return t[0]=e*(h*D-S*x)-c*(M*D-s*x)+f*(M*S-s*h),t[1]=-(r*(h*D-S*x)-c*(o*D-u*x)+f*(o*S-u*h)),t[2]=r*(M*D-s*x)-e*(o*D-u*x)+f*(o*s-u*M),t[3]=-(r*(M*S-s*h)-e*(o*S-u*h)+c*(o*s-u*M)),t[4]=-(l*(h*D-S*x)-i*(M*D-s*x)+I*(M*S-s*h)),t[5]=n*(h*D-S*x)-i*(o*D-u*x)+I*(o*S-u*h),t[6]=-(n*(M*D-s*x)-l*(o*D-u*x)+I*(o*s-u*M)),t[7]=n*(M*S-s*h)-l*(o*S-u*h)+i*(o*s-u*M),t[8]=l*(c*D-S*f)-i*(e*D-s*f)+I*(e*S-s*c),t[9]=-(n*(c*D-S*f)-i*(r*D-u*f)+I*(r*S-u*c)),t[10]=n*(e*D-s*f)-l*(r*D-u*f)+I*(r*s-u*e),t[11]=-(n*(e*S-s*c)-l*(r*S-u*c)+i*(r*s-u*e)),t[12]=-(l*(c*x-h*f)-i*(e*x-M*f)+I*(e*h-M*c)),t[13]=n*(c*x-h*f)-i*(r*x-o*f)+I*(r*h-o*c),t[14]=-(n*(e*x-M*f)-l*(r*x-o*f)+I*(r*M-o*e)),t[15]=n*(e*h-M*c)-l*(r*h-o*c)+i*(r*M-o*e),t},o.SIMD.adjoint=function(t,a){var n,r,o,u,l,e,M,s,i,c,h,S,I,n=SIMD.Float32x4.load(a,0),r=SIMD.Float32x4.load(a,4),o=SIMD.Float32x4.load(a,8),u=SIMD.Float32x4.load(a,12);return i=SIMD.Float32x4.shuffle(n,r,0,1,4,5),e=SIMD.Float32x4.shuffle(o,u,0,1,4,5),l=SIMD.Float32x4.shuffle(i,e,0,2,4,6),e=SIMD.Float32x4.shuffle(e,i,1,3,5,7),i=SIMD.Float32x4.shuffle(n,r,2,3,6,7),s=SIMD.Float32x4.shuffle(o,u,2,3,6,7),M=SIMD.Float32x4.shuffle(i,s,0,2,4,6),s=SIMD.Float32x4.shuffle(s,i,1,3,5,7),i=SIMD.Float32x4.mul(M,s),i=SIMD.Float32x4.swizzle(i,1,0,3,2),c=SIMD.Float32x4.mul(e,i),h=SIMD.Float32x4.mul(l,i),i=SIMD.Float32x4.swizzle(i,2,3,0,1),c=SIMD.Float32x4.sub(SIMD.Float32x4.mul(e,i),c),h=SIMD.Float32x4.sub(SIMD.Float32x4.mul(l,i),h),h=SIMD.Float32x4.swizzle(h,2,3,0,1),i=SIMD.Float32x4.mul(e,M),i=SIMD.Float32x4.swizzle(i,1,0,3,2),c=SIMD.Float32x4.add(SIMD.Float32x4.mul(s,i),c),I=SIMD.Float32x4.mul(l,i),i=SIMD.Float32x4.swizzle(i,2,3,0,1),c=SIMD.Float32x4.sub(c,SIMD.Float32x4.mul(s,i)),I=SIMD.Float32x4.sub(SIMD.Float32x4.mul(l,i),I),I=SIMD.Float32x4.swizzle(I,2,3,0,1),i=SIMD.Float32x4.mul(SIMD.Float32x4.swizzle(e,2,3,0,1),s),i=SIMD.Float32x4.swizzle(i,1,0,3,2),M=SIMD.Float32x4.swizzle(M,2,3,0,1),c=SIMD.Float32x4.add(SIMD.Float32x4.mul(M,i),c),S=SIMD.Float32x4.mul(l,i),i=SIMD.Float32x4.swizzle(i,2,3,0,1),c=SIMD.Float32x4.sub(c,SIMD.Float32x4.mul(M,i)),S=SIMD.Float32x4.sub(SIMD.Float32x4.mul(l,i),S),S=SIMD.Float32x4.swizzle(S,2,3,0,1),i=SIMD.Float32x4.mul(l,e),i=SIMD.Float32x4.swizzle(i,1,0,3,2),S=SIMD.Float32x4.add(SIMD.Float32x4.mul(s,i),S),I=SIMD.Float32x4.sub(SIMD.Float32x4.mul(M,i),I),i=SIMD.Float32x4.swizzle(i,2,3,0,1),S=SIMD.Float32x4.sub(SIMD.Float32x4.mul(s,i),S),I=SIMD.Float32x4.sub(I,SIMD.Float32x4.mul(M,i)),i=SIMD.Float32x4.mul(l,s),i=SIMD.Float32x4.swizzle(i,1,0,3,2),h=SIMD.Float32x4.sub(h,SIMD.Float32x4.mul(M,i)),S=SIMD.Float32x4.add(SIMD.Float32x4.mul(e,i),S),i=SIMD.Float32x4.swizzle(i,2,3,0,1),h=SIMD.Float32x4.add(SIMD.Float32x4.mul(M,i),h),S=SIMD.Float32x4.sub(S,SIMD.Float32x4.mul(e,i)),i=SIMD.Float32x4.mul(l,M),i=SIMD.Float32x4.swizzle(i,1,0,3,2),h=SIMD.Float32x4.add(SIMD.Float32x4.mul(s,i),h),I=SIMD.Float32x4.sub(I,SIMD.Float32x4.mul(e,i)),i=SIMD.Float32x4.swizzle(i,2,3,0,1),h=SIMD.Float32x4.sub(h,SIMD.Float32x4.mul(s,i)),I=SIMD.Float32x4.add(SIMD.Float32x4.mul(e,i),I),SIMD.Float32x4.store(t,0,c),SIMD.Float32x4.store(t,4,h),SIMD.Float32x4.store(t,8,S),SIMD.Float32x4.store(t,12,I),t},o.adjoint=r.USE_SIMD?o.SIMD.adjoint:o.scalar.adjoint,o.determinant=function(t){var a=t[0],n=t[1],r=t[2],o=t[3],u=t[4],l=t[5],e=t[6],M=t[7],s=t[8],i=t[9],c=t[10],h=t[11],S=t[12],I=t[13],f=t[14],x=t[15],D=a*l-n*u,F=a*e-r*u,m=a*M-o*u,d=n*e-r*l,b=n*M-o*l,v=r*M-o*e,z=s*I-i*S,p=s*f-c*S,w=s*x-h*S,E=i*f-c*I,A=i*x-h*I,P=c*x-h*f;return D*P-F*A+m*E+d*w-b*p+v*z},o.SIMD.multiply=function(t,a,n){var r=SIMD.Float32x4.load(a,0),o=SIMD.Float32x4.load(a,4),u=SIMD.Float32x4.load(a,8),l=SIMD.Float32x4.load(a,12),e=SIMD.Float32x4.load(n,0),M=SIMD.Float32x4.add(SIMD.Float32x4.mul(SIMD.Float32x4.swizzle(e,0,0,0,0),r),SIMD.Float32x4.add(SIMD.Float32x4.mul(SIMD.Float32x4.swizzle(e,1,1,1,1),o),SIMD.Float32x4.add(SIMD.Float32x4.mul(SIMD.Float32x4.swizzle(e,2,2,2,2),u),SIMD.Float32x4.mul(SIMD.Float32x4.swizzle(e,3,3,3,3),l))));SIMD.Float32x4.store(t,0,M);var s=SIMD.Float32x4.load(n,4),i=SIMD.Float32x4.add(SIMD.Float32x4.mul(SIMD.Float32x4.swizzle(s,0,0,0,0),r),SIMD.Float32x4.add(SIMD.Float32x4.mul(SIMD.Float32x4.swizzle(s,1,1,1,1),o),SIMD.Float32x4.add(SIMD.Float32x4.mul(SIMD.Float32x4.swizzle(s,2,2,2,2),u),SIMD.Float32x4.mul(SIMD.Float32x4.swizzle(s,3,3,3,3),l))));SIMD.Float32x4.store(t,4,i);var c=SIMD.Float32x4.load(n,8),h=SIMD.Float32x4.add(SIMD.Float32x4.mul(SIMD.Float32x4.swizzle(c,0,0,0,0),r),SIMD.Float32x4.add(SIMD.Float32x4.mul(SIMD.Float32x4.swizzle(c,1,1,1,1),o),SIMD.Float32x4.add(SIMD.Float32x4.mul(SIMD.Float32x4.swizzle(c,2,2,2,2),u),SIMD.Float32x4.mul(SIMD.Float32x4.swizzle(c,3,3,3,3),l))));SIMD.Float32x4.store(t,8,h);var S=SIMD.Float32x4.load(n,12),I=SIMD.Float32x4.add(SIMD.Float32x4.mul(SIMD.Float32x4.swizzle(S,0,0,0,0),r),SIMD.Float32x4.add(SIMD.Float32x4.mul(SIMD.Float32x4.swizzle(S,1,1,1,1),o),SIMD.Float32x4.add(SIMD.Float32x4.mul(SIMD.Float32x4.swizzle(S,2,2,2,2),u),SIMD.Float32x4.mul(SIMD.Float32x4.swizzle(S,3,3,3,3),l))));return SIMD.Float32x4.store(t,12,I),t},o.scalar.multiply=function(t,a,n){var r=a[0],o=a[1],u=a[2],l=a[3],e=a[4],M=a[5],s=a[6],i=a[7],c=a[8],h=a[9],S=a[10],I=a[11],f=a[12],x=a[13],D=a[14],F=a[15],m=n[0],d=n[1],b=n[2],v=n[3];return t[0]=m*r+d*e+b*c+v*f,t[1]=m*o+d*M+b*h+v*x,t[2]=m*u+d*s+b*S+v*D,t[3]=m*l+d*i+b*I+v*F,m=n[4],d=n[5],b=n[6],v=n[7],t[4]=m*r+d*e+b*c+v*f,t[5]=m*o+d*M+b*h+v*x,t[6]=m*u+d*s+b*S+v*D,t[7]=m*l+d*i+b*I+v*F,m=n[8],d=n[9],b=n[10],v=n[11],t[8]=m*r+d*e+b*c+v*f,t[9]=m*o+d*M+b*h+v*x,t[10]=m*u+d*s+b*S+v*D,t[11]=m*l+d*i+b*I+v*F,m=n[12],d=n[13],b=n[14],v=n[15],t[12]=m*r+d*e+b*c+v*f,t[13]=m*o+d*M+b*h+v*x,t[14]=m*u+d*s+b*S+v*D,t[15]=m*l+d*i+b*I+v*F,t},o.multiply=r.USE_SIMD?o.SIMD.multiply:o.scalar.multiply,o.mul=o.multiply,o.scalar.translate=function(t,a,n){var r,o,u,l,e,M,s,i,c,h,S,I,f=n[0],x=n[1],D=n[2];return a===t?(t[12]=a[0]*f+a[4]*x+a[8]*D+a[12],t[13]=a[1]*f+a[5]*x+a[9]*D+a[13],t[14]=a[2]*f+a[6]*x+a[10]*D+a[14],t[15]=a[3]*f+a[7]*x+a[11]*D+a[15]):(r=a[0],o=a[1],u=a[2],l=a[3],e=a[4],M=a[5],s=a[6],i=a[7],c=a[8],h=a[9],S=a[10],I=a[11],t[0]=r,t[1]=o,t[2]=u,t[3]=l,t[4]=e,t[5]=M,t[6]=s,t[7]=i,t[8]=c,t[9]=h,t[10]=S,t[11]=I,t[12]=r*f+e*x+c*D+a[12],t[13]=o*f+M*x+h*D+a[13],t[14]=u*f+s*x+S*D+a[14],t[15]=l*f+i*x+I*D+a[15]),t},o.SIMD.translate=function(t,a,n){var r=SIMD.Float32x4.load(a,0),o=SIMD.Float32x4.load(a,4),u=SIMD.Float32x4.load(a,8),l=SIMD.Float32x4.load(a,12),e=SIMD.Float32x4(n[0],n[1],n[2],0);a!==t&&(t[0]=a[0],t[1]=a[1],t[2]=a[2],t[3]=a[3],t[4]=a[4],t[5]=a[5],t[6]=a[6],t[7]=a[7],t[8]=a[8],t[9]=a[9],t[10]=a[10],t[11]=a[11]),r=SIMD.Float32x4.mul(r,SIMD.Float32x4.swizzle(e,0,0,0,0)),o=SIMD.Float32x4.mul(o,SIMD.Float32x4.swizzle(e,1,1,1,1)),u=SIMD.Float32x4.mul(u,SIMD.Float32x4.swizzle(e,2,2,2,2));var M=SIMD.Float32x4.add(r,SIMD.Float32x4.add(o,SIMD.Float32x4.add(u,l)));return SIMD.Float32x4.store(t,12,M),t},o.translate=r.USE_SIMD?o.SIMD.translate:o.scalar.translate,o.scalar.scale=function(t,a,n){var r=n[0],o=n[1],u=n[2];return t[0]=a[0]*r,t[1]=a[1]*r,t[2]=a[2]*r,t[3]=a[3]*r,t[4]=a[4]*o,t[5]=a[5]*o,t[6]=a[6]*o,t[7]=a[7]*o,t[8]=a[8]*u,t[9]=a[9]*u,t[10]=a[10]*u,t[11]=a[11]*u,t[12]=a[12],t[13]=a[13],t[14]=a[14],t[15]=a[15],t},o.SIMD.scale=function(t,a,n){var r,o,u,l=SIMD.Float32x4(n[0],n[1],n[2],0);return r=SIMD.Float32x4.load(a,0),SIMD.Float32x4.store(t,0,SIMD.Float32x4.mul(r,SIMD.Float32x4.swizzle(l,0,0,0,0))),o=SIMD.Float32x4.load(a,4),SIMD.Float32x4.store(t,4,SIMD.Float32x4.mul(o,SIMD.Float32x4.swizzle(l,1,1,1,1))),u=SIMD.Float32x4.load(a,8),SIMD.Float32x4.store(t,8,SIMD.Float32x4.mul(u,SIMD.Float32x4.swizzle(l,2,2,2,2))),t[12]=a[12],t[13]=a[13],t[14]=a[14],t[15]=a[15],t},o.scale=r.USE_SIMD?o.SIMD.scale:o.scalar.scale,o.rotate=function(t,a,n,o){var u,l,e,M,s,i,c,h,S,I,f,x,D,F,m,d,b,v,z,p,w,E,A,P,L=o[0],q=o[1],R=o[2],N=Math.sqrt(L*L+q*q+R*R);return Math.abs(N)0?(r=2*Math.sqrt(n+1),t[3]=.25*r,t[0]=(a[6]-a[9])/r,t[1]=(a[8]-a[2])/r,t[2]=(a[1]-a[4])/r):a[0]>a[5]&a[0]>a[10]?(r=2*Math.sqrt(1+a[0]-a[5]-a[10]),t[3]=(a[6]-a[9])/r,t[0]=.25*r,t[1]=(a[1]+a[4])/r,t[2]=(a[8]+a[2])/r):a[5]>a[10]?(r=2*Math.sqrt(1+a[5]-a[0]-a[10]),t[3]=(a[8]-a[2])/r,t[0]=(a[1]+a[4])/r,t[1]=.25*r,t[2]=(a[6]+a[9])/r):(r=2*Math.sqrt(1+a[10]-a[0]-a[5]),t[3]=(a[1]-a[4])/r,t[0]=(a[8]+a[2])/r,t[1]=(a[6]+a[9])/r,t[2]=.25*r),t},o.fromRotationTranslationScale=function(t,a,n,r){var o=a[0],u=a[1],l=a[2],e=a[3],M=o+o,s=u+u,i=l+l,c=o*M,h=o*s,S=o*i,I=u*s,f=u*i,x=l*i,D=e*M,F=e*s,m=e*i,d=r[0],b=r[1],v=r[2];return t[0]=(1-(I+x))*d,t[1]=(h+m)*d,t[2]=(S-F)*d,t[3]=0,t[4]=(h-m)*b,t[5]=(1-(c+x))*b,t[6]=(f+D)*b,t[7]=0,t[8]=(S+F)*v,t[9]=(f-D)*v,t[10]=(1-(c+I))*v,t[11]=0,t[12]=n[0],t[13]=n[1],t[14]=n[2],t[15]=1,t},o.fromRotationTranslationScaleOrigin=function(t,a,n,r,o){ -var u=a[0],l=a[1],e=a[2],M=a[3],s=u+u,i=l+l,c=e+e,h=u*s,S=u*i,I=u*c,f=l*i,x=l*c,D=e*c,F=M*s,m=M*i,d=M*c,b=r[0],v=r[1],z=r[2],p=o[0],w=o[1],E=o[2];return t[0]=(1-(f+D))*b,t[1]=(S+d)*b,t[2]=(I-m)*b,t[3]=0,t[4]=(S-d)*v,t[5]=(1-(h+D))*v,t[6]=(x+F)*v,t[7]=0,t[8]=(I+m)*z,t[9]=(x-F)*z,t[10]=(1-(h+f))*z,t[11]=0,t[12]=n[0]+p-(t[0]*p+t[4]*w+t[8]*E),t[13]=n[1]+w-(t[1]*p+t[5]*w+t[9]*E),t[14]=n[2]+E-(t[2]*p+t[6]*w+t[10]*E),t[15]=1,t},o.fromQuat=function(t,a){var n=a[0],r=a[1],o=a[2],u=a[3],l=n+n,e=r+r,M=o+o,s=n*l,i=r*l,c=r*e,h=o*l,S=o*e,I=o*M,f=u*l,x=u*e,D=u*M;return t[0]=1-c-I,t[1]=i+D,t[2]=h-x,t[3]=0,t[4]=i-D,t[5]=1-s-I,t[6]=S+f,t[7]=0,t[8]=h+x,t[9]=S-f,t[10]=1-s-c,t[11]=0,t[12]=0,t[13]=0,t[14]=0,t[15]=1,t},o.frustum=function(t,a,n,r,o,u,l){var e=1/(n-a),M=1/(o-r),s=1/(u-l);return t[0]=2*u*e,t[1]=0,t[2]=0,t[3]=0,t[4]=0,t[5]=2*u*M,t[6]=0,t[7]=0,t[8]=(n+a)*e,t[9]=(o+r)*M,t[10]=(l+u)*s,t[11]=-1,t[12]=0,t[13]=0,t[14]=l*u*2*s,t[15]=0,t},o.perspective=function(t,a,n,r,o){var u=1/Math.tan(a/2),l=1/(r-o);return t[0]=u/n,t[1]=0,t[2]=0,t[3]=0,t[4]=0,t[5]=u,t[6]=0,t[7]=0,t[8]=0,t[9]=0,t[10]=(o+r)*l,t[11]=-1,t[12]=0,t[13]=0,t[14]=2*o*r*l,t[15]=0,t},o.perspectiveFromFieldOfView=function(t,a,n,r){var o=Math.tan(a.upDegrees*Math.PI/180),u=Math.tan(a.downDegrees*Math.PI/180),l=Math.tan(a.leftDegrees*Math.PI/180),e=Math.tan(a.rightDegrees*Math.PI/180),M=2/(l+e),s=2/(o+u);return t[0]=M,t[1]=0,t[2]=0,t[3]=0,t[4]=0,t[5]=s,t[6]=0,t[7]=0,t[8]=-((l-e)*M*.5),t[9]=(o-u)*s*.5,t[10]=r/(n-r),t[11]=-1,t[12]=0,t[13]=0,t[14]=r*n/(n-r),t[15]=0,t},o.ortho=function(t,a,n,r,o,u,l){var e=1/(a-n),M=1/(r-o),s=1/(u-l);return t[0]=-2*e,t[1]=0,t[2]=0,t[3]=0,t[4]=0,t[5]=-2*M,t[6]=0,t[7]=0,t[8]=0,t[9]=0,t[10]=2*s,t[11]=0,t[12]=(a+n)*e,t[13]=(o+r)*M,t[14]=(l+u)*s,t[15]=1,t},o.lookAt=function(t,a,n,u){var l,e,M,s,i,c,h,S,I,f,x=a[0],D=a[1],F=a[2],m=u[0],d=u[1],b=u[2],v=n[0],z=n[1],p=n[2];return Math.abs(x-v)M?(u.cross(t,a,o),u.length(t)<1e-6&&u.cross(t,n,o),u.normalize(t,t),e.setAxisAngle(r,t,Math.PI),r):M>.999999?(r[0]=0,r[1]=0,r[2]=0,r[3]=1,r):(u.cross(t,o,l),r[0]=t[0],r[1]=t[1],r[2]=t[2],r[3]=1+M,e.normalize(r,r))}}(),e.setAxes=function(){var t=o.create();return function(a,n,r,o){return t[0]=r[0],t[3]=r[1],t[6]=r[2],t[1]=o[0],t[4]=o[1],t[7]=o[2],t[2]=-n[0],t[5]=-n[1],t[8]=-n[2],e.normalize(a,e.fromMat3(a,t))}}(),e.clone=l.clone,e.fromValues=l.fromValues,e.copy=l.copy,e.set=l.set,e.identity=function(t){return t[0]=0,t[1]=0,t[2]=0,t[3]=1,t},e.setAxisAngle=function(t,a,n){n=.5*n;var r=Math.sin(n);return t[0]=r*a[0],t[1]=r*a[1],t[2]=r*a[2],t[3]=Math.cos(n),t},e.getAxisAngle=function(t,a){var n=2*Math.acos(a[3]),r=Math.sin(n/2);return 0!=r?(t[0]=a[0]/r,t[1]=a[1]/r,t[2]=a[2]/r):(t[0]=1,t[1]=0,t[2]=0),n},e.add=l.add,e.multiply=function(t,a,n){var r=a[0],o=a[1],u=a[2],l=a[3],e=n[0],M=n[1],s=n[2],i=n[3];return t[0]=r*i+l*e+o*s-u*M,t[1]=o*i+l*M+u*e-r*s,t[2]=u*i+l*s+r*M-o*e,t[3]=l*i-r*e-o*M-u*s,t},e.mul=e.multiply,e.scale=l.scale,e.rotateX=function(t,a,n){n*=.5;var r=a[0],o=a[1],u=a[2],l=a[3],e=Math.sin(n),M=Math.cos(n);return t[0]=r*M+l*e,t[1]=o*M+u*e,t[2]=u*M-o*e,t[3]=l*M-r*e,t},e.rotateY=function(t,a,n){n*=.5;var r=a[0],o=a[1],u=a[2],l=a[3],e=Math.sin(n),M=Math.cos(n);return t[0]=r*M-u*e,t[1]=o*M+l*e,t[2]=u*M+r*e,t[3]=l*M-o*e,t},e.rotateZ=function(t,a,n){n*=.5;var r=a[0],o=a[1],u=a[2],l=a[3],e=Math.sin(n),M=Math.cos(n);return t[0]=r*M+o*e,t[1]=o*M-r*e,t[2]=u*M+l*e,t[3]=l*M-u*e,t},e.calculateW=function(t,a){var n=a[0],r=a[1],o=a[2];return t[0]=n,t[1]=r,t[2]=o,t[3]=Math.sqrt(Math.abs(1-n*n-r*r-o*o)),t},e.dot=l.dot,e.lerp=l.lerp,e.slerp=function(t,a,n,r){var o,u,l,e,M,s=a[0],i=a[1],c=a[2],h=a[3],S=n[0],I=n[1],f=n[2],x=n[3];return u=s*S+i*I+c*f+h*x,0>u&&(u=-u,S=-S,I=-I,f=-f,x=-x),1-u>1e-6?(o=Math.acos(u),l=Math.sin(o),e=Math.sin((1-r)*o)/l,M=Math.sin(r*o)/l):(e=1-r,M=r),t[0]=e*s+M*S,t[1]=e*i+M*I,t[2]=e*c+M*f,t[3]=e*h+M*x,t},e.sqlerp=function(){var t=e.create(),a=e.create();return function(n,r,o,u,l,M){return e.slerp(t,r,l,M),e.slerp(a,o,u,M),e.slerp(n,t,a,2*M*(1-M)),n}}(),e.invert=function(t,a){var n=a[0],r=a[1],o=a[2],u=a[3],l=n*n+r*r+o*o+u*u,e=l?1/l:0;return t[0]=-n*e,t[1]=-r*e,t[2]=-o*e,t[3]=u*e,t},e.conjugate=function(t,a){return t[0]=-a[0],t[1]=-a[1],t[2]=-a[2],t[3]=a[3],t},e.length=l.length,e.len=e.length,e.squaredLength=l.squaredLength,e.sqrLen=e.squaredLength,e.normalize=l.normalize,e.fromMat3=function(t,a){var n,r=a[0]+a[4]+a[8];if(r>0)n=Math.sqrt(r+1),t[3]=.5*n,n=.5/n,t[0]=(a[5]-a[7])*n,t[1]=(a[6]-a[2])*n,t[2]=(a[1]-a[3])*n;else{var o=0;a[4]>a[0]&&(o=1),a[8]>a[3*o+o]&&(o=2);var u=(o+1)%3,l=(o+2)%3;n=Math.sqrt(a[3*o+o]-a[3*u+u]-a[3*l+l]+1),t[o]=.5*n,n=.5/n,t[3]=(a[3*u+l]-a[3*l+u])*n,t[u]=(a[3*u+o]+a[3*o+u])*n,t[l]=(a[3*l+o]+a[3*o+l])*n}return t},e.str=function(t){return"quat("+t[0]+", "+t[1]+", "+t[2]+", "+t[3]+")"},e.exactEquals=l.exactEquals,e.equals=l.equals,t.exports=e},function(t,a,n){var r=n(1),o={};o.create=function(){var t=new r.ARRAY_TYPE(3);return t[0]=0,t[1]=0,t[2]=0,t},o.clone=function(t){var a=new r.ARRAY_TYPE(3);return a[0]=t[0],a[1]=t[1],a[2]=t[2],a},o.fromValues=function(t,a,n){var o=new r.ARRAY_TYPE(3);return o[0]=t,o[1]=a,o[2]=n,o},o.copy=function(t,a){return t[0]=a[0],t[1]=a[1],t[2]=a[2],t},o.set=function(t,a,n,r){return t[0]=a,t[1]=n,t[2]=r,t},o.add=function(t,a,n){return t[0]=a[0]+n[0],t[1]=a[1]+n[1],t[2]=a[2]+n[2],t},o.subtract=function(t,a,n){return t[0]=a[0]-n[0],t[1]=a[1]-n[1],t[2]=a[2]-n[2],t},o.sub=o.subtract,o.multiply=function(t,a,n){return t[0]=a[0]*n[0],t[1]=a[1]*n[1],t[2]=a[2]*n[2],t},o.mul=o.multiply,o.divide=function(t,a,n){return t[0]=a[0]/n[0],t[1]=a[1]/n[1],t[2]=a[2]/n[2],t},o.div=o.divide,o.ceil=function(t,a){return t[0]=Math.ceil(a[0]),t[1]=Math.ceil(a[1]),t[2]=Math.ceil(a[2]),t},o.floor=function(t,a){return t[0]=Math.floor(a[0]),t[1]=Math.floor(a[1]),t[2]=Math.floor(a[2]),t},o.min=function(t,a,n){return t[0]=Math.min(a[0],n[0]),t[1]=Math.min(a[1],n[1]),t[2]=Math.min(a[2],n[2]),t},o.max=function(t,a,n){return t[0]=Math.max(a[0],n[0]),t[1]=Math.max(a[1],n[1]),t[2]=Math.max(a[2],n[2]),t},o.round=function(t,a){return t[0]=Math.round(a[0]),t[1]=Math.round(a[1]),t[2]=Math.round(a[2]),t},o.scale=function(t,a,n){return t[0]=a[0]*n,t[1]=a[1]*n,t[2]=a[2]*n,t},o.scaleAndAdd=function(t,a,n,r){return t[0]=a[0]+n[0]*r,t[1]=a[1]+n[1]*r,t[2]=a[2]+n[2]*r,t},o.distance=function(t,a){var n=a[0]-t[0],r=a[1]-t[1],o=a[2]-t[2];return Math.sqrt(n*n+r*r+o*o)},o.dist=o.distance,o.squaredDistance=function(t,a){var n=a[0]-t[0],r=a[1]-t[1],o=a[2]-t[2];return n*n+r*r+o*o},o.sqrDist=o.squaredDistance,o.length=function(t){var a=t[0],n=t[1],r=t[2];return Math.sqrt(a*a+n*n+r*r)},o.len=o.length,o.squaredLength=function(t){var a=t[0],n=t[1],r=t[2];return a*a+n*n+r*r},o.sqrLen=o.squaredLength,o.negate=function(t,a){return t[0]=-a[0],t[1]=-a[1],t[2]=-a[2],t},o.inverse=function(t,a){return t[0]=1/a[0],t[1]=1/a[1],t[2]=1/a[2],t},o.normalize=function(t,a){var n=a[0],r=a[1],o=a[2],u=n*n+r*r+o*o;return u>0&&(u=1/Math.sqrt(u),t[0]=a[0]*u,t[1]=a[1]*u,t[2]=a[2]*u),t},o.dot=function(t,a){return t[0]*a[0]+t[1]*a[1]+t[2]*a[2]},o.cross=function(t,a,n){var r=a[0],o=a[1],u=a[2],l=n[0],e=n[1],M=n[2];return t[0]=o*M-u*e,t[1]=u*l-r*M,t[2]=r*e-o*l,t},o.lerp=function(t,a,n,r){var o=a[0],u=a[1],l=a[2];return t[0]=o+r*(n[0]-o),t[1]=u+r*(n[1]-u),t[2]=l+r*(n[2]-l),t},o.hermite=function(t,a,n,r,o,u){var l=u*u,e=l*(2*u-3)+1,M=l*(u-2)+u,s=l*(u-1),i=l*(3-2*u);return t[0]=a[0]*e+n[0]*M+r[0]*s+o[0]*i,t[1]=a[1]*e+n[1]*M+r[1]*s+o[1]*i,t[2]=a[2]*e+n[2]*M+r[2]*s+o[2]*i,t},o.bezier=function(t,a,n,r,o,u){var l=1-u,e=l*l,M=u*u,s=e*l,i=3*u*e,c=3*M*l,h=M*u;return t[0]=a[0]*s+n[0]*i+r[0]*c+o[0]*h,t[1]=a[1]*s+n[1]*i+r[1]*c+o[1]*h,t[2]=a[2]*s+n[2]*i+r[2]*c+o[2]*h,t},o.random=function(t,a){a=a||1;var n=2*r.RANDOM()*Math.PI,o=2*r.RANDOM()-1,u=Math.sqrt(1-o*o)*a;return t[0]=Math.cos(n)*u,t[1]=Math.sin(n)*u,t[2]=o*a,t},o.transformMat4=function(t,a,n){var r=a[0],o=a[1],u=a[2],l=n[3]*r+n[7]*o+n[11]*u+n[15];return l=l||1,t[0]=(n[0]*r+n[4]*o+n[8]*u+n[12])/l,t[1]=(n[1]*r+n[5]*o+n[9]*u+n[13])/l,t[2]=(n[2]*r+n[6]*o+n[10]*u+n[14])/l,t},o.transformMat3=function(t,a,n){var r=a[0],o=a[1],u=a[2];return t[0]=r*n[0]+o*n[3]+u*n[6],t[1]=r*n[1]+o*n[4]+u*n[7],t[2]=r*n[2]+o*n[5]+u*n[8],t},o.transformQuat=function(t,a,n){var r=a[0],o=a[1],u=a[2],l=n[0],e=n[1],M=n[2],s=n[3],i=s*r+e*u-M*o,c=s*o+M*r-l*u,h=s*u+l*o-e*r,S=-l*r-e*o-M*u;return t[0]=i*s+S*-l+c*-M-h*-e,t[1]=c*s+S*-e+h*-l-i*-M,t[2]=h*s+S*-M+i*-e-c*-l,t},o.rotateX=function(t,a,n,r){var o=[],u=[];return o[0]=a[0]-n[0],o[1]=a[1]-n[1],o[2]=a[2]-n[2],u[0]=o[0],u[1]=o[1]*Math.cos(r)-o[2]*Math.sin(r),u[2]=o[1]*Math.sin(r)+o[2]*Math.cos(r),t[0]=u[0]+n[0],t[1]=u[1]+n[1],t[2]=u[2]+n[2],t},o.rotateY=function(t,a,n,r){var o=[],u=[];return o[0]=a[0]-n[0],o[1]=a[1]-n[1],o[2]=a[2]-n[2],u[0]=o[2]*Math.sin(r)+o[0]*Math.cos(r),u[1]=o[1],u[2]=o[2]*Math.cos(r)-o[0]*Math.sin(r),t[0]=u[0]+n[0],t[1]=u[1]+n[1],t[2]=u[2]+n[2],t},o.rotateZ=function(t,a,n,r){var o=[],u=[];return o[0]=a[0]-n[0],o[1]=a[1]-n[1],o[2]=a[2]-n[2],u[0]=o[0]*Math.cos(r)-o[1]*Math.sin(r),u[1]=o[0]*Math.sin(r)+o[1]*Math.cos(r),u[2]=o[2],t[0]=u[0]+n[0],t[1]=u[1]+n[1],t[2]=u[2]+n[2],t},o.forEach=function(){var t=o.create();return function(a,n,r,o,u,l){var e,M;for(n||(n=3),r||(r=0),M=o?Math.min(o*n+r,a.length):a.length,e=r;M>e;e+=n)t[0]=a[e],t[1]=a[e+1],t[2]=a[e+2],u(t,t,l),a[e]=t[0],a[e+1]=t[1],a[e+2]=t[2];return a}}(),o.angle=function(t,a){var n=o.fromValues(t[0],t[1],t[2]),r=o.fromValues(a[0],a[1],a[2]);o.normalize(n,n),o.normalize(r,r);var u=o.dot(n,r);return u>1?0:Math.acos(u)},o.str=function(t){return"vec3("+t[0]+", "+t[1]+", "+t[2]+")"},o.exactEquals=function(t,a){return t[0]===a[0]&&t[1]===a[1]&&t[2]===a[2]},o.equals=function(t,a){var n=t[0],o=t[1],u=t[2],l=a[0],e=a[1],M=a[2];return Math.abs(n-l)<=r.EPSILON*Math.max(1,Math.abs(n),Math.abs(l))&&Math.abs(o-e)<=r.EPSILON*Math.max(1,Math.abs(o),Math.abs(e))&&Math.abs(u-M)<=r.EPSILON*Math.max(1,Math.abs(u),Math.abs(M))},t.exports=o},function(t,a,n){var r=n(1),o={};o.create=function(){var t=new r.ARRAY_TYPE(4);return t[0]=0,t[1]=0,t[2]=0,t[3]=0,t},o.clone=function(t){var a=new r.ARRAY_TYPE(4);return a[0]=t[0],a[1]=t[1],a[2]=t[2],a[3]=t[3],a},o.fromValues=function(t,a,n,o){var u=new r.ARRAY_TYPE(4);return u[0]=t,u[1]=a,u[2]=n,u[3]=o,u},o.copy=function(t,a){return t[0]=a[0],t[1]=a[1],t[2]=a[2],t[3]=a[3],t},o.set=function(t,a,n,r,o){return t[0]=a,t[1]=n,t[2]=r,t[3]=o,t},o.add=function(t,a,n){return t[0]=a[0]+n[0],t[1]=a[1]+n[1],t[2]=a[2]+n[2],t[3]=a[3]+n[3],t},o.subtract=function(t,a,n){return t[0]=a[0]-n[0],t[1]=a[1]-n[1],t[2]=a[2]-n[2],t[3]=a[3]-n[3],t},o.sub=o.subtract,o.multiply=function(t,a,n){return t[0]=a[0]*n[0],t[1]=a[1]*n[1],t[2]=a[2]*n[2],t[3]=a[3]*n[3],t},o.mul=o.multiply,o.divide=function(t,a,n){return t[0]=a[0]/n[0],t[1]=a[1]/n[1],t[2]=a[2]/n[2],t[3]=a[3]/n[3],t},o.div=o.divide,o.ceil=function(t,a){return t[0]=Math.ceil(a[0]),t[1]=Math.ceil(a[1]),t[2]=Math.ceil(a[2]),t[3]=Math.ceil(a[3]),t},o.floor=function(t,a){return t[0]=Math.floor(a[0]),t[1]=Math.floor(a[1]),t[2]=Math.floor(a[2]),t[3]=Math.floor(a[3]),t},o.min=function(t,a,n){return t[0]=Math.min(a[0],n[0]),t[1]=Math.min(a[1],n[1]),t[2]=Math.min(a[2],n[2]),t[3]=Math.min(a[3],n[3]),t},o.max=function(t,a,n){return t[0]=Math.max(a[0],n[0]),t[1]=Math.max(a[1],n[1]),t[2]=Math.max(a[2],n[2]),t[3]=Math.max(a[3],n[3]),t},o.round=function(t,a){return t[0]=Math.round(a[0]),t[1]=Math.round(a[1]),t[2]=Math.round(a[2]),t[3]=Math.round(a[3]),t},o.scale=function(t,a,n){return t[0]=a[0]*n,t[1]=a[1]*n,t[2]=a[2]*n,t[3]=a[3]*n,t},o.scaleAndAdd=function(t,a,n,r){return t[0]=a[0]+n[0]*r,t[1]=a[1]+n[1]*r,t[2]=a[2]+n[2]*r,t[3]=a[3]+n[3]*r,t},o.distance=function(t,a){var n=a[0]-t[0],r=a[1]-t[1],o=a[2]-t[2],u=a[3]-t[3];return Math.sqrt(n*n+r*r+o*o+u*u)},o.dist=o.distance,o.squaredDistance=function(t,a){var n=a[0]-t[0],r=a[1]-t[1],o=a[2]-t[2],u=a[3]-t[3];return n*n+r*r+o*o+u*u},o.sqrDist=o.squaredDistance,o.length=function(t){var a=t[0],n=t[1],r=t[2],o=t[3];return Math.sqrt(a*a+n*n+r*r+o*o)},o.len=o.length,o.squaredLength=function(t){var a=t[0],n=t[1],r=t[2],o=t[3];return a*a+n*n+r*r+o*o},o.sqrLen=o.squaredLength,o.negate=function(t,a){return t[0]=-a[0],t[1]=-a[1],t[2]=-a[2],t[3]=-a[3],t},o.inverse=function(t,a){return t[0]=1/a[0],t[1]=1/a[1],t[2]=1/a[2],t[3]=1/a[3],t},o.normalize=function(t,a){var n=a[0],r=a[1],o=a[2],u=a[3],l=n*n+r*r+o*o+u*u;return l>0&&(l=1/Math.sqrt(l),t[0]=n*l,t[1]=r*l,t[2]=o*l,t[3]=u*l),t},o.dot=function(t,a){return t[0]*a[0]+t[1]*a[1]+t[2]*a[2]+t[3]*a[3]},o.lerp=function(t,a,n,r){var o=a[0],u=a[1],l=a[2],e=a[3];return t[0]=o+r*(n[0]-o),t[1]=u+r*(n[1]-u),t[2]=l+r*(n[2]-l),t[3]=e+r*(n[3]-e),t},o.random=function(t,a){return a=a||1,t[0]=r.RANDOM(),t[1]=r.RANDOM(),t[2]=r.RANDOM(),t[3]=r.RANDOM(),o.normalize(t,t),o.scale(t,t,a),t},o.transformMat4=function(t,a,n){var r=a[0],o=a[1],u=a[2],l=a[3];return t[0]=n[0]*r+n[4]*o+n[8]*u+n[12]*l,t[1]=n[1]*r+n[5]*o+n[9]*u+n[13]*l,t[2]=n[2]*r+n[6]*o+n[10]*u+n[14]*l,t[3]=n[3]*r+n[7]*o+n[11]*u+n[15]*l,t},o.transformQuat=function(t,a,n){var r=a[0],o=a[1],u=a[2],l=n[0],e=n[1],M=n[2],s=n[3],i=s*r+e*u-M*o,c=s*o+M*r-l*u,h=s*u+l*o-e*r,S=-l*r-e*o-M*u;return t[0]=i*s+S*-l+c*-M-h*-e,t[1]=c*s+S*-e+h*-l-i*-M,t[2]=h*s+S*-M+i*-e-c*-l,t[3]=a[3],t},o.forEach=function(){var t=o.create();return function(a,n,r,o,u,l){var e,M;for(n||(n=4),r||(r=0),M=o?Math.min(o*n+r,a.length):a.length,e=r;M>e;e+=n)t[0]=a[e],t[1]=a[e+1],t[2]=a[e+2],t[3]=a[e+3],u(t,t,l),a[e]=t[0],a[e+1]=t[1],a[e+2]=t[2],a[e+3]=t[3];return a}}(),o.str=function(t){return"vec4("+t[0]+", "+t[1]+", "+t[2]+", "+t[3]+")"},o.exactEquals=function(t,a){return t[0]===a[0]&&t[1]===a[1]&&t[2]===a[2]&&t[3]===a[3]},o.equals=function(t,a){var n=t[0],o=t[1],u=t[2],l=t[3],e=a[0],M=a[1],s=a[2],i=a[3];return Math.abs(n-e)<=r.EPSILON*Math.max(1,Math.abs(n),Math.abs(e))&&Math.abs(o-M)<=r.EPSILON*Math.max(1,Math.abs(o),Math.abs(M))&&Math.abs(u-s)<=r.EPSILON*Math.max(1,Math.abs(u),Math.abs(s))&&Math.abs(l-i)<=r.EPSILON*Math.max(1,Math.abs(l),Math.abs(i))},t.exports=o},function(t,a,n){var r=n(1),o={};o.create=function(){var t=new r.ARRAY_TYPE(2);return t[0]=0,t[1]=0,t},o.clone=function(t){var a=new r.ARRAY_TYPE(2);return a[0]=t[0],a[1]=t[1],a},o.fromValues=function(t,a){var n=new r.ARRAY_TYPE(2);return n[0]=t,n[1]=a,n},o.copy=function(t,a){return t[0]=a[0],t[1]=a[1],t},o.set=function(t,a,n){return t[0]=a,t[1]=n,t},o.add=function(t,a,n){return t[0]=a[0]+n[0],t[1]=a[1]+n[1],t},o.subtract=function(t,a,n){return t[0]=a[0]-n[0],t[1]=a[1]-n[1],t},o.sub=o.subtract,o.multiply=function(t,a,n){return t[0]=a[0]*n[0],t[1]=a[1]*n[1],t},o.mul=o.multiply,o.divide=function(t,a,n){return t[0]=a[0]/n[0],t[1]=a[1]/n[1],t},o.div=o.divide,o.ceil=function(t,a){return t[0]=Math.ceil(a[0]),t[1]=Math.ceil(a[1]),t},o.floor=function(t,a){return t[0]=Math.floor(a[0]),t[1]=Math.floor(a[1]),t},o.min=function(t,a,n){return t[0]=Math.min(a[0],n[0]),t[1]=Math.min(a[1],n[1]),t},o.max=function(t,a,n){return t[0]=Math.max(a[0],n[0]),t[1]=Math.max(a[1],n[1]),t},o.round=function(t,a){return t[0]=Math.round(a[0]),t[1]=Math.round(a[1]),t},o.scale=function(t,a,n){return t[0]=a[0]*n,t[1]=a[1]*n,t},o.scaleAndAdd=function(t,a,n,r){return t[0]=a[0]+n[0]*r,t[1]=a[1]+n[1]*r,t},o.distance=function(t,a){var n=a[0]-t[0],r=a[1]-t[1];return Math.sqrt(n*n+r*r)},o.dist=o.distance,o.squaredDistance=function(t,a){var n=a[0]-t[0],r=a[1]-t[1];return n*n+r*r},o.sqrDist=o.squaredDistance,o.length=function(t){var a=t[0],n=t[1];return Math.sqrt(a*a+n*n)},o.len=o.length,o.squaredLength=function(t){var a=t[0],n=t[1];return a*a+n*n},o.sqrLen=o.squaredLength,o.negate=function(t,a){return t[0]=-a[0],t[1]=-a[1],t},o.inverse=function(t,a){return t[0]=1/a[0],t[1]=1/a[1],t},o.normalize=function(t,a){var n=a[0],r=a[1],o=n*n+r*r;return o>0&&(o=1/Math.sqrt(o),t[0]=a[0]*o,t[1]=a[1]*o),t},o.dot=function(t,a){return t[0]*a[0]+t[1]*a[1]},o.cross=function(t,a,n){var r=a[0]*n[1]-a[1]*n[0];return t[0]=t[1]=0,t[2]=r,t},o.lerp=function(t,a,n,r){var o=a[0],u=a[1];return t[0]=o+r*(n[0]-o),t[1]=u+r*(n[1]-u),t},o.random=function(t,a){a=a||1;var n=2*r.RANDOM()*Math.PI;return t[0]=Math.cos(n)*a,t[1]=Math.sin(n)*a,t},o.transformMat2=function(t,a,n){var r=a[0],o=a[1];return t[0]=n[0]*r+n[2]*o,t[1]=n[1]*r+n[3]*o,t},o.transformMat2d=function(t,a,n){var r=a[0],o=a[1];return t[0]=n[0]*r+n[2]*o+n[4],t[1]=n[1]*r+n[3]*o+n[5],t},o.transformMat3=function(t,a,n){var r=a[0],o=a[1];return t[0]=n[0]*r+n[3]*o+n[6],t[1]=n[1]*r+n[4]*o+n[7],t},o.transformMat4=function(t,a,n){var r=a[0],o=a[1];return t[0]=n[0]*r+n[4]*o+n[12],t[1]=n[1]*r+n[5]*o+n[13],t},o.forEach=function(){var t=o.create();return function(a,n,r,o,u,l){var e,M;for(n||(n=2),r||(r=0),M=o?Math.min(o*n+r,a.length):a.length,e=r;M>e;e+=n)t[0]=a[e],t[1]=a[e+1],u(t,t,l),a[e]=t[0],a[e+1]=t[1];return a}}(),o.str=function(t){return"vec2("+t[0]+", "+t[1]+")"},o.exactEquals=function(t,a){return t[0]===a[0]&&t[1]===a[1]},o.equals=function(t,a){var n=t[0],o=t[1],u=a[0],l=a[1];return Math.abs(n-u)<=r.EPSILON*Math.max(1,Math.abs(n),Math.abs(u))&&Math.abs(o-l)<=r.EPSILON*Math.max(1,Math.abs(o),Math.abs(l))},t.exports=o}])}); \ No newline at end of file diff --git a/servo/tests/html/webvr/js/third-party/webvr-polyfill.js b/servo/tests/html/webvr/js/third-party/webvr-polyfill.js deleted file mode 100644 index 2e4b2ee29ac0..000000000000 --- a/servo/tests/html/webvr/js/third-party/webvr-polyfill.js +++ /dev/null @@ -1,5939 +0,0 @@ -(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o self.capabilities.maxLayers) { - reject(new Error('Invalid number of layers.')); - return; - } - - var incomingLayer = layers[0]; - if (!incomingLayer.source) { - /* - todo: figure out the correct behavior if the source is not provided. - see https://github.com/w3c/webvr/issues/58 - */ - resolve(); - return; - } - - var leftBounds = incomingLayer.leftBounds || defaultLeftBounds; - var rightBounds = incomingLayer.rightBounds || defaultRightBounds; - if (wasPresenting) { - // Already presenting, just changing configuration - var changed = false; - var layer = self.layer_; - if (layer.source !== incomingLayer.source) { - layer.source = incomingLayer.source; - changed = true; - } - - for (var i = 0; i < 4; i++) { - if (layer.leftBounds[i] !== leftBounds[i]) { - layer.leftBounds[i] = leftBounds[i]; - changed = true; - } - if (layer.rightBounds[i] !== rightBounds[i]) { - layer.rightBounds[i] = rightBounds[i]; - changed = true; - } - } - - if (changed) { - self.fireVRDisplayPresentChange_(); - } - resolve(); - return; - } - - // Was not already presenting. - self.layer_ = { - predistorted: incomingLayer.predistorted, - source: incomingLayer.source, - leftBounds: leftBounds.slice(0), - rightBounds: rightBounds.slice(0) - }; - - self.waitingForPresent_ = false; - if (self.layer_ && self.layer_.source) { - var fullscreenElement = self.wrapForFullscreen(self.layer_.source); - - function onFullscreenChange() { - var actualFullscreenElement = Util.getFullscreenElement(); - - self.isPresenting = (fullscreenElement === actualFullscreenElement); - if (self.isPresenting) { - if (screen.orientation && screen.orientation.lock) { - screen.orientation.lock('landscape-primary').catch(function(error){ - console.error('screen.orientation.lock() failed due to', error.message) - }); - } - self.waitingForPresent_ = false; - self.beginPresent_(); - resolve(); - } else { - if (screen.orientation && screen.orientation.unlock) { - screen.orientation.unlock(); - } - self.removeFullscreenWrapper(); - self.wakelock_.release(); - self.endPresent_(); - self.removeFullscreenListeners_(); - } - self.fireVRDisplayPresentChange_(); - } - function onFullscreenError() { - if (!self.waitingForPresent_) { - return; - } - - self.removeFullscreenWrapper(); - self.removeFullscreenListeners_(); - - self.wakelock_.release(); - self.waitingForPresent_ = false; - self.isPresenting = false; - - reject(new Error('Unable to present.')); - } - - self.addFullscreenListeners_(fullscreenElement, - onFullscreenChange, onFullscreenError); - - if (Util.requestFullscreen(fullscreenElement)) { - self.wakelock_.request(); - self.waitingForPresent_ = true; - } else if (Util.isIOS()) { - // *sigh* Just fake it. - self.wakelock_.request(); - self.isPresenting = true; - self.beginPresent_(); - self.fireVRDisplayPresentChange_(); - resolve(); - } - } - - if (!self.waitingForPresent_ && !Util.isIOS()) { - Util.exitFullscreen(); - reject(new Error('Unable to present.')); - } - }); -}; - -VRDisplay.prototype.exitPresent = function() { - var wasPresenting = this.isPresenting; - var self = this; - this.isPresenting = false; - this.layer_ = null; - this.wakelock_.release(); - - return new Promise(function(resolve, reject) { - if (wasPresenting) { - if (!Util.exitFullscreen() && Util.isIOS()) { - self.endPresent_(); - self.fireVRDisplayPresentChange_(); - } - - resolve(); - } else { - reject(new Error('Was not presenting to VRDisplay.')); - } - }); -}; - -VRDisplay.prototype.getLayers = function() { - if (this.layer_) { - return [this.layer_]; - } - return []; -}; - -VRDisplay.prototype.fireVRDisplayPresentChange_ = function() { - var event = new CustomEvent('vrdisplaypresentchange', {detail: {vrdisplay: this}}); - window.dispatchEvent(event); -}; - -VRDisplay.prototype.addFullscreenListeners_ = function(element, changeHandler, errorHandler) { - this.removeFullscreenListeners_(); - - this.fullscreenEventTarget_ = element; - this.fullscreenChangeHandler_ = changeHandler; - this.fullscreenErrorHandler_ = errorHandler; - - if (changeHandler) { - element.addEventListener('fullscreenchange', changeHandler, false); - element.addEventListener('webkitfullscreenchange', changeHandler, false); - document.addEventListener('mozfullscreenchange', changeHandler, false); - element.addEventListener('msfullscreenchange', changeHandler, false); - } - - if (errorHandler) { - element.addEventListener('fullscreenerror', errorHandler, false); - element.addEventListener('webkitfullscreenerror', errorHandler, false); - document.addEventListener('mozfullscreenerror', errorHandler, false); - element.addEventListener('msfullscreenerror', errorHandler, false); - } -}; - -VRDisplay.prototype.removeFullscreenListeners_ = function() { - if (!this.fullscreenEventTarget_) - return; - - var element = this.fullscreenEventTarget_; - - if (this.fullscreenChangeHandler_) { - var changeHandler = this.fullscreenChangeHandler_; - element.removeEventListener('fullscreenchange', changeHandler, false); - element.removeEventListener('webkitfullscreenchange', changeHandler, false); - document.removeEventListener('mozfullscreenchange', changeHandler, false); - element.removeEventListener('msfullscreenchange', changeHandler, false); - } - - if (this.fullscreenErrorHandler_) { - var errorHandler = this.fullscreenErrorHandler_; - element.removeEventListener('fullscreenerror', errorHandler, false); - element.removeEventListener('webkitfullscreenerror', errorHandler, false); - document.removeEventListener('mozfullscreenerror', errorHandler, false); - element.removeEventListener('msfullscreenerror', errorHandler, false); - } - - this.fullscreenEventTarget_ = null; - this.fullscreenChangeHandler_ = null; - this.fullscreenErrorHandler_ = null; -}; - -VRDisplay.prototype.beginPresent_ = function() { - // Override to add custom behavior when presentation begins. -}; - -VRDisplay.prototype.endPresent_ = function() { - // Override to add custom behavior when presentation ends. -}; - -VRDisplay.prototype.submitFrame = function(pose) { - // Override to add custom behavior for frame submission. -}; - -VRDisplay.prototype.getEyeParameters = function(whichEye) { - // Override to return accurate eye parameters if canPresent is true. - return null; -}; - -/* - * Deprecated classes - */ - -/** - * The base class for all VR devices. (Deprecated) - */ -function VRDevice() { - this.isPolyfilled = true; - this.hardwareUnitId = 'webvr-polyfill hardwareUnitId'; - this.deviceId = 'webvr-polyfill deviceId'; - this.deviceName = 'webvr-polyfill deviceName'; -} - -/** - * The base class for all VR HMD devices. (Deprecated) - */ -function HMDVRDevice() { -} -HMDVRDevice.prototype = new VRDevice(); - -/** - * The base class for all VR position sensor devices. (Deprecated) - */ -function PositionSensorVRDevice() { -} -PositionSensorVRDevice.prototype = new VRDevice(); - -module.exports.VRFrameData = VRFrameData; -module.exports.VRDisplay = VRDisplay; -module.exports.VRDevice = VRDevice; -module.exports.HMDVRDevice = HMDVRDevice; -module.exports.PositionSensorVRDevice = PositionSensorVRDevice; - -},{"./util.js":22,"./wakelock.js":24}],3:[function(_dereq_,module,exports){ -/* - * Copyright 2016 Google Inc. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -var CardboardUI = _dereq_('./cardboard-ui.js'); -var Util = _dereq_('./util.js'); -var WGLUPreserveGLState = _dereq_('./deps/wglu-preserve-state.js'); - -var distortionVS = [ - 'attribute vec2 position;', - 'attribute vec3 texCoord;', - - 'varying vec2 vTexCoord;', - - 'uniform vec4 viewportOffsetScale[2];', - - 'void main() {', - ' vec4 viewport = viewportOffsetScale[int(texCoord.z)];', - ' vTexCoord = (texCoord.xy * viewport.zw) + viewport.xy;', - ' gl_Position = vec4( position, 1.0, 1.0 );', - '}', -].join('\n'); - -var distortionFS = [ - 'precision mediump float;', - 'uniform sampler2D diffuse;', - - 'varying vec2 vTexCoord;', - - 'void main() {', - ' gl_FragColor = texture2D(diffuse, vTexCoord);', - '}', -].join('\n'); - -/** - * A mesh-based distorter. - */ -function CardboardDistorter(gl) { - this.gl = gl; - this.ctxAttribs = gl.getContextAttributes(); - - this.meshWidth = 20; - this.meshHeight = 20; - - this.bufferScale = WebVRConfig.BUFFER_SCALE; - - this.bufferWidth = gl.drawingBufferWidth; - this.bufferHeight = gl.drawingBufferHeight; - - // Patching support - this.realBindFramebuffer = gl.bindFramebuffer; - this.realEnable = gl.enable; - this.realDisable = gl.disable; - this.realColorMask = gl.colorMask; - this.realClearColor = gl.clearColor; - this.realViewport = gl.viewport; - - if (!Util.isIOS()) { - this.realCanvasWidth = Object.getOwnPropertyDescriptor(gl.canvas.__proto__, 'width'); - this.realCanvasHeight = Object.getOwnPropertyDescriptor(gl.canvas.__proto__, 'height'); - } - - this.isPatched = false; - - // State tracking - this.lastBoundFramebuffer = null; - this.cullFace = false; - this.depthTest = false; - this.blend = false; - this.scissorTest = false; - this.stencilTest = false; - this.viewport = [0, 0, 0, 0]; - this.colorMask = [true, true, true, true]; - this.clearColor = [0, 0, 0, 0]; - - this.attribs = { - position: 0, - texCoord: 1 - }; - this.program = Util.linkProgram(gl, distortionVS, distortionFS, this.attribs); - this.uniforms = Util.getProgramUniforms(gl, this.program); - - this.viewportOffsetScale = new Float32Array(8); - this.setTextureBounds(); - - this.vertexBuffer = gl.createBuffer(); - this.indexBuffer = gl.createBuffer(); - this.indexCount = 0; - - this.renderTarget = gl.createTexture(); - this.framebuffer = gl.createFramebuffer(); - - this.depthStencilBuffer = null; - this.depthBuffer = null; - this.stencilBuffer = null; - - if (this.ctxAttribs.depth && this.ctxAttribs.stencil) { - this.depthStencilBuffer = gl.createRenderbuffer(); - } else if (this.ctxAttribs.depth) { - this.depthBuffer = gl.createRenderbuffer(); - } else if (this.ctxAttribs.stencil) { - this.stencilBuffer = gl.createRenderbuffer(); - } - - this.patch(); - - this.onResize(); - - if (!WebVRConfig.CARDBOARD_UI_DISABLED) { - this.cardboardUI = new CardboardUI(gl); - } -}; - -/** - * Tears down all the resources created by the distorter and removes any - * patches. - */ -CardboardDistorter.prototype.destroy = function() { - var gl = this.gl; - - this.unpatch(); - - gl.deleteProgram(this.program); - gl.deleteBuffer(this.vertexBuffer); - gl.deleteBuffer(this.indexBuffer); - gl.deleteTexture(this.renderTarget); - gl.deleteFramebuffer(this.framebuffer); - if (this.depthStencilBuffer) { - gl.deleteRenderbuffer(this.depthStencilBuffer); - } - if (this.depthBuffer) { - gl.deleteRenderbuffer(this.depthBuffer); - } - if (this.stencilBuffer) { - gl.deleteRenderbuffer(this.stencilBuffer); - } - - if (this.cardboardUI) { - this.cardboardUI.destroy(); - } -}; - - -/** - * Resizes the backbuffer to match the canvas width and height. - */ -CardboardDistorter.prototype.onResize = function() { - var gl = this.gl; - var self = this; - - var glState = [ - gl.RENDERBUFFER_BINDING, - gl.TEXTURE_BINDING_2D, gl.TEXTURE0 - ]; - - WGLUPreserveGLState(gl, glState, function(gl) { - // Bind real backbuffer and clear it once. We don't need to clear it again - // after that because we're overwriting the same area every frame. - self.realBindFramebuffer.call(gl, gl.FRAMEBUFFER, null); - - // Put things in a good state - if (self.scissorTest) { self.realDisable.call(gl, gl.SCISSOR_TEST); } - self.realColorMask.call(gl, true, true, true, true); - self.realViewport.call(gl, 0, 0, gl.drawingBufferWidth, gl.drawingBufferHeight); - self.realClearColor.call(gl, 0, 0, 0, 1); - - gl.clear(gl.COLOR_BUFFER_BIT); - - // Now bind and resize the fake backbuffer - self.realBindFramebuffer.call(gl, gl.FRAMEBUFFER, self.framebuffer); - - gl.bindTexture(gl.TEXTURE_2D, self.renderTarget); - gl.texImage2D(gl.TEXTURE_2D, 0, self.ctxAttribs.alpha ? gl.RGBA : gl.RGB, - self.bufferWidth, self.bufferHeight, 0, - self.ctxAttribs.alpha ? gl.RGBA : gl.RGB, gl.UNSIGNED_BYTE, null); - gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR); - gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR); - gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE); - gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE); - gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, self.renderTarget, 0); - - if (self.ctxAttribs.depth && self.ctxAttribs.stencil) { - gl.bindRenderbuffer(gl.RENDERBUFFER, self.depthStencilBuffer); - gl.renderbufferStorage(gl.RENDERBUFFER, gl.DEPTH_STENCIL, - self.bufferWidth, self.bufferHeight); - gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.DEPTH_STENCIL_ATTACHMENT, - gl.RENDERBUFFER, self.depthStencilBuffer); - } else if (self.ctxAttribs.depth) { - gl.bindRenderbuffer(gl.RENDERBUFFER, self.depthBuffer); - gl.renderbufferStorage(gl.RENDERBUFFER, gl.DEPTH_COMPONENT16, - self.bufferWidth, self.bufferHeight); - gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.DEPTH_ATTACHMENT, - gl.RENDERBUFFER, self.depthBuffer); - } else if (self.ctxAttribs.stencil) { - gl.bindRenderbuffer(gl.RENDERBUFFER, self.stencilBuffer); - gl.renderbufferStorage(gl.RENDERBUFFER, gl.STENCIL_INDEX8, - self.bufferWidth, self.bufferHeight); - gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.STENCIL_ATTACHMENT, - gl.RENDERBUFFER, self.stencilBuffer); - } - - if (!gl.checkFramebufferStatus(gl.FRAMEBUFFER) === gl.FRAMEBUFFER_COMPLETE) { - console.error('Framebuffer incomplete!'); - } - - self.realBindFramebuffer.call(gl, gl.FRAMEBUFFER, self.lastBoundFramebuffer); - - if (self.scissorTest) { self.realEnable.call(gl, gl.SCISSOR_TEST); } - - self.realColorMask.apply(gl, self.colorMask); - self.realViewport.apply(gl, self.viewport); - self.realClearColor.apply(gl, self.clearColor); - }); - - if (this.cardboardUI) { - this.cardboardUI.onResize(); - } -}; - -CardboardDistorter.prototype.patch = function() { - if (this.isPatched) { - return; - } - - var self = this; - var canvas = this.gl.canvas; - var gl = this.gl; - - if (!Util.isIOS()) { - canvas.width = Util.getScreenWidth() * this.bufferScale; - canvas.height = Util.getScreenHeight() * this.bufferScale; - - Object.defineProperty(canvas, 'width', { - configurable: true, - enumerable: true, - get: function() { - return self.bufferWidth; - }, - set: function(value) { - self.bufferWidth = value; - self.onResize(); - } - }); - - Object.defineProperty(canvas, 'height', { - configurable: true, - enumerable: true, - get: function() { - return self.bufferHeight; - }, - set: function(value) { - self.bufferHeight = value; - self.onResize(); - } - }); - } - - this.lastBoundFramebuffer = gl.getParameter(gl.FRAMEBUFFER_BINDING); - - if (this.lastBoundFramebuffer == null) { - this.lastBoundFramebuffer = this.framebuffer; - this.gl.bindFramebuffer(gl.FRAMEBUFFER, this.framebuffer); - } - - this.gl.bindFramebuffer = function(target, framebuffer) { - self.lastBoundFramebuffer = framebuffer ? framebuffer : self.framebuffer; - // Silently make calls to bind the default framebuffer bind ours instead. - self.realBindFramebuffer.call(gl, target, self.lastBoundFramebuffer); - }; - - this.cullFace = gl.getParameter(gl.CULL_FACE); - this.depthTest = gl.getParameter(gl.DEPTH_TEST); - this.blend = gl.getParameter(gl.BLEND); - this.scissorTest = gl.getParameter(gl.SCISSOR_TEST); - this.stencilTest = gl.getParameter(gl.STENCIL_TEST); - - gl.enable = function(pname) { - switch (pname) { - case gl.CULL_FACE: self.cullFace = true; break; - case gl.DEPTH_TEST: self.depthTest = true; break; - case gl.BLEND: self.blend = true; break; - case gl.SCISSOR_TEST: self.scissorTest = true; break; - case gl.STENCIL_TEST: self.stencilTest = true; break; - } - self.realEnable.call(gl, pname); - }; - - gl.disable = function(pname) { - switch (pname) { - case gl.CULL_FACE: self.cullFace = false; break; - case gl.DEPTH_TEST: self.depthTest = false; break; - case gl.BLEND: self.blend = false; break; - case gl.SCISSOR_TEST: self.scissorTest = false; break; - case gl.STENCIL_TEST: self.stencilTest = false; break; - } - self.realDisable.call(gl, pname); - }; - - this.colorMask = gl.getParameter(gl.COLOR_WRITEMASK); - gl.colorMask = function(r, g, b, a) { - self.colorMask[0] = r; - self.colorMask[1] = g; - self.colorMask[2] = b; - self.colorMask[3] = a; - self.realColorMask.call(gl, r, g, b, a); - }; - - this.clearColor = gl.getParameter(gl.COLOR_CLEAR_VALUE); - gl.clearColor = function(r, g, b, a) { - self.clearColor[0] = r; - self.clearColor[1] = g; - self.clearColor[2] = b; - self.clearColor[3] = a; - self.realClearColor.call(gl, r, g, b, a); - }; - - this.viewport = gl.getParameter(gl.VIEWPORT); - gl.viewport = function(x, y, w, h) { - self.viewport[0] = x; - self.viewport[1] = y; - self.viewport[2] = w; - self.viewport[3] = h; - self.realViewport.call(gl, x, y, w, h); - }; - - this.isPatched = true; - Util.safariCssSizeWorkaround(canvas); -}; - -CardboardDistorter.prototype.unpatch = function() { - if (!this.isPatched) { - return; - } - - var gl = this.gl; - var canvas = this.gl.canvas; - - if (!Util.isIOS()) { - Object.defineProperty(canvas, 'width', this.realCanvasWidth); - Object.defineProperty(canvas, 'height', this.realCanvasHeight); - } - canvas.width = this.bufferWidth; - canvas.height = this.bufferHeight; - - gl.bindFramebuffer = this.realBindFramebuffer; - gl.enable = this.realEnable; - gl.disable = this.realDisable; - gl.colorMask = this.realColorMask; - gl.clearColor = this.realClearColor; - gl.viewport = this.realViewport; - - // Check to see if our fake backbuffer is bound and bind the real backbuffer - // if that's the case. - if (this.lastBoundFramebuffer == this.framebuffer) { - gl.bindFramebuffer(gl.FRAMEBUFFER, null); - } - - this.isPatched = false; - - setTimeout(function() { - Util.safariCssSizeWorkaround(canvas); - }, 1); -}; - -CardboardDistorter.prototype.setTextureBounds = function(leftBounds, rightBounds) { - if (!leftBounds) { - leftBounds = [0, 0, 0.5, 1]; - } - - if (!rightBounds) { - rightBounds = [0.5, 0, 0.5, 1]; - } - - // Left eye - this.viewportOffsetScale[0] = leftBounds[0]; // X - this.viewportOffsetScale[1] = leftBounds[1]; // Y - this.viewportOffsetScale[2] = leftBounds[2]; // Width - this.viewportOffsetScale[3] = leftBounds[3]; // Height - - // Right eye - this.viewportOffsetScale[4] = rightBounds[0]; // X - this.viewportOffsetScale[5] = rightBounds[1]; // Y - this.viewportOffsetScale[6] = rightBounds[2]; // Width - this.viewportOffsetScale[7] = rightBounds[3]; // Height -}; - -/** - * Performs distortion pass on the injected backbuffer, rendering it to the real - * backbuffer. - */ -CardboardDistorter.prototype.submitFrame = function() { - var gl = this.gl; - var self = this; - - var glState = []; - - if (!WebVRConfig.DIRTY_SUBMIT_FRAME_BINDINGS) { - glState.push( - gl.CURRENT_PROGRAM, - gl.ARRAY_BUFFER_BINDING, - gl.ELEMENT_ARRAY_BUFFER_BINDING, - gl.TEXTURE_BINDING_2D, gl.TEXTURE0 - ); - } - - WGLUPreserveGLState(gl, glState, function(gl) { - // Bind the real default framebuffer - self.realBindFramebuffer.call(gl, gl.FRAMEBUFFER, null); - - // Make sure the GL state is in a good place - if (self.cullFace) { self.realDisable.call(gl, gl.CULL_FACE); } - if (self.depthTest) { self.realDisable.call(gl, gl.DEPTH_TEST); } - if (self.blend) { self.realDisable.call(gl, gl.BLEND); } - if (self.scissorTest) { self.realDisable.call(gl, gl.SCISSOR_TEST); } - if (self.stencilTest) { self.realDisable.call(gl, gl.STENCIL_TEST); } - self.realColorMask.call(gl, true, true, true, true); - self.realViewport.call(gl, 0, 0, gl.drawingBufferWidth, gl.drawingBufferHeight); - - // If the backbuffer has an alpha channel clear every frame so the page - // doesn't show through. - if (self.ctxAttribs.alpha || Util.isIOS()) { - self.realClearColor.call(gl, 0, 0, 0, 1); - gl.clear(gl.COLOR_BUFFER_BIT); - } - - // Bind distortion program and mesh - gl.useProgram(self.program); - - gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, self.indexBuffer); - - gl.bindBuffer(gl.ARRAY_BUFFER, self.vertexBuffer); - gl.enableVertexAttribArray(self.attribs.position); - gl.enableVertexAttribArray(self.attribs.texCoord); - gl.vertexAttribPointer(self.attribs.position, 2, gl.FLOAT, false, 20, 0); - gl.vertexAttribPointer(self.attribs.texCoord, 3, gl.FLOAT, false, 20, 8); - - gl.activeTexture(gl.TEXTURE0); - gl.uniform1i(self.uniforms.diffuse, 0); - gl.bindTexture(gl.TEXTURE_2D, self.renderTarget); - - gl.uniform4fv(self.uniforms.viewportOffsetScale, self.viewportOffsetScale); - - // Draws both eyes - gl.drawElements(gl.TRIANGLES, self.indexCount, gl.UNSIGNED_SHORT, 0); - - if (self.cardboardUI) { - self.cardboardUI.renderNoState(); - } - - // Bind the fake default framebuffer again - self.realBindFramebuffer.call(self.gl, gl.FRAMEBUFFER, self.framebuffer); - - // If preserveDrawingBuffer == false clear the framebuffer - if (!self.ctxAttribs.preserveDrawingBuffer) { - self.realClearColor.call(gl, 0, 0, 0, 0); - gl.clear(gl.COLOR_BUFFER_BIT); - } - - if (!WebVRConfig.DIRTY_SUBMIT_FRAME_BINDINGS) { - self.realBindFramebuffer.call(gl, gl.FRAMEBUFFER, self.lastBoundFramebuffer); - } - - // Restore state - if (self.cullFace) { self.realEnable.call(gl, gl.CULL_FACE); } - if (self.depthTest) { self.realEnable.call(gl, gl.DEPTH_TEST); } - if (self.blend) { self.realEnable.call(gl, gl.BLEND); } - if (self.scissorTest) { self.realEnable.call(gl, gl.SCISSOR_TEST); } - if (self.stencilTest) { self.realEnable.call(gl, gl.STENCIL_TEST); } - - self.realColorMask.apply(gl, self.colorMask); - self.realViewport.apply(gl, self.viewport); - if (self.ctxAttribs.alpha || !self.ctxAttribs.preserveDrawingBuffer) { - self.realClearColor.apply(gl, self.clearColor); - } - }); - - // Workaround for the fact that Safari doesn't allow us to patch the canvas - // width and height correctly. After each submit frame check to see what the - // real backbuffer size has been set to and resize the fake backbuffer size - // to match. - if (Util.isIOS()) { - var canvas = gl.canvas; - if (canvas.width != self.bufferWidth || canvas.height != self.bufferHeight) { - self.bufferWidth = canvas.width; - self.bufferHeight = canvas.height; - self.onResize(); - } - } -}; - -/** - * Call when the deviceInfo has changed. At this point we need - * to re-calculate the distortion mesh. - */ -CardboardDistorter.prototype.updateDeviceInfo = function(deviceInfo) { - var gl = this.gl; - var self = this; - - var glState = [gl.ARRAY_BUFFER_BINDING, gl.ELEMENT_ARRAY_BUFFER_BINDING]; - WGLUPreserveGLState(gl, glState, function(gl) { - var vertices = self.computeMeshVertices_(self.meshWidth, self.meshHeight, deviceInfo); - gl.bindBuffer(gl.ARRAY_BUFFER, self.vertexBuffer); - gl.bufferData(gl.ARRAY_BUFFER, vertices, gl.STATIC_DRAW); - - // Indices don't change based on device parameters, so only compute once. - if (!self.indexCount) { - var indices = self.computeMeshIndices_(self.meshWidth, self.meshHeight); - gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, self.indexBuffer); - gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, indices, gl.STATIC_DRAW); - self.indexCount = indices.length; - } - }); -}; - -/** - * Build the distortion mesh vertices. - * Based on code from the Unity cardboard plugin. - */ -CardboardDistorter.prototype.computeMeshVertices_ = function(width, height, deviceInfo) { - var vertices = new Float32Array(2 * width * height * 5); - - var lensFrustum = deviceInfo.getLeftEyeVisibleTanAngles(); - var noLensFrustum = deviceInfo.getLeftEyeNoLensTanAngles(); - var viewport = deviceInfo.getLeftEyeVisibleScreenRect(noLensFrustum); - var vidx = 0; - var iidx = 0; - for (var e = 0; e < 2; e++) { - for (var j = 0; j < height; j++) { - for (var i = 0; i < width; i++, vidx++) { - var u = i / (width - 1); - var v = j / (height - 1); - - // Grid points regularly spaced in StreoScreen, and barrel distorted in - // the mesh. - var s = u; - var t = v; - var x = Util.lerp(lensFrustum[0], lensFrustum[2], u); - var y = Util.lerp(lensFrustum[3], lensFrustum[1], v); - var d = Math.sqrt(x * x + y * y); - var r = deviceInfo.distortion.distortInverse(d); - var p = x * r / d; - var q = y * r / d; - u = (p - noLensFrustum[0]) / (noLensFrustum[2] - noLensFrustum[0]); - v = (q - noLensFrustum[3]) / (noLensFrustum[1] - noLensFrustum[3]); - - // Convert u,v to mesh screen coordinates. - var aspect = deviceInfo.device.widthMeters / deviceInfo.device.heightMeters; - - // FIXME: The original Unity plugin multiplied U by the aspect ratio - // and didn't multiply either value by 2, but that seems to get it - // really close to correct looking for me. I hate this kind of "Don't - // know why it works" code though, and wold love a more logical - // explanation of what needs to happen here. - u = (viewport.x + u * viewport.width - 0.5) * 2.0; //* aspect; - v = (viewport.y + v * viewport.height - 0.5) * 2.0; - - vertices[(vidx * 5) + 0] = u; // position.x - vertices[(vidx * 5) + 1] = v; // position.y - vertices[(vidx * 5) + 2] = s; // texCoord.x - vertices[(vidx * 5) + 3] = t; // texCoord.y - vertices[(vidx * 5) + 4] = e; // texCoord.z (viewport index) - } - } - var w = lensFrustum[2] - lensFrustum[0]; - lensFrustum[0] = -(w + lensFrustum[0]); - lensFrustum[2] = w - lensFrustum[2]; - w = noLensFrustum[2] - noLensFrustum[0]; - noLensFrustum[0] = -(w + noLensFrustum[0]); - noLensFrustum[2] = w - noLensFrustum[2]; - viewport.x = 1 - (viewport.x + viewport.width); - } - return vertices; -} - -/** - * Build the distortion mesh indices. - * Based on code from the Unity cardboard plugin. - */ -CardboardDistorter.prototype.computeMeshIndices_ = function(width, height) { - var indices = new Uint16Array(2 * (width - 1) * (height - 1) * 6); - var halfwidth = width / 2; - var halfheight = height / 2; - var vidx = 0; - var iidx = 0; - for (var e = 0; e < 2; e++) { - for (var j = 0; j < height; j++) { - for (var i = 0; i < width; i++, vidx++) { - if (i == 0 || j == 0) - continue; - // Build a quad. Lower right and upper left quadrants have quads with - // the triangle diagonal flipped to get the vignette to interpolate - // correctly. - if ((i <= halfwidth) == (j <= halfheight)) { - // Quad diagonal lower left to upper right. - indices[iidx++] = vidx; - indices[iidx++] = vidx - width - 1; - indices[iidx++] = vidx - width; - indices[iidx++] = vidx - width - 1; - indices[iidx++] = vidx; - indices[iidx++] = vidx - 1; - } else { - // Quad diagonal upper left to lower right. - indices[iidx++] = vidx - 1; - indices[iidx++] = vidx - width; - indices[iidx++] = vidx; - indices[iidx++] = vidx - width; - indices[iidx++] = vidx - 1; - indices[iidx++] = vidx - width - 1; - } - } - } - } - return indices; -}; - -CardboardDistorter.prototype.getOwnPropertyDescriptor_ = function(proto, attrName) { - var descriptor = Object.getOwnPropertyDescriptor(proto, attrName); - // In some cases (ahem... Safari), the descriptor returns undefined get and - // set fields. In this case, we need to create a synthetic property - // descriptor. This works around some of the issues in - // https://github.com/borismus/webvr-polyfill/issues/46 - if (descriptor.get === undefined || descriptor.set === undefined) { - descriptor.configurable = true; - descriptor.enumerable = true; - descriptor.get = function() { - return this.getAttribute(attrName); - }; - descriptor.set = function(val) { - this.setAttribute(attrName, val); - }; - } - return descriptor; -}; - -module.exports = CardboardDistorter; - -},{"./cardboard-ui.js":4,"./deps/wglu-preserve-state.js":6,"./util.js":22}],4:[function(_dereq_,module,exports){ -/* - * Copyright 2016 Google Inc. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -var Util = _dereq_('./util.js'); -var WGLUPreserveGLState = _dereq_('./deps/wglu-preserve-state.js'); - -var uiVS = [ - 'attribute vec2 position;', - - 'uniform mat4 projectionMat;', - - 'void main() {', - ' gl_Position = projectionMat * vec4( position, -1.0, 1.0 );', - '}', -].join('\n'); - -var uiFS = [ - 'precision mediump float;', - - 'uniform vec4 color;', - - 'void main() {', - ' gl_FragColor = color;', - '}', -].join('\n'); - -var DEG2RAD = Math.PI/180.0; - -// The gear has 6 identical sections, each spanning 60 degrees. -var kAnglePerGearSection = 60; - -// Half-angle of the span of the outer rim. -var kOuterRimEndAngle = 12; - -// Angle between the middle of the outer rim and the start of the inner rim. -var kInnerRimBeginAngle = 20; - -// Distance from center to outer rim, normalized so that the entire model -// fits in a [-1, 1] x [-1, 1] square. -var kOuterRadius = 1; - -// Distance from center to depressed rim, in model units. -var kMiddleRadius = 0.75; - -// Radius of the inner hollow circle, in model units. -var kInnerRadius = 0.3125; - -// Center line thickness in DP. -var kCenterLineThicknessDp = 4; - -// Button width in DP. -var kButtonWidthDp = 28; - -// Factor to scale the touch area that responds to the touch. -var kTouchSlopFactor = 1.5; - -var Angles = [ - 0, kOuterRimEndAngle, kInnerRimBeginAngle, - kAnglePerGearSection - kInnerRimBeginAngle, - kAnglePerGearSection - kOuterRimEndAngle -]; - -/** - * Renders the alignment line and "options" gear. It is assumed that the canvas - * this is rendered into covers the entire screen (or close to it.) - */ -function CardboardUI(gl) { - this.gl = gl; - - this.attribs = { - position: 0 - }; - this.program = Util.linkProgram(gl, uiVS, uiFS, this.attribs); - this.uniforms = Util.getProgramUniforms(gl, this.program); - - this.vertexBuffer = gl.createBuffer(); - this.gearOffset = 0; - this.gearVertexCount = 0; - this.arrowOffset = 0; - this.arrowVertexCount = 0; - - this.projMat = new Float32Array(16); - - this.listener = null; - - this.onResize(); -}; - -/** - * Tears down all the resources created by the UI renderer. - */ -CardboardUI.prototype.destroy = function() { - var gl = this.gl; - - if (this.listener) { - gl.canvas.removeEventListener('click', this.listener, false); - } - - gl.deleteProgram(this.program); - gl.deleteBuffer(this.vertexBuffer); -}; - -/** - * Adds a listener to clicks on the gear and back icons - */ -CardboardUI.prototype.listen = function(optionsCallback, backCallback) { - var canvas = this.gl.canvas; - this.listener = function(event) { - var midline = canvas.clientWidth / 2; - var buttonSize = kButtonWidthDp * kTouchSlopFactor; - // Check to see if the user clicked on (or around) the gear icon - if (event.clientX > midline - buttonSize && - event.clientX < midline + buttonSize && - event.clientY > canvas.clientHeight - buttonSize) { - optionsCallback(event); - } - // Check to see if the user clicked on (or around) the back icon - else if (event.clientX < buttonSize && event.clientY < buttonSize) { - backCallback(event); - } - }; - canvas.addEventListener('click', this.listener, false); -}; - -/** - * Builds the UI mesh. - */ -CardboardUI.prototype.onResize = function() { - var gl = this.gl; - var self = this; - - var glState = [ - gl.ARRAY_BUFFER_BINDING - ]; - - WGLUPreserveGLState(gl, glState, function(gl) { - var vertices = []; - - var midline = gl.drawingBufferWidth / 2; - - // Assumes your canvas width and height is scaled proportionately. - // TODO(smus): The following causes buttons to become huge on iOS, but seems - // like the right thing to do. For now, added a hack. But really, investigate why. - var dps = (gl.drawingBufferWidth / (screen.width * window.devicePixelRatio)); - if (!Util.isIOS()) { - dps *= window.devicePixelRatio; - } - - var lineWidth = kCenterLineThicknessDp * dps / 2; - var buttonSize = kButtonWidthDp * kTouchSlopFactor * dps; - var buttonScale = kButtonWidthDp * dps / 2; - var buttonBorder = ((kButtonWidthDp * kTouchSlopFactor) - kButtonWidthDp) * dps; - - // Build centerline - vertices.push(midline - lineWidth, buttonSize); - vertices.push(midline - lineWidth, gl.drawingBufferHeight); - vertices.push(midline + lineWidth, buttonSize); - vertices.push(midline + lineWidth, gl.drawingBufferHeight); - - // Build gear - self.gearOffset = (vertices.length / 2); - - function addGearSegment(theta, r) { - var angle = (90 - theta) * DEG2RAD; - var x = Math.cos(angle); - var y = Math.sin(angle); - vertices.push(kInnerRadius * x * buttonScale + midline, kInnerRadius * y * buttonScale + buttonScale); - vertices.push(r * x * buttonScale + midline, r * y * buttonScale + buttonScale); - } - - for (var i = 0; i <= 6; i++) { - var segmentTheta = i * kAnglePerGearSection; - - addGearSegment(segmentTheta, kOuterRadius); - addGearSegment(segmentTheta + kOuterRimEndAngle, kOuterRadius); - addGearSegment(segmentTheta + kInnerRimBeginAngle, kMiddleRadius); - addGearSegment(segmentTheta + (kAnglePerGearSection - kInnerRimBeginAngle), kMiddleRadius); - addGearSegment(segmentTheta + (kAnglePerGearSection - kOuterRimEndAngle), kOuterRadius); - } - - self.gearVertexCount = (vertices.length / 2) - self.gearOffset; - - // Build back arrow - self.arrowOffset = (vertices.length / 2); - - function addArrowVertex(x, y) { - vertices.push(buttonBorder + x, gl.drawingBufferHeight - buttonBorder - y); - } - - var angledLineWidth = lineWidth / Math.sin(45 * DEG2RAD); - - addArrowVertex(0, buttonScale); - addArrowVertex(buttonScale, 0); - addArrowVertex(buttonScale + angledLineWidth, angledLineWidth); - addArrowVertex(angledLineWidth, buttonScale + angledLineWidth); - - addArrowVertex(angledLineWidth, buttonScale - angledLineWidth); - addArrowVertex(0, buttonScale); - addArrowVertex(buttonScale, buttonScale * 2); - addArrowVertex(buttonScale + angledLineWidth, (buttonScale * 2) - angledLineWidth); - - addArrowVertex(angledLineWidth, buttonScale - angledLineWidth); - addArrowVertex(0, buttonScale); - - addArrowVertex(angledLineWidth, buttonScale - lineWidth); - addArrowVertex(kButtonWidthDp * dps, buttonScale - lineWidth); - addArrowVertex(angledLineWidth, buttonScale + lineWidth); - addArrowVertex(kButtonWidthDp * dps, buttonScale + lineWidth); - - self.arrowVertexCount = (vertices.length / 2) - self.arrowOffset; - - // Buffer data - gl.bindBuffer(gl.ARRAY_BUFFER, self.vertexBuffer); - gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(vertices), gl.STATIC_DRAW); - }); -}; - -/** - * Performs distortion pass on the injected backbuffer, rendering it to the real - * backbuffer. - */ -CardboardUI.prototype.render = function() { - var gl = this.gl; - var self = this; - - var glState = [ - gl.CULL_FACE, - gl.DEPTH_TEST, - gl.BLEND, - gl.SCISSOR_TEST, - gl.STENCIL_TEST, - gl.COLOR_WRITEMASK, - gl.VIEWPORT, - - gl.CURRENT_PROGRAM, - gl.ARRAY_BUFFER_BINDING - ]; - - WGLUPreserveGLState(gl, glState, function(gl) { - // Make sure the GL state is in a good place - gl.disable(gl.CULL_FACE); - gl.disable(gl.DEPTH_TEST); - gl.disable(gl.BLEND); - gl.disable(gl.SCISSOR_TEST); - gl.disable(gl.STENCIL_TEST); - gl.colorMask(true, true, true, true); - gl.viewport(0, 0, gl.drawingBufferWidth, gl.drawingBufferHeight); - - self.renderNoState(); - }); -}; - -CardboardUI.prototype.renderNoState = function() { - var gl = this.gl; - - // Bind distortion program and mesh - gl.useProgram(this.program); - - gl.bindBuffer(gl.ARRAY_BUFFER, this.vertexBuffer); - gl.enableVertexAttribArray(this.attribs.position); - gl.vertexAttribPointer(this.attribs.position, 2, gl.FLOAT, false, 8, 0); - - gl.uniform4f(this.uniforms.color, 1.0, 1.0, 1.0, 1.0); - - Util.orthoMatrix(this.projMat, 0, gl.drawingBufferWidth, 0, gl.drawingBufferHeight, 0.1, 1024.0); - gl.uniformMatrix4fv(this.uniforms.projectionMat, false, this.projMat); - - // Draws UI element - gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4); - gl.drawArrays(gl.TRIANGLE_STRIP, this.gearOffset, this.gearVertexCount); - gl.drawArrays(gl.TRIANGLE_STRIP, this.arrowOffset, this.arrowVertexCount); -}; - -module.exports = CardboardUI; - -},{"./deps/wglu-preserve-state.js":6,"./util.js":22}],5:[function(_dereq_,module,exports){ -/* - * Copyright 2016 Google Inc. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -var CardboardDistorter = _dereq_('./cardboard-distorter.js'); -var CardboardUI = _dereq_('./cardboard-ui.js'); -var DeviceInfo = _dereq_('./device-info.js'); -var Dpdb = _dereq_('./dpdb/dpdb.js'); -var FusionPoseSensor = _dereq_('./sensor-fusion/fusion-pose-sensor.js'); -var RotateInstructions = _dereq_('./rotate-instructions.js'); -var ViewerSelector = _dereq_('./viewer-selector.js'); -var VRDisplay = _dereq_('./base.js').VRDisplay; -var Util = _dereq_('./util.js'); - -var Eye = { - LEFT: 'left', - RIGHT: 'right' -}; - -/** - * VRDisplay based on mobile device parameters and DeviceMotion APIs. - */ -function CardboardVRDisplay() { - this.displayName = 'Cardboard VRDisplay (webvr-polyfill)'; - - this.capabilities.hasOrientation = true; - this.capabilities.canPresent = true; - - // "Private" members. - this.bufferScale_ = WebVRConfig.BUFFER_SCALE; - this.poseSensor_ = new FusionPoseSensor(); - this.distorter_ = null; - this.cardboardUI_ = null; - - this.dpdb_ = new Dpdb(true, this.onDeviceParamsUpdated_.bind(this)); - this.deviceInfo_ = new DeviceInfo(this.dpdb_.getDeviceParams()); - - this.viewerSelector_ = new ViewerSelector(); - this.viewerSelector_.on('change', this.onViewerChanged_.bind(this)); - - // Set the correct initial viewer. - this.deviceInfo_.setViewer(this.viewerSelector_.getCurrentViewer()); - - if (!WebVRConfig.ROTATE_INSTRUCTIONS_DISABLED) { - this.rotateInstructions_ = new RotateInstructions(); - } - - if (Util.isIOS()) { - // Listen for resize events to workaround this awful Safari bug. - window.addEventListener('resize', this.onResize_.bind(this)); - } -} -CardboardVRDisplay.prototype = new VRDisplay(); - -CardboardVRDisplay.prototype.getImmediatePose = function() { - return { - position: this.poseSensor_.getPosition(), - orientation: this.poseSensor_.getOrientation(), - linearVelocity: null, - linearAcceleration: null, - angularVelocity: null, - angularAcceleration: null - }; -}; - -CardboardVRDisplay.prototype.resetPose = function() { - this.poseSensor_.resetPose(); -}; - -CardboardVRDisplay.prototype.getEyeParameters = function(whichEye) { - var offset = [this.deviceInfo_.viewer.interLensDistance * 0.5, 0.0, 0.0]; - var fieldOfView; - - // TODO: FoV can be a little expensive to compute. Cache when device params change. - if (whichEye == Eye.LEFT) { - offset[0] *= -1.0; - fieldOfView = this.deviceInfo_.getFieldOfViewLeftEye(); - } else if (whichEye == Eye.RIGHT) { - fieldOfView = this.deviceInfo_.getFieldOfViewRightEye(); - } else { - console.error('Invalid eye provided: %s', whichEye); - return null; - } - - return { - fieldOfView: fieldOfView, - offset: offset, - // TODO: Should be able to provide better values than these. - renderWidth: this.deviceInfo_.device.width * 0.5 * this.bufferScale_, - renderHeight: this.deviceInfo_.device.height * this.bufferScale_, - }; -}; - -CardboardVRDisplay.prototype.onDeviceParamsUpdated_ = function(newParams) { - console.log('DPDB reported that device params were updated.'); - this.deviceInfo_.updateDeviceParams(newParams); - - if (this.distorter_) { - this.distorter.updateDeviceInfo(this.deviceInfo_); - } -}; - -CardboardVRDisplay.prototype.updateBounds_ = function () { - if (this.layer_ && this.distorter_ && (this.layer_.leftBounds || this.layer_.rightBounds)) { - this.distorter_.setTextureBounds(this.layer_.leftBounds, this.layer_.rightBounds); - } -}; - -CardboardVRDisplay.prototype.beginPresent_ = function() { - var gl = this.layer_.source.getContext('webgl'); - if (!gl) - gl = this.layer_.source.getContext('experimental-webgl'); - if (!gl) - gl = this.layer_.source.getContext('webgl2'); - - if (!gl) - return; // Can't do distortion without a WebGL context. - - // Provides a way to opt out of distortion - if (this.layer_.predistorted) { - if (!WebVRConfig.CARDBOARD_UI_DISABLED) { - gl.canvas.width = Util.getScreenWidth() * this.bufferScale_; - gl.canvas.height = Util.getScreenHeight() * this.bufferScale_; - this.cardboardUI_ = new CardboardUI(gl); - } - } else { - // Create a new distorter for the target context - this.distorter_ = new CardboardDistorter(gl); - this.distorter_.updateDeviceInfo(this.deviceInfo_); - this.cardboardUI_ = this.distorter_.cardboardUI; - } - - if (this.cardboardUI_) { - this.cardboardUI_.listen(function(e) { - // Options clicked. - this.viewerSelector_.show(this.layer_.source.parentElement); - e.stopPropagation(); - e.preventDefault(); - }.bind(this), function(e) { - // Back clicked. - this.exitPresent(); - e.stopPropagation(); - e.preventDefault(); - }.bind(this)); - } - - if (this.rotateInstructions_) { - if (Util.isLandscapeMode() && Util.isMobile()) { - // In landscape mode, temporarily show the "put into Cardboard" - // interstitial. Otherwise, do the default thing. - this.rotateInstructions_.showTemporarily(3000, this.layer_.source.parentElement); - } else { - this.rotateInstructions_.update(); - } - } - - // Listen for orientation change events in order to show interstitial. - this.orientationHandler = this.onOrientationChange_.bind(this); - window.addEventListener('orientationchange', this.orientationHandler); - - // Listen for present display change events in order to update distorter dimensions - this.vrdisplaypresentchangeHandler = this.updateBounds_.bind(this); - window.addEventListener('vrdisplaypresentchange', this.vrdisplaypresentchangeHandler); - - // Fire this event initially, to give geometry-distortion clients the chance - // to do something custom. - this.fireVRDisplayDeviceParamsChange_(); -}; - -CardboardVRDisplay.prototype.endPresent_ = function() { - if (this.distorter_) { - this.distorter_.destroy(); - this.distorter_ = null; - } - if (this.cardboardUI_) { - this.cardboardUI_.destroy(); - this.cardboardUI_ = null; - } - - if (this.rotateInstructions_) { - this.rotateInstructions_.hide(); - } - this.viewerSelector_.hide(); - - window.removeEventListener('orientationchange', this.orientationHandler); - window.removeEventListener('vrdisplaypresentchange', this.vrdisplaypresentchangeHandler); -}; - -CardboardVRDisplay.prototype.submitFrame = function(pose) { - if (this.distorter_) { - this.distorter_.submitFrame(); - } else if (this.cardboardUI_ && this.layer_) { - // Hack for predistorted: true. - var canvas = this.layer_.source.getContext('webgl').canvas; - if (canvas.width != this.lastWidth || canvas.height != this.lastHeight) { - this.cardboardUI_.onResize(); - } - this.lastWidth = canvas.width; - this.lastHeight = canvas.height; - - // Render the Cardboard UI. - this.cardboardUI_.render(); - } -}; - -CardboardVRDisplay.prototype.onOrientationChange_ = function(e) { - console.log('onOrientationChange_'); - - // Hide the viewer selector. - this.viewerSelector_.hide(); - - // Update the rotate instructions. - if (this.rotateInstructions_) { - this.rotateInstructions_.update(); - } - - this.onResize_(); -}; - -CardboardVRDisplay.prototype.onResize_ = function(e) { - if (this.layer_) { - var gl = this.layer_.source.getContext('webgl'); - // Size the CSS canvas. - // Added padding on right and bottom because iPhone 5 will not - // hide the URL bar unless content is bigger than the screen. - // This will not be visible as long as the container element (e.g. body) - // is set to 'overflow: hidden'. - var cssProperties = [ - 'position: absolute', - 'top: 0', - 'left: 0', - 'width: ' + Math.max(screen.width, screen.height) + 'px', - 'height: ' + Math.min(screen.height, screen.width) + 'px', - 'border: 0', - 'margin: 0', - 'padding: 0 10px 10px 0', - ]; - gl.canvas.setAttribute('style', cssProperties.join('; ') + ';'); - - Util.safariCssSizeWorkaround(gl.canvas); - } -}; - -CardboardVRDisplay.prototype.onViewerChanged_ = function(viewer) { - this.deviceInfo_.setViewer(viewer); - - if (this.distorter_) { - // Update the distortion appropriately. - this.distorter_.updateDeviceInfo(this.deviceInfo_); - } - - // Fire a new event containing viewer and device parameters for clients that - // want to implement their own geometry-based distortion. - this.fireVRDisplayDeviceParamsChange_(); -}; - -CardboardVRDisplay.prototype.fireVRDisplayDeviceParamsChange_ = function() { - var event = new CustomEvent('vrdisplaydeviceparamschange', { - detail: { - vrdisplay: this, - deviceInfo: this.deviceInfo_, - } - }); - window.dispatchEvent(event); -}; - -module.exports = CardboardVRDisplay; - -},{"./base.js":2,"./cardboard-distorter.js":3,"./cardboard-ui.js":4,"./device-info.js":7,"./dpdb/dpdb.js":11,"./rotate-instructions.js":16,"./sensor-fusion/fusion-pose-sensor.js":18,"./util.js":22,"./viewer-selector.js":23}],6:[function(_dereq_,module,exports){ -/* -Copyright (c) 2016, Brandon Jones. - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. -*/ - -/* -Caches specified GL state, runs a callback, and restores the cached state when -done. - -Example usage: - -var savedState = [ - gl.ARRAY_BUFFER_BINDING, - - // TEXTURE_BINDING_2D or _CUBE_MAP must always be followed by the texure unit. - gl.TEXTURE_BINDING_2D, gl.TEXTURE0, - - gl.CLEAR_COLOR, -]; -// After this call the array buffer, texture unit 0, active texture, and clear -// color will be restored. The viewport will remain changed, however, because -// gl.VIEWPORT was not included in the savedState list. -WGLUPreserveGLState(gl, savedState, function(gl) { - gl.viewport(0, 0, gl.drawingBufferWidth, gl.drawingBufferHeight); - - gl.bindBuffer(gl.ARRAY_BUFFER, buffer); - gl.bufferData(gl.ARRAY_BUFFER, ....); - - gl.activeTexture(gl.TEXTURE0); - gl.bindTexture(gl.TEXTURE_2D, texture); - gl.texImage2D(gl.TEXTURE_2D, ...); - - gl.clearColor(1, 0, 0, 1); - gl.clear(gl.COLOR_BUFFER_BIT); -}); - -Note that this is not intended to be fast. Managing state in your own code to -avoid redundant state setting and querying will always be faster. This function -is most useful for cases where you may not have full control over the WebGL -calls being made, such as tooling or effect injectors. -*/ - -function WGLUPreserveGLState(gl, bindings, callback) { - if (!bindings) { - callback(gl); - return; - } - - var boundValues = []; - - var activeTexture = null; - for (var i = 0; i < bindings.length; ++i) { - var binding = bindings[i]; - switch (binding) { - case gl.TEXTURE_BINDING_2D: - case gl.TEXTURE_BINDING_CUBE_MAP: - var textureUnit = bindings[++i]; - if (textureUnit < gl.TEXTURE0 || textureUnit > gl.TEXTURE31) { - console.error("TEXTURE_BINDING_2D or TEXTURE_BINDING_CUBE_MAP must be followed by a valid texture unit"); - boundValues.push(null, null); - break; - } - if (!activeTexture) { - activeTexture = gl.getParameter(gl.ACTIVE_TEXTURE); - } - gl.activeTexture(textureUnit); - boundValues.push(gl.getParameter(binding), null); - break; - case gl.ACTIVE_TEXTURE: - activeTexture = gl.getParameter(gl.ACTIVE_TEXTURE); - boundValues.push(null); - break; - default: - boundValues.push(gl.getParameter(binding)); - break; - } - } - - callback(gl); - - for (var i = 0; i < bindings.length; ++i) { - var binding = bindings[i]; - var boundValue = boundValues[i]; - switch (binding) { - case gl.ACTIVE_TEXTURE: - break; // Ignore this binding, since we special-case it to happen last. - case gl.ARRAY_BUFFER_BINDING: - gl.bindBuffer(gl.ARRAY_BUFFER, boundValue); - break; - case gl.COLOR_CLEAR_VALUE: - gl.clearColor(boundValue[0], boundValue[1], boundValue[2], boundValue[3]); - break; - case gl.COLOR_WRITEMASK: - gl.colorMask(boundValue[0], boundValue[1], boundValue[2], boundValue[3]); - break; - case gl.CURRENT_PROGRAM: - gl.useProgram(boundValue); - break; - case gl.ELEMENT_ARRAY_BUFFER_BINDING: - gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, boundValue); - break; - case gl.FRAMEBUFFER_BINDING: - gl.bindFramebuffer(gl.FRAMEBUFFER, boundValue); - break; - case gl.RENDERBUFFER_BINDING: - gl.bindRenderbuffer(gl.RENDERBUFFER, boundValue); - break; - case gl.TEXTURE_BINDING_2D: - var textureUnit = bindings[++i]; - if (textureUnit < gl.TEXTURE0 || textureUnit > gl.TEXTURE31) - break; - gl.activeTexture(textureUnit); - gl.bindTexture(gl.TEXTURE_2D, boundValue); - break; - case gl.TEXTURE_BINDING_CUBE_MAP: - var textureUnit = bindings[++i]; - if (textureUnit < gl.TEXTURE0 || textureUnit > gl.TEXTURE31) - break; - gl.activeTexture(textureUnit); - gl.bindTexture(gl.TEXTURE_CUBE_MAP, boundValue); - break; - case gl.VIEWPORT: - gl.viewport(boundValue[0], boundValue[1], boundValue[2], boundValue[3]); - break; - case gl.BLEND: - case gl.CULL_FACE: - case gl.DEPTH_TEST: - case gl.SCISSOR_TEST: - case gl.STENCIL_TEST: - if (boundValue) { - gl.enable(binding); - } else { - gl.disable(binding); - } - break; - default: - console.log("No GL restore behavior for 0x" + binding.toString(16)); - break; - } - - if (activeTexture) { - gl.activeTexture(activeTexture); - } - } -} - -module.exports = WGLUPreserveGLState; -},{}],7:[function(_dereq_,module,exports){ -/* - * Copyright 2015 Google Inc. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -var Distortion = _dereq_('./distortion/distortion.js'); -var MathUtil = _dereq_('./math-util.js'); -var Util = _dereq_('./util.js'); - -function Device(params) { - this.width = params.width || Util.getScreenWidth(); - this.height = params.height || Util.getScreenHeight(); - this.widthMeters = params.widthMeters; - this.heightMeters = params.heightMeters; - this.bevelMeters = params.bevelMeters; -} - - -// Fallback Android device (based on Nexus 5 measurements) for use when -// we can't recognize an Android device. -var DEFAULT_ANDROID = new Device({ - widthMeters: 0.110, - heightMeters: 0.062, - bevelMeters: 0.004 -}); - -// Fallback iOS device (based on iPhone6) for use when -// we can't recognize an Android device. -var DEFAULT_IOS = new Device({ - widthMeters: 0.1038, - heightMeters: 0.0584, - bevelMeters: 0.004 -}); - - -var Viewers = { - CardboardV1: new CardboardViewer({ - id: 'CardboardV1', - label: 'Cardboard I/O 2014', - fov: 40, - interLensDistance: 0.060, - baselineLensDistance: 0.035, - screenLensDistance: 0.042, - distortionCoefficients: [0.441, 0.156], - inverseCoefficients: [-0.4410035, 0.42756155, -0.4804439, 0.5460139, - -0.58821183, 0.5733938, -0.48303202, 0.33299083, -0.17573841, - 0.0651772, -0.01488963, 0.001559834] - }), - CardboardV2: new CardboardViewer({ - id: 'CardboardV2', - label: 'Cardboard I/O 2015', - fov: 60, - interLensDistance: 0.064, - baselineLensDistance: 0.035, - screenLensDistance: 0.039, - distortionCoefficients: [0.34, 0.55], - inverseCoefficients: [-0.33836704, -0.18162185, 0.862655, -1.2462051, - 1.0560602, -0.58208317, 0.21609078, -0.05444823, 0.009177956, - -9.904169E-4, 6.183535E-5, -1.6981803E-6] - }) -}; - - -var DEFAULT_LEFT_CENTER = {x: 0.5, y: 0.5}; -var DEFAULT_RIGHT_CENTER = {x: 0.5, y: 0.5}; - -/** - * Manages information about the device and the viewer. - * - * deviceParams indicates the parameters of the device to use (generally - * obtained from dpdb.getDeviceParams()). Can be null to mean no device - * params were found. - */ -function DeviceInfo(deviceParams) { - this.viewer = Viewers.CardboardV2; - this.updateDeviceParams(deviceParams); - this.distortion = new Distortion(this.viewer.distortionCoefficients); -} - -DeviceInfo.prototype.updateDeviceParams = function(deviceParams) { - this.device = this.determineDevice_(deviceParams) || this.device; -}; - -DeviceInfo.prototype.getDevice = function() { - return this.device; -}; - -DeviceInfo.prototype.setViewer = function(viewer) { - this.viewer = viewer; - this.distortion = new Distortion(this.viewer.distortionCoefficients); -}; - -DeviceInfo.prototype.determineDevice_ = function(deviceParams) { - if (!deviceParams) { - // No parameters, so use a default. - if (Util.isIOS()) { - console.warn('Using fallback iOS device measurements.'); - return DEFAULT_IOS; - } else { - console.warn('Using fallback Android device measurements.'); - return DEFAULT_ANDROID; - } - } - - // Compute device screen dimensions based on deviceParams. - var METERS_PER_INCH = 0.0254; - var metersPerPixelX = METERS_PER_INCH / deviceParams.xdpi; - var metersPerPixelY = METERS_PER_INCH / deviceParams.ydpi; - var width = Util.getScreenWidth(); - var height = Util.getScreenHeight(); - return new Device({ - widthMeters: metersPerPixelX * width, - heightMeters: metersPerPixelY * height, - bevelMeters: deviceParams.bevelMm * 0.001, - }); -}; - -/** - * Calculates field of view for the left eye. - */ -DeviceInfo.prototype.getDistortedFieldOfViewLeftEye = function() { - var viewer = this.viewer; - var device = this.device; - var distortion = this.distortion; - - // Device.height and device.width for device in portrait mode, so transpose. - var eyeToScreenDistance = viewer.screenLensDistance; - - var outerDist = (device.widthMeters - viewer.interLensDistance) / 2; - var innerDist = viewer.interLensDistance / 2; - var bottomDist = viewer.baselineLensDistance - device.bevelMeters; - var topDist = device.heightMeters - bottomDist; - - var outerAngle = MathUtil.radToDeg * Math.atan( - distortion.distort(outerDist / eyeToScreenDistance)); - var innerAngle = MathUtil.radToDeg * Math.atan( - distortion.distort(innerDist / eyeToScreenDistance)); - var bottomAngle = MathUtil.radToDeg * Math.atan( - distortion.distort(bottomDist / eyeToScreenDistance)); - var topAngle = MathUtil.radToDeg * Math.atan( - distortion.distort(topDist / eyeToScreenDistance)); - - return { - leftDegrees: Math.min(outerAngle, viewer.fov), - rightDegrees: Math.min(innerAngle, viewer.fov), - downDegrees: Math.min(bottomAngle, viewer.fov), - upDegrees: Math.min(topAngle, viewer.fov) - }; -}; - -/** - * Calculates the tan-angles from the maximum FOV for the left eye for the - * current device and screen parameters. - */ -DeviceInfo.prototype.getLeftEyeVisibleTanAngles = function() { - var viewer = this.viewer; - var device = this.device; - var distortion = this.distortion; - - // Tan-angles from the max FOV. - var fovLeft = Math.tan(-MathUtil.degToRad * viewer.fov); - var fovTop = Math.tan(MathUtil.degToRad * viewer.fov); - var fovRight = Math.tan(MathUtil.degToRad * viewer.fov); - var fovBottom = Math.tan(-MathUtil.degToRad * viewer.fov); - // Viewport size. - var halfWidth = device.widthMeters / 4; - var halfHeight = device.heightMeters / 2; - // Viewport center, measured from left lens position. - var verticalLensOffset = (viewer.baselineLensDistance - device.bevelMeters - halfHeight); - var centerX = viewer.interLensDistance / 2 - halfWidth; - var centerY = -verticalLensOffset; - var centerZ = viewer.screenLensDistance; - // Tan-angles of the viewport edges, as seen through the lens. - var screenLeft = distortion.distort((centerX - halfWidth) / centerZ); - var screenTop = distortion.distort((centerY + halfHeight) / centerZ); - var screenRight = distortion.distort((centerX + halfWidth) / centerZ); - var screenBottom = distortion.distort((centerY - halfHeight) / centerZ); - // Compare the two sets of tan-angles and take the value closer to zero on each side. - var result = new Float32Array(4); - result[0] = Math.max(fovLeft, screenLeft); - result[1] = Math.min(fovTop, screenTop); - result[2] = Math.min(fovRight, screenRight); - result[3] = Math.max(fovBottom, screenBottom); - return result; -}; - -/** - * Calculates the tan-angles from the maximum FOV for the left eye for the - * current device and screen parameters, assuming no lenses. - */ -DeviceInfo.prototype.getLeftEyeNoLensTanAngles = function() { - var viewer = this.viewer; - var device = this.device; - var distortion = this.distortion; - - var result = new Float32Array(4); - // Tan-angles from the max FOV. - var fovLeft = distortion.distortInverse(Math.tan(-MathUtil.degToRad * viewer.fov)); - var fovTop = distortion.distortInverse(Math.tan(MathUtil.degToRad * viewer.fov)); - var fovRight = distortion.distortInverse(Math.tan(MathUtil.degToRad * viewer.fov)); - var fovBottom = distortion.distortInverse(Math.tan(-MathUtil.degToRad * viewer.fov)); - // Viewport size. - var halfWidth = device.widthMeters / 4; - var halfHeight = device.heightMeters / 2; - // Viewport center, measured from left lens position. - var verticalLensOffset = (viewer.baselineLensDistance - device.bevelMeters - halfHeight); - var centerX = viewer.interLensDistance / 2 - halfWidth; - var centerY = -verticalLensOffset; - var centerZ = viewer.screenLensDistance; - // Tan-angles of the viewport edges, as seen through the lens. - var screenLeft = (centerX - halfWidth) / centerZ; - var screenTop = (centerY + halfHeight) / centerZ; - var screenRight = (centerX + halfWidth) / centerZ; - var screenBottom = (centerY - halfHeight) / centerZ; - // Compare the two sets of tan-angles and take the value closer to zero on each side. - result[0] = Math.max(fovLeft, screenLeft); - result[1] = Math.min(fovTop, screenTop); - result[2] = Math.min(fovRight, screenRight); - result[3] = Math.max(fovBottom, screenBottom); - return result; -}; - -/** - * Calculates the screen rectangle visible from the left eye for the - * current device and screen parameters. - */ -DeviceInfo.prototype.getLeftEyeVisibleScreenRect = function(undistortedFrustum) { - var viewer = this.viewer; - var device = this.device; - - var dist = viewer.screenLensDistance; - var eyeX = (device.widthMeters - viewer.interLensDistance) / 2; - var eyeY = viewer.baselineLensDistance - device.bevelMeters; - var left = (undistortedFrustum[0] * dist + eyeX) / device.widthMeters; - var top = (undistortedFrustum[1] * dist + eyeY) / device.heightMeters; - var right = (undistortedFrustum[2] * dist + eyeX) / device.widthMeters; - var bottom = (undistortedFrustum[3] * dist + eyeY) / device.heightMeters; - return { - x: left, - y: bottom, - width: right - left, - height: top - bottom - }; -}; - -DeviceInfo.prototype.getFieldOfViewLeftEye = function(opt_isUndistorted) { - return opt_isUndistorted ? this.getUndistortedFieldOfViewLeftEye() : - this.getDistortedFieldOfViewLeftEye(); -}; - -DeviceInfo.prototype.getFieldOfViewRightEye = function(opt_isUndistorted) { - var fov = this.getFieldOfViewLeftEye(opt_isUndistorted); - return { - leftDegrees: fov.rightDegrees, - rightDegrees: fov.leftDegrees, - upDegrees: fov.upDegrees, - downDegrees: fov.downDegrees - }; -}; - -/** - * Calculates undistorted field of view for the left eye. - */ -DeviceInfo.prototype.getUndistortedFieldOfViewLeftEye = function() { - var p = this.getUndistortedParams_(); - - return { - leftDegrees: MathUtil.radToDeg * Math.atan(p.outerDist), - rightDegrees: MathUtil.radToDeg * Math.atan(p.innerDist), - downDegrees: MathUtil.radToDeg * Math.atan(p.bottomDist), - upDegrees: MathUtil.radToDeg * Math.atan(p.topDist) - }; -}; - -DeviceInfo.prototype.getUndistortedViewportLeftEye = function() { - var p = this.getUndistortedParams_(); - var viewer = this.viewer; - var device = this.device; - - // Distances stored in local variables are in tan-angle units unless otherwise - // noted. - var eyeToScreenDistance = viewer.screenLensDistance; - var screenWidth = device.widthMeters / eyeToScreenDistance; - var screenHeight = device.heightMeters / eyeToScreenDistance; - var xPxPerTanAngle = device.width / screenWidth; - var yPxPerTanAngle = device.height / screenHeight; - - var x = Math.round((p.eyePosX - p.outerDist) * xPxPerTanAngle); - var y = Math.round((p.eyePosY - p.bottomDist) * yPxPerTanAngle); - return { - x: x, - y: y, - width: Math.round((p.eyePosX + p.innerDist) * xPxPerTanAngle) - x, - height: Math.round((p.eyePosY + p.topDist) * yPxPerTanAngle) - y - }; -}; - -DeviceInfo.prototype.getUndistortedParams_ = function() { - var viewer = this.viewer; - var device = this.device; - var distortion = this.distortion; - - // Most of these variables in tan-angle units. - var eyeToScreenDistance = viewer.screenLensDistance; - var halfLensDistance = viewer.interLensDistance / 2 / eyeToScreenDistance; - var screenWidth = device.widthMeters / eyeToScreenDistance; - var screenHeight = device.heightMeters / eyeToScreenDistance; - - var eyePosX = screenWidth / 2 - halfLensDistance; - var eyePosY = (viewer.baselineLensDistance - device.bevelMeters) / eyeToScreenDistance; - - var maxFov = viewer.fov; - var viewerMax = distortion.distortInverse(Math.tan(MathUtil.degToRad * maxFov)); - var outerDist = Math.min(eyePosX, viewerMax); - var innerDist = Math.min(halfLensDistance, viewerMax); - var bottomDist = Math.min(eyePosY, viewerMax); - var topDist = Math.min(screenHeight - eyePosY, viewerMax); - - return { - outerDist: outerDist, - innerDist: innerDist, - topDist: topDist, - bottomDist: bottomDist, - eyePosX: eyePosX, - eyePosY: eyePosY - }; -}; - - -function CardboardViewer(params) { - // A machine readable ID. - this.id = params.id; - // A human readable label. - this.label = params.label; - - // Field of view in degrees (per side). - this.fov = params.fov; - - // Distance between lens centers in meters. - this.interLensDistance = params.interLensDistance; - // Distance between viewer baseline and lens center in meters. - this.baselineLensDistance = params.baselineLensDistance; - // Screen-to-lens distance in meters. - this.screenLensDistance = params.screenLensDistance; - - // Distortion coefficients. - this.distortionCoefficients = params.distortionCoefficients; - // Inverse distortion coefficients. - // TODO: Calculate these from distortionCoefficients in the future. - this.inverseCoefficients = params.inverseCoefficients; -} - -// Export viewer information. -DeviceInfo.Viewers = Viewers; -module.exports = DeviceInfo; - -},{"./distortion/distortion.js":9,"./math-util.js":14,"./util.js":22}],8:[function(_dereq_,module,exports){ -/* - * Copyright 2016 Google Inc. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -var VRDisplay = _dereq_('./base.js').VRDisplay; -var HMDVRDevice = _dereq_('./base.js').HMDVRDevice; -var PositionSensorVRDevice = _dereq_('./base.js').PositionSensorVRDevice; - -/** - * Wraps a VRDisplay and exposes it as a HMDVRDevice - */ -function VRDisplayHMDDevice(display) { - this.display = display; - - this.hardwareUnitId = display.displayId; - this.deviceId = 'webvr-polyfill:HMD:' + display.displayId; - this.deviceName = display.displayName + ' (HMD)'; -} -VRDisplayHMDDevice.prototype = new HMDVRDevice(); - -VRDisplayHMDDevice.prototype.getEyeParameters = function(whichEye) { - var eyeParameters = this.display.getEyeParameters(whichEye); - - return { - currentFieldOfView: eyeParameters.fieldOfView, - maximumFieldOfView: eyeParameters.fieldOfView, - minimumFieldOfView: eyeParameters.fieldOfView, - recommendedFieldOfView: eyeParameters.fieldOfView, - eyeTranslation: { x: eyeParameters.offset[0], y: eyeParameters.offset[1], z: eyeParameters.offset[2] }, - renderRect: { - x: (whichEye == 'right') ? eyeParameters.renderWidth : 0, - y: 0, - width: eyeParameters.renderWidth, - height: eyeParameters.renderHeight - } - }; -}; - -VRDisplayHMDDevice.prototype.setFieldOfView = - function(opt_fovLeft, opt_fovRight, opt_zNear, opt_zFar) { - // Not supported. getEyeParameters reports that the min, max, and recommended - // FoV is all the same, so no adjustment can be made. -}; - -// TODO: Need to hook requestFullscreen to see if a wrapped VRDisplay was passed -// in as an option. If so we should prevent the default fullscreen behavior and -// call VRDisplay.requestPresent instead. - -/** - * Wraps a VRDisplay and exposes it as a PositionSensorVRDevice - */ -function VRDisplayPositionSensorDevice(display) { - this.display = display; - - this.hardwareUnitId = display.displayId; - this.deviceId = 'webvr-polyfill:PositionSensor: ' + display.displayId; - this.deviceName = display.displayName + ' (PositionSensor)'; -} -VRDisplayPositionSensorDevice.prototype = new PositionSensorVRDevice(); - -VRDisplayPositionSensorDevice.prototype.getState = function() { - var pose = this.display.getPose(); - return { - position: pose.position ? { x: pose.position[0], y: pose.position[1], z: pose.position[2] } : null, - orientation: pose.orientation ? { x: pose.orientation[0], y: pose.orientation[1], z: pose.orientation[2], w: pose.orientation[3] } : null, - linearVelocity: null, - linearAcceleration: null, - angularVelocity: null, - angularAcceleration: null - }; -}; - -VRDisplayPositionSensorDevice.prototype.resetState = function() { - return this.positionDevice.resetPose(); -}; - - -module.exports.VRDisplayHMDDevice = VRDisplayHMDDevice; -module.exports.VRDisplayPositionSensorDevice = VRDisplayPositionSensorDevice; - - -},{"./base.js":2}],9:[function(_dereq_,module,exports){ -/** - * TODO(smus): Implement coefficient inversion. - */ -function Distortion(coefficients) { - this.coefficients = coefficients; -} - -/** - * Calculates the inverse distortion for a radius. - *

- * Allows to compute the original undistorted radius from a distorted one. - * See also getApproximateInverseDistortion() for a faster but potentially - * less accurate method. - * - * @param {Number} radius Distorted radius from the lens center in tan-angle units. - * @return {Number} The undistorted radius in tan-angle units. - */ -Distortion.prototype.distortInverse = function(radius) { - // Secant method. - var r0 = 0; - var r1 = 1; - var dr0 = radius - this.distort(r0); - while (Math.abs(r1 - r0) > 0.0001 /** 0.1mm */) { - var dr1 = radius - this.distort(r1); - var r2 = r1 - dr1 * ((r1 - r0) / (dr1 - dr0)); - r0 = r1; - r1 = r2; - dr0 = dr1; - } - return r1; -}; - -/** - * Distorts a radius by its distortion factor from the center of the lenses. - * - * @param {Number} radius Radius from the lens center in tan-angle units. - * @return {Number} The distorted radius in tan-angle units. - */ -Distortion.prototype.distort = function(radius) { - var r2 = radius * radius; - var ret = 0; - for (var i = 0; i < this.coefficients.length; i++) { - ret = r2 * (ret + this.coefficients[i]); - } - return (ret + 1) * radius; -}; - -// Functions below roughly ported from -// https://github.com/googlesamples/cardboard-unity/blob/master/Cardboard/Scripts/CardboardProfile.cs#L412 - -// Solves a small linear equation via destructive gaussian -// elimination and back substitution. This isn't generic numeric -// code, it's just a quick hack to work with the generally -// well-behaved symmetric matrices for least-squares fitting. -// Not intended for reuse. -// -// @param a Input positive definite symmetrical matrix. Destroyed -// during calculation. -// @param y Input right-hand-side values. Destroyed during calculation. -// @return Resulting x value vector. -// -Distortion.prototype.solveLinear_ = function(a, y) { - var n = a.length; - - // Gaussian elimination (no row exchange) to triangular matrix. - // The input matrix is a A^T A product which should be a positive - // definite symmetrical matrix, and if I remember my linear - // algebra right this implies that the pivots will be nonzero and - // calculations sufficiently accurate without needing row - // exchange. - for (var j = 0; j < n - 1; ++j) { - for (var k = j + 1; k < n; ++k) { - var p = a[j][k] / a[j][j]; - for (var i = j + 1; i < n; ++i) { - a[i][k] -= p * a[i][j]; - } - y[k] -= p * y[j]; - } - } - // From this point on, only the matrix elements a[j][i] with i>=j are - // valid. The elimination doesn't fill in eliminated 0 values. - - var x = new Array(n); - - // Back substitution. - for (var j = n - 1; j >= 0; --j) { - var v = y[j]; - for (var i = j + 1; i < n; ++i) { - v -= a[i][j] * x[i]; - } - x[j] = v / a[j][j]; - } - - return x; -}; - -// Solves a least-squares matrix equation. Given the equation A * x = y, calculate the -// least-square fit x = inverse(A * transpose(A)) * transpose(A) * y. The way this works -// is that, while A is typically not a square matrix (and hence not invertible), A * transpose(A) -// is always square. That is: -// A * x = y -// transpose(A) * (A * x) = transpose(A) * y <- multiply both sides by transpose(A) -// (transpose(A) * A) * x = transpose(A) * y <- associativity -// x = inverse(transpose(A) * A) * transpose(A) * y <- solve for x -// Matrix A's row count (first index) must match y's value count. A's column count (second index) -// determines the length of the result vector x. -Distortion.prototype.solveLeastSquares_ = function(matA, vecY) { - var i, j, k, sum; - var numSamples = matA.length; - var numCoefficients = matA[0].length; - if (numSamples != vecY.Length) { - throw new Error("Matrix / vector dimension mismatch"); - } - - // Calculate transpose(A) * A - var matATA = new Array(numCoefficients); - for (k = 0; k < numCoefficients; ++k) { - matATA[k] = new Array(numCoefficients); - for (j = 0; j < numCoefficients; ++j) { - sum = 0; - for (i = 0; i < numSamples; ++i) { - sum += matA[j][i] * matA[k][i]; - } - matATA[k][j] = sum; - } - } - - // Calculate transpose(A) * y - var vecATY = new Array(numCoefficients); - for (j = 0; j < numCoefficients; ++j) { - sum = 0; - for (i = 0; i < numSamples; ++i) { - sum += matA[j][i] * vecY[i]; - } - vecATY[j] = sum; - } - - // Now solve (A * transpose(A)) * x = transpose(A) * y. - return this.solveLinear_(matATA, vecATY); -}; - -/// Calculates an approximate inverse to the given radial distortion parameters. -Distortion.prototype.approximateInverse = function(maxRadius, numSamples) { - maxRadius = maxRadius || 1; - numSamples = numSamples || 100; - var numCoefficients = 6; - var i, j; - - // R + K1*R^3 + K2*R^5 = r, with R = rp = distort(r) - // Repeating for numSamples: - // [ R0^3, R0^5 ] * [ K1 ] = [ r0 - R0 ] - // [ R1^3, R1^5 ] [ K2 ] [ r1 - R1 ] - // [ R2^3, R2^5 ] [ r2 - R2 ] - // [ etc... ] [ etc... ] - // That is: - // matA * [K1, K2] = y - // Solve: - // [K1, K2] = inverse(transpose(matA) * matA) * transpose(matA) * y - var matA = new Array(numCoefficients); - for (j = 0; j < numCoefficients; ++j) { - matA[j] = new Array(numSamples); - } - var vecY = new Array(numSamples); - - for (i = 0; i < numSamples; ++i) { - var r = maxRadius * (i + 1) / numSamples; - var rp = this.distort(r); - var v = rp; - for (j = 0; j < numCoefficients; ++j) { - v *= rp * rp; - matA[j][i] = v; - } - vecY[i] = r - rp; - } - - var inverseCoefficients = this.solveLeastSquares_(matA, vecY); - - return new Distortion(inverseCoefficients); -}; - -module.exports = Distortion; - -},{}],10:[function(_dereq_,module,exports){ -/* - * Copyright 2015 Google Inc. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** - * DPDB cache. - */ -var DPDB_CACHE = { - "format": 1, - "last_updated": "2016-01-20T00:18:35Z", - "devices": [ - - { - "type": "android", - "rules": [ - { "mdmh": "asus/*/Nexus 7/*" }, - { "ua": "Nexus 7" } - ], - "dpi": [ 320.8, 323.0 ], - "bw": 3, - "ac": 500 - }, - - { - "type": "android", - "rules": [ - { "mdmh": "asus/*/ASUS_Z00AD/*" }, - { "ua": "ASUS_Z00AD" } - ], - "dpi": [ 403.0, 404.6 ], - "bw": 3, - "ac": 1000 - }, - - { - "type": "android", - "rules": [ - { "mdmh": "HTC/*/HTC6435LVW/*" }, - { "ua": "HTC6435LVW" } - ], - "dpi": [ 449.7, 443.3 ], - "bw": 3, - "ac": 1000 - }, - - { - "type": "android", - "rules": [ - { "mdmh": "HTC/*/HTC One XL/*" }, - { "ua": "HTC One XL" } - ], - "dpi": [ 315.3, 314.6 ], - "bw": 3, - "ac": 1000 - }, - - { - "type": "android", - "rules": [ - { "mdmh": "htc/*/Nexus 9/*" }, - { "ua": "Nexus 9" } - ], - "dpi": 289.0, - "bw": 3, - "ac": 500 - }, - - { - "type": "android", - "rules": [ - { "mdmh": "HTC/*/HTC One M9/*" }, - { "ua": "HTC One M9" } - ], - "dpi": [ 442.5, 443.3 ], - "bw": 3, - "ac": 500 - }, - - { - "type": "android", - "rules": [ - { "mdmh": "HTC/*/HTC One_M8/*" }, - { "ua": "HTC One_M8" } - ], - "dpi": [ 449.7, 447.4 ], - "bw": 3, - "ac": 500 - }, - - { - "type": "android", - "rules": [ - { "mdmh": "HTC/*/HTC One/*" }, - { "ua": "HTC One" } - ], - "dpi": 472.8, - "bw": 3, - "ac": 1000 - }, - - { - "type": "android", - "rules": [ - { "mdmh": "Huawei/*/Nexus 6P/*" }, - { "ua": "Nexus 6P" } - ], - "dpi": [ 515.1, 518.0 ], - "bw": 3, - "ac": 1000 - }, - - { - "type": "android", - "rules": [ - { "mdmh": "LGE/*/Nexus 5X/*" }, - { "ua": "Nexus 5X" } - ], - "dpi": [ 422.0, 419.9 ], - "bw": 3, - "ac": 1000 - }, - - { - "type": "android", - "rules": [ - { "mdmh": "LGE/*/LGMS345/*" }, - { "ua": "LGMS345" } - ], - "dpi": [ 221.7, 219.1 ], - "bw": 3, - "ac": 500 - }, - - { - "type": "android", - "rules": [ - { "mdmh": "LGE/*/LG-D800/*" }, - { "ua": "LG-D800" } - ], - "dpi": [ 422.0, 424.1 ], - "bw": 3, - "ac": 500 - }, - - { - "type": "android", - "rules": [ - { "mdmh": "LGE/*/LG-D850/*" }, - { "ua": "LG-D850" } - ], - "dpi": [ 537.9, 541.9 ], - "bw": 3, - "ac": 500 - }, - - { - "type": "android", - "rules": [ - { "mdmh": "LGE/*/VS985 4G/*" }, - { "ua": "VS985 4G" } - ], - "dpi": [ 537.9, 535.6 ], - "bw": 3, - "ac": 1000 - }, - - { - "type": "android", - "rules": [ - { "mdmh": "LGE/*/Nexus 5/*" }, - { "ua": "Nexus 5 " } - ], - "dpi": [ 442.4, 444.8 ], - "bw": 3, - "ac": 1000 - }, - - { - "type": "android", - "rules": [ - { "mdmh": "LGE/*/Nexus 4/*" }, - { "ua": "Nexus 4" } - ], - "dpi": [ 319.8, 318.4 ], - "bw": 3, - "ac": 1000 - }, - - { - "type": "android", - "rules": [ - { "mdmh": "LGE/*/LG-P769/*" }, - { "ua": "LG-P769" } - ], - "dpi": [ 240.6, 247.5 ], - "bw": 3, - "ac": 1000 - }, - - { - "type": "android", - "rules": [ - { "mdmh": "LGE/*/LGMS323/*" }, - { "ua": "LGMS323" } - ], - "dpi": [ 206.6, 204.6 ], - "bw": 3, - "ac": 1000 - }, - - { - "type": "android", - "rules": [ - { "mdmh": "LGE/*/LGLS996/*" }, - { "ua": "LGLS996" } - ], - "dpi": [ 403.4, 401.5 ], - "bw": 3, - "ac": 1000 - }, - - { - "type": "android", - "rules": [ - { "mdmh": "Micromax/*/4560MMX/*" }, - { "ua": "4560MMX" } - ], - "dpi": [ 240.0, 219.4 ], - "bw": 3, - "ac": 1000 - }, - - { - "type": "android", - "rules": [ - { "mdmh": "Micromax/*/A250/*" }, - { "ua": "Micromax A250" } - ], - "dpi": [ 480.0, 446.4 ], - "bw": 3, - "ac": 1000 - }, - - { - "type": "android", - "rules": [ - { "mdmh": "Micromax/*/Micromax AQ4501/*" }, - { "ua": "Micromax AQ4501" } - ], - "dpi": 240.0, - "bw": 3, - "ac": 500 - }, - - { - "type": "android", - "rules": [ - { "mdmh": "motorola/*/DROID RAZR/*" }, - { "ua": "DROID RAZR" } - ], - "dpi": [ 368.1, 256.7 ], - "bw": 3, - "ac": 1000 - }, - - { - "type": "android", - "rules": [ - { "mdmh": "motorola/*/XT830C/*" }, - { "ua": "XT830C" } - ], - "dpi": [ 254.0, 255.9 ], - "bw": 3, - "ac": 1000 - }, - - { - "type": "android", - "rules": [ - { "mdmh": "motorola/*/XT1021/*" }, - { "ua": "XT1021" } - ], - "dpi": [ 254.0, 256.7 ], - "bw": 3, - "ac": 500 - }, - - { - "type": "android", - "rules": [ - { "mdmh": "motorola/*/XT1023/*" }, - { "ua": "XT1023" } - ], - "dpi": [ 254.0, 256.7 ], - "bw": 3, - "ac": 500 - }, - - { - "type": "android", - "rules": [ - { "mdmh": "motorola/*/XT1028/*" }, - { "ua": "XT1028" } - ], - "dpi": [ 326.6, 327.6 ], - "bw": 3, - "ac": 1000 - }, - - { - "type": "android", - "rules": [ - { "mdmh": "motorola/*/XT1034/*" }, - { "ua": "XT1034" } - ], - "dpi": [ 326.6, 328.4 ], - "bw": 3, - "ac": 500 - }, - - { - "type": "android", - "rules": [ - { "mdmh": "motorola/*/XT1053/*" }, - { "ua": "XT1053" } - ], - "dpi": [ 315.3, 316.1 ], - "bw": 3, - "ac": 1000 - }, - - { - "type": "android", - "rules": [ - { "mdmh": "motorola/*/XT1562/*" }, - { "ua": "XT1562" } - ], - "dpi": [ 403.4, 402.7 ], - "bw": 3, - "ac": 1000 - }, - - { - "type": "android", - "rules": [ - { "mdmh": "motorola/*/Nexus 6/*" }, - { "ua": "Nexus 6 " } - ], - "dpi": [ 494.3, 489.7 ], - "bw": 3, - "ac": 1000 - }, - - { - "type": "android", - "rules": [ - { "mdmh": "motorola/*/XT1063/*" }, - { "ua": "XT1063" } - ], - "dpi": [ 295.0, 296.6 ], - "bw": 3, - "ac": 1000 - }, - - { - "type": "android", - "rules": [ - { "mdmh": "motorola/*/XT1064/*" }, - { "ua": "XT1064" } - ], - "dpi": [ 295.0, 295.6 ], - "bw": 3, - "ac": 500 - }, - - { - "type": "android", - "rules": [ - { "mdmh": "motorola/*/XT1092/*" }, - { "ua": "XT1092" } - ], - "dpi": [ 422.0, 424.1 ], - "bw": 3, - "ac": 500 - }, - - { - "type": "android", - "rules": [ - { "mdmh": "motorola/*/XT1095/*" }, - { "ua": "XT1095" } - ], - "dpi": [ 422.0, 423.4 ], - "bw": 3, - "ac": 1000 - }, - - { - "type": "android", - "rules": [ - { "mdmh": "OnePlus/*/A0001/*" }, - { "ua": "A0001" } - ], - "dpi": [ 403.4, 401.0 ], - "bw": 3, - "ac": 1000 - }, - - { - "type": "android", - "rules": [ - { "mdmh": "OnePlus/*/ONE E1005/*" }, - { "ua": "ONE E1005" } - ], - "dpi": [ 442.4, 441.4 ], - "bw": 3, - "ac": 1000 - }, - - { - "type": "android", - "rules": [ - { "mdmh": "OnePlus/*/ONE A2005/*" }, - { "ua": "ONE A2005" } - ], - "dpi": [ 391.9, 405.4 ], - "bw": 3, - "ac": 1000 - }, - - { - "type": "android", - "rules": [ - { "mdmh": "OPPO/*/X909/*" }, - { "ua": "X909" } - ], - "dpi": [ 442.4, 444.1 ], - "bw": 3, - "ac": 1000 - }, - - { - "type": "android", - "rules": [ - { "mdmh": "samsung/*/GT-I9082/*" }, - { "ua": "GT-I9082" } - ], - "dpi": [ 184.7, 185.4 ], - "bw": 3, - "ac": 1000 - }, - - { - "type": "android", - "rules": [ - { "mdmh": "samsung/*/SM-G360P/*" }, - { "ua": "SM-G360P" } - ], - "dpi": [ 196.7, 205.4 ], - "bw": 3, - "ac": 1000 - }, - - { - "type": "android", - "rules": [ - { "mdmh": "samsung/*/Nexus S/*" }, - { "ua": "Nexus S" } - ], - "dpi": [ 234.5, 229.8 ], - "bw": 3, - "ac": 1000 - }, - - { - "type": "android", - "rules": [ - { "mdmh": "samsung/*/GT-I9300/*" }, - { "ua": "GT-I9300" } - ], - "dpi": [ 304.8, 303.9 ], - "bw": 5, - "ac": 500 - }, - - { - "type": "android", - "rules": [ - { "mdmh": "samsung/*/SM-T230NU/*" }, - { "ua": "SM-T230NU" } - ], - "dpi": 216.0, - "bw": 3, - "ac": 500 - }, - - { - "type": "android", - "rules": [ - { "mdmh": "samsung/*/SGH-T399/*" }, - { "ua": "SGH-T399" } - ], - "dpi": [ 217.7, 231.4 ], - "bw": 3, - "ac": 1000 - }, - - { - "type": "android", - "rules": [ - { "mdmh": "samsung/*/SM-N9005/*" }, - { "ua": "SM-N9005" } - ], - "dpi": [ 386.4, 387.0 ], - "bw": 3, - "ac": 500 - }, - - { - "type": "android", - "rules": [ - { "mdmh": "samsung/*/SAMSUNG-SM-N900A/*" }, - { "ua": "SAMSUNG-SM-N900A" } - ], - "dpi": [ 386.4, 387.7 ], - "bw": 3, - "ac": 1000 - }, - - { - "type": "android", - "rules": [ - { "mdmh": "samsung/*/GT-I9500/*" }, - { "ua": "GT-I9500" } - ], - "dpi": [ 442.5, 443.3 ], - "bw": 3, - "ac": 500 - }, - - { - "type": "android", - "rules": [ - { "mdmh": "samsung/*/GT-I9505/*" }, - { "ua": "GT-I9505" } - ], - "dpi": 439.4, - "bw": 4, - "ac": 1000 - }, - - { - "type": "android", - "rules": [ - { "mdmh": "samsung/*/SM-G900F/*" }, - { "ua": "SM-G900F" } - ], - "dpi": [ 415.6, 431.6 ], - "bw": 5, - "ac": 1000 - }, - - { - "type": "android", - "rules": [ - { "mdmh": "samsung/*/SM-G900M/*" }, - { "ua": "SM-G900M" } - ], - "dpi": [ 415.6, 431.6 ], - "bw": 5, - "ac": 1000 - }, - - { - "type": "android", - "rules": [ - { "mdmh": "samsung/*/SM-G800F/*" }, - { "ua": "SM-G800F" } - ], - "dpi": 326.8, - "bw": 3, - "ac": 1000 - }, - - { - "type": "android", - "rules": [ - { "mdmh": "samsung/*/SM-G906S/*" }, - { "ua": "SM-G906S" } - ], - "dpi": [ 562.7, 572.4 ], - "bw": 3, - "ac": 1000 - }, - - { - "type": "android", - "rules": [ - { "mdmh": "samsung/*/GT-I9300/*" }, - { "ua": "GT-I9300" } - ], - "dpi": [ 306.7, 304.8 ], - "bw": 5, - "ac": 1000 - }, - - { - "type": "android", - "rules": [ - { "mdmh": "samsung/*/SM-T535/*" }, - { "ua": "SM-T535" } - ], - "dpi": [ 142.6, 136.4 ], - "bw": 3, - "ac": 500 - }, - - { - "type": "android", - "rules": [ - { "mdmh": "samsung/*/SM-N920C/*" }, - { "ua": "SM-N920C" } - ], - "dpi": [ 515.1, 518.4 ], - "bw": 3, - "ac": 1000 - }, - - { - "type": "android", - "rules": [ - { "mdmh": "samsung/*/GT-I9300I/*" }, - { "ua": "GT-I9300I" } - ], - "dpi": [ 304.8, 305.8 ], - "bw": 3, - "ac": 1000 - }, - - { - "type": "android", - "rules": [ - { "mdmh": "samsung/*/GT-I9195/*" }, - { "ua": "GT-I9195" } - ], - "dpi": [ 249.4, 256.7 ], - "bw": 3, - "ac": 500 - }, - - { - "type": "android", - "rules": [ - { "mdmh": "samsung/*/SPH-L520/*" }, - { "ua": "SPH-L520" } - ], - "dpi": [ 249.4, 255.9 ], - "bw": 3, - "ac": 1000 - }, - - { - "type": "android", - "rules": [ - { "mdmh": "samsung/*/SAMSUNG-SGH-I717/*" }, - { "ua": "SAMSUNG-SGH-I717" } - ], - "dpi": 285.8, - "bw": 3, - "ac": 1000 - }, - - { - "type": "android", - "rules": [ - { "mdmh": "samsung/*/SPH-D710/*" }, - { "ua": "SPH-D710" } - ], - "dpi": [ 217.7, 204.2 ], - "bw": 3, - "ac": 1000 - }, - - { - "type": "android", - "rules": [ - { "mdmh": "samsung/*/GT-N7100/*" }, - { "ua": "GT-N7100" } - ], - "dpi": 265.1, - "bw": 3, - "ac": 1000 - }, - - { - "type": "android", - "rules": [ - { "mdmh": "samsung/*/SCH-I605/*" }, - { "ua": "SCH-I605" } - ], - "dpi": 265.1, - "bw": 3, - "ac": 1000 - }, - - { - "type": "android", - "rules": [ - { "mdmh": "samsung/*/Galaxy Nexus/*" }, - { "ua": "Galaxy Nexus" } - ], - "dpi": [ 315.3, 314.2 ], - "bw": 3, - "ac": 1000 - }, - - { - "type": "android", - "rules": [ - { "mdmh": "samsung/*/SM-N910H/*" }, - { "ua": "SM-N910H" } - ], - "dpi": [ 515.1, 518.0 ], - "bw": 3, - "ac": 1000 - }, - - { - "type": "android", - "rules": [ - { "mdmh": "samsung/*/SM-N910C/*" }, - { "ua": "SM-N910C" } - ], - "dpi": [ 515.2, 520.2 ], - "bw": 3, - "ac": 500 - }, - - { - "type": "android", - "rules": [ - { "mdmh": "samsung/*/SM-G130M/*" }, - { "ua": "SM-G130M" } - ], - "dpi": [ 165.9, 164.8 ], - "bw": 3, - "ac": 500 - }, - - { - "type": "android", - "rules": [ - { "mdmh": "samsung/*/SM-G928I/*" }, - { "ua": "SM-G928I" } - ], - "dpi": [ 515.1, 518.4 ], - "bw": 3, - "ac": 1000 - }, - - { - "type": "android", - "rules": [ - { "mdmh": "samsung/*/SM-G920F/*" }, - { "ua": "SM-G920F" } - ], - "dpi": 580.6, - "bw": 3, - "ac": 500 - }, - - { - "type": "android", - "rules": [ - { "mdmh": "samsung/*/SM-G920P/*" }, - { "ua": "SM-G920P" } - ], - "dpi": [ 522.5, 577.0 ], - "bw": 3, - "ac": 1000 - }, - - { - "type": "android", - "rules": [ - { "mdmh": "samsung/*/SM-G925F/*" }, - { "ua": "SM-G925F" } - ], - "dpi": 580.6, - "bw": 3, - "ac": 500 - }, - - { - "type": "android", - "rules": [ - { "mdmh": "samsung/*/SM-G925V/*" }, - { "ua": "SM-G925V" } - ], - "dpi": [ 522.5, 576.6 ], - "bw": 3, - "ac": 1000 - }, - - { - "type": "android", - "rules": [ - { "mdmh": "Sony/*/C6903/*" }, - { "ua": "C6903" } - ], - "dpi": [ 442.5, 443.3 ], - "bw": 3, - "ac": 500 - }, - - { - "type": "android", - "rules": [ - { "mdmh": "Sony/*/D6653/*" }, - { "ua": "D6653" } - ], - "dpi": [ 428.6, 427.6 ], - "bw": 3, - "ac": 1000 - }, - - { - "type": "android", - "rules": [ - { "mdmh": "Sony/*/E6653/*" }, - { "ua": "E6653" } - ], - "dpi": [ 428.6, 425.7 ], - "bw": 3, - "ac": 1000 - }, - - { - "type": "android", - "rules": [ - { "mdmh": "Sony/*/E6853/*" }, - { "ua": "E6853" } - ], - "dpi": [ 403.4, 401.9 ], - "bw": 3, - "ac": 1000 - }, - - { - "type": "android", - "rules": [ - { "mdmh": "Sony/*/SGP321/*" }, - { "ua": "SGP321" } - ], - "dpi": [ 224.7, 224.1 ], - "bw": 3, - "ac": 500 - }, - - { - "type": "android", - "rules": [ - { "mdmh": "TCT/*/ALCATEL ONE TOUCH Fierce/*" }, - { "ua": "ALCATEL ONE TOUCH Fierce" } - ], - "dpi": [ 240.0, 247.5 ], - "bw": 3, - "ac": 1000 - }, - - { - "type": "android", - "rules": [ - { "mdmh": "THL/*/thl 5000/*" }, - { "ua": "thl 5000" } - ], - "dpi": [ 480.0, 443.3 ], - "bw": 3, - "ac": 1000 - }, - - { - "type": "android", - "rules": [ - { "mdmh": "ZTE/*/ZTE Blade L2/*" }, - { "ua": "ZTE Blade L2" } - ], - "dpi": 240.0, - "bw": 3, - "ac": 500 - }, - - { - "type": "ios", - "rules": [ { "res": [ 640, 960 ] } ], - "dpi": [ 325.1, 328.4 ], - "bw": 4, - "ac": 1000 - }, - - { - "type": "ios", - "rules": [ { "res": [ 640, 960 ] } ], - "dpi": [ 325.1, 328.4 ], - "bw": 4, - "ac": 1000 - }, - - { - "type": "ios", - "rules": [ { "res": [ 640, 1136 ] } ], - "dpi": [ 317.1, 320.2 ], - "bw": 3, - "ac": 1000 - }, - - { - "type": "ios", - "rules": [ { "res": [ 640, 1136 ] } ], - "dpi": [ 317.1, 320.2 ], - "bw": 3, - "ac": 1000 - }, - - { - "type": "ios", - "rules": [ { "res": [ 750, 1334 ] } ], - "dpi": 326.4, - "bw": 4, - "ac": 1000 - }, - - { - "type": "ios", - "rules": [ { "res": [ 750, 1334 ] } ], - "dpi": 326.4, - "bw": 4, - "ac": 1000 - }, - - { - "type": "ios", - "rules": [ { "res": [ 1242, 2208 ] } ], - "dpi": [ 453.6, 458.4 ], - "bw": 4, - "ac": 1000 - }, - - { - "type": "ios", - "rules": [ { "res": [ 1242, 2208 ] } ], - "dpi": [ 453.6, 458.4 ], - "bw": 4, - "ac": 1000 - } -]}; - -module.exports = DPDB_CACHE; - -},{}],11:[function(_dereq_,module,exports){ -/* - * Copyright 2015 Google Inc. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -// Offline cache of the DPDB, to be used until we load the online one (and -// as a fallback in case we can't load the online one). -var DPDB_CACHE = _dereq_('./dpdb-cache.js'); -var Util = _dereq_('../util.js'); - -// Online DPDB URL. -var ONLINE_DPDB_URL = 'https://storage.googleapis.com/cardboard-dpdb/dpdb.json'; - -/** - * Calculates device parameters based on the DPDB (Device Parameter Database). - * Initially, uses the cached DPDB values. - * - * If fetchOnline == true, then this object tries to fetch the online version - * of the DPDB and updates the device info if a better match is found. - * Calls the onDeviceParamsUpdated callback when there is an update to the - * device information. - */ -function Dpdb(fetchOnline, onDeviceParamsUpdated) { - // Start with the offline DPDB cache while we are loading the real one. - this.dpdb = DPDB_CACHE; - - // Calculate device params based on the offline version of the DPDB. - this.recalculateDeviceParams_(); - - // XHR to fetch online DPDB file, if requested. - if (fetchOnline) { - // Set the callback. - this.onDeviceParamsUpdated = onDeviceParamsUpdated; - - console.log('Fetching DPDB...'); - var xhr = new XMLHttpRequest(); - var obj = this; - xhr.open('GET', ONLINE_DPDB_URL, true); - xhr.addEventListener('load', function() { - obj.loading = false; - if (xhr.status >= 200 && xhr.status <= 299) { - // Success. - console.log('Successfully loaded online DPDB.'); - obj.dpdb = JSON.parse(xhr.response); - obj.recalculateDeviceParams_(); - } else { - // Error loading the DPDB. - console.error('Error loading online DPDB!'); - } - }); - xhr.send(); - } -} - -// Returns the current device parameters. -Dpdb.prototype.getDeviceParams = function() { - return this.deviceParams; -}; - -// Recalculates this device's parameters based on the DPDB. -Dpdb.prototype.recalculateDeviceParams_ = function() { - console.log('Recalculating device params.'); - var newDeviceParams = this.calcDeviceParams_(); - console.log('New device parameters:'); - console.log(newDeviceParams); - if (newDeviceParams) { - this.deviceParams = newDeviceParams; - // Invoke callback, if it is set. - if (this.onDeviceParamsUpdated) { - this.onDeviceParamsUpdated(this.deviceParams); - } - } else { - console.error('Failed to recalculate device parameters.'); - } -}; - -// Returns a DeviceParams object that represents the best guess as to this -// device's parameters. Can return null if the device does not match any -// known devices. -Dpdb.prototype.calcDeviceParams_ = function() { - var db = this.dpdb; // shorthand - if (!db) { - console.error('DPDB not available.'); - return null; - } - if (db.format != 1) { - console.error('DPDB has unexpected format version.'); - return null; - } - if (!db.devices || !db.devices.length) { - console.error('DPDB does not have a devices section.'); - return null; - } - - // Get the actual user agent and screen dimensions in pixels. - var userAgent = navigator.userAgent || navigator.vendor || window.opera; - var width = Util.getScreenWidth(); - var height = Util.getScreenHeight(); - console.log('User agent: ' + userAgent); - console.log('Pixel width: ' + width); - console.log('Pixel height: ' + height); - - if (!db.devices) { - console.error('DPDB has no devices section.'); - return null; - } - - for (var i = 0; i < db.devices.length; i++) { - var device = db.devices[i]; - if (!device.rules) { - console.warn('Device[' + i + '] has no rules section.'); - continue; - } - - if (device.type != 'ios' && device.type != 'android') { - console.warn('Device[' + i + '] has invalid type.'); - continue; - } - - // See if this device is of the appropriate type. - if (Util.isIOS() != (device.type == 'ios')) continue; - - // See if this device matches any of the rules: - var matched = false; - for (var j = 0; j < device.rules.length; j++) { - var rule = device.rules[j]; - if (this.matchRule_(rule, userAgent, width, height)) { - console.log('Rule matched:'); - console.log(rule); - matched = true; - break; - } - } - if (!matched) continue; - - // device.dpi might be an array of [ xdpi, ydpi] or just a scalar. - var xdpi = device.dpi[0] || device.dpi; - var ydpi = device.dpi[1] || device.dpi; - - return new DeviceParams({ xdpi: xdpi, ydpi: ydpi, bevelMm: device.bw }); - } - - console.warn('No DPDB device match.'); - return null; -}; - -Dpdb.prototype.matchRule_ = function(rule, ua, screenWidth, screenHeight) { - // We can only match 'ua' and 'res' rules, not other types like 'mdmh' - // (which are meant for native platforms). - if (!rule.ua && !rule.res) return false; - - // If our user agent string doesn't contain the indicated user agent string, - // the match fails. - if (rule.ua && ua.indexOf(rule.ua) < 0) return false; - - // If the rule specifies screen dimensions that don't correspond to ours, - // the match fails. - if (rule.res) { - if (!rule.res[0] || !rule.res[1]) return false; - var resX = rule.res[0]; - var resY = rule.res[1]; - // Compare min and max so as to make the order not matter, i.e., it should - // be true that 640x480 == 480x640. - if (Math.min(screenWidth, screenHeight) != Math.min(resX, resY) || - (Math.max(screenWidth, screenHeight) != Math.max(resX, resY))) { - return false; - } - } - - return true; -} - -function DeviceParams(params) { - this.xdpi = params.xdpi; - this.ydpi = params.ydpi; - this.bevelMm = params.bevelMm; -} - -module.exports = Dpdb; -},{"../util.js":22,"./dpdb-cache.js":10}],12:[function(_dereq_,module,exports){ -/* - * Copyright 2015 Google Inc. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -function Emitter() { - this.callbacks = {}; -} - -Emitter.prototype.emit = function(eventName) { - var callbacks = this.callbacks[eventName]; - if (!callbacks) { - //console.log('No valid callback specified.'); - return; - } - var args = [].slice.call(arguments); - // Eliminate the first param (the callback). - args.shift(); - for (var i = 0; i < callbacks.length; i++) { - callbacks[i].apply(this, args); - } -}; - -Emitter.prototype.on = function(eventName, callback) { - if (eventName in this.callbacks) { - this.callbacks[eventName].push(callback); - } else { - this.callbacks[eventName] = [callback]; - } -}; - -module.exports = Emitter; - -},{}],13:[function(_dereq_,module,exports){ -/* - * Copyright 2015 Google Inc. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -var Util = _dereq_('./util.js'); -var WebVRPolyfill = _dereq_('./webvr-polyfill.js').WebVRPolyfill; -var InstallWebVRSpecShim = _dereq_('./webvr-polyfill.js').InstallWebVRSpecShim; - -// Initialize a WebVRConfig just in case. -window.WebVRConfig = Util.extend({ - // Forces availability of VR mode, even for non-mobile devices. - FORCE_ENABLE_VR: false, - - // Complementary filter coefficient. 0 for accelerometer, 1 for gyro. - K_FILTER: 0.98, - - // How far into the future to predict during fast motion (in seconds). - PREDICTION_TIME_S: 0.040, - - // Flag to disable touch panner. In case you have your own touch controls. - TOUCH_PANNER_DISABLED: false, - - // Flag to disabled the UI in VR Mode. - CARDBOARD_UI_DISABLED: false, // Default: false - - // Flag to disable the instructions to rotate your device. - ROTATE_INSTRUCTIONS_DISABLED: false, // Default: false. - - // Enable yaw panning only, disabling roll and pitch. This can be useful - // for panoramas with nothing interesting above or below. - YAW_ONLY: false, - - // To disable keyboard and mouse controls, if you want to use your own - // implementation. - MOUSE_KEYBOARD_CONTROLS_DISABLED: false, - - // Prevent the polyfill from initializing immediately. Requires the app - // to call InitializeWebVRPolyfill() before it can be used. - DEFER_INITIALIZATION: false, - - // Enable the deprecated version of the API (navigator.getVRDevices). - ENABLE_DEPRECATED_API: false, - - // Scales the recommended buffer size reported by WebVR, which can improve - // performance. - // UPDATE(2016-05-03): Setting this to 0.5 by default since 1.0 does not - // perform well on many mobile devices. - BUFFER_SCALE: 0.5, - - // Allow VRDisplay.submitFrame to change gl bindings, which is more - // efficient if the application code will re-bind its resources on the - // next frame anyway. This has been seen to cause rendering glitches with - // THREE.js. - // Dirty bindings include: gl.FRAMEBUFFER_BINDING, gl.CURRENT_PROGRAM, - // gl.ARRAY_BUFFER_BINDING, gl.ELEMENT_ARRAY_BUFFER_BINDING, - // and gl.TEXTURE_BINDING_2D for texture unit 0. - DIRTY_SUBMIT_FRAME_BINDINGS: false -}, window.WebVRConfig); - -if (!window.WebVRConfig.DEFER_INITIALIZATION) { - new WebVRPolyfill(); -} else { - window.InitializeWebVRPolyfill = function() { - new WebVRPolyfill(); - } - // Call this if you want to use the shim without the rest of the polyfill. - // InitializeWebVRPolyfill() will install the shim automatically when needed, - // so this should rarely be used. - window.InitializeSpecShim = function() { - InstallWebVRSpecShim(); - } -} - -},{"./util.js":22,"./webvr-polyfill.js":25}],14:[function(_dereq_,module,exports){ -/* - * Copyright 2016 Google Inc. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -var MathUtil = window.MathUtil || {}; - -MathUtil.degToRad = Math.PI / 180; -MathUtil.radToDeg = 180 / Math.PI; - -// Some minimal math functionality borrowed from THREE.Math and stripped down -// for the purposes of this library. - - -MathUtil.Vector2 = function ( x, y ) { - this.x = x || 0; - this.y = y || 0; -}; - -MathUtil.Vector2.prototype = { - constructor: MathUtil.Vector2, - - set: function ( x, y ) { - this.x = x; - this.y = y; - - return this; - }, - - copy: function ( v ) { - this.x = v.x; - this.y = v.y; - - return this; - }, - - subVectors: function ( a, b ) { - this.x = a.x - b.x; - this.y = a.y - b.y; - - return this; - }, -}; - -MathUtil.Vector3 = function ( x, y, z ) { - this.x = x || 0; - this.y = y || 0; - this.z = z || 0; -}; - -MathUtil.Vector3.prototype = { - constructor: MathUtil.Vector3, - - set: function ( x, y, z ) { - this.x = x; - this.y = y; - this.z = z; - - return this; - }, - - copy: function ( v ) { - this.x = v.x; - this.y = v.y; - this.z = v.z; - - return this; - }, - - length: function () { - return Math.sqrt( this.x * this.x + this.y * this.y + this.z * this.z ); - }, - - normalize: function () { - var scalar = this.length(); - - if ( scalar !== 0 ) { - var invScalar = 1 / scalar; - - this.multiplyScalar(invScalar); - } else { - this.x = 0; - this.y = 0; - this.z = 0; - } - - return this; - }, - - multiplyScalar: function ( scalar ) { - this.x *= scalar; - this.y *= scalar; - this.z *= scalar; - }, - - applyQuaternion: function ( q ) { - var x = this.x; - var y = this.y; - var z = this.z; - - var qx = q.x; - var qy = q.y; - var qz = q.z; - var qw = q.w; - - // calculate quat * vector - var ix = qw * x + qy * z - qz * y; - var iy = qw * y + qz * x - qx * z; - var iz = qw * z + qx * y - qy * x; - var iw = - qx * x - qy * y - qz * z; - - // calculate result * inverse quat - this.x = ix * qw + iw * - qx + iy * - qz - iz * - qy; - this.y = iy * qw + iw * - qy + iz * - qx - ix * - qz; - this.z = iz * qw + iw * - qz + ix * - qy - iy * - qx; - - return this; - }, - - dot: function ( v ) { - return this.x * v.x + this.y * v.y + this.z * v.z; - }, - - crossVectors: function ( a, b ) { - var ax = a.x, ay = a.y, az = a.z; - var bx = b.x, by = b.y, bz = b.z; - - this.x = ay * bz - az * by; - this.y = az * bx - ax * bz; - this.z = ax * by - ay * bx; - - return this; - }, -}; - -MathUtil.Quaternion = function ( x, y, z, w ) { - this.x = x || 0; - this.y = y || 0; - this.z = z || 0; - this.w = ( w !== undefined ) ? w : 1; -}; - -MathUtil.Quaternion.prototype = { - constructor: MathUtil.Quaternion, - - set: function ( x, y, z, w ) { - this.x = x; - this.y = y; - this.z = z; - this.w = w; - - return this; - }, - - copy: function ( quaternion ) { - this.x = quaternion.x; - this.y = quaternion.y; - this.z = quaternion.z; - this.w = quaternion.w; - - return this; - }, - - setFromEulerXYZ: function( x, y, z ) { - var c1 = Math.cos( x / 2 ); - var c2 = Math.cos( y / 2 ); - var c3 = Math.cos( z / 2 ); - var s1 = Math.sin( x / 2 ); - var s2 = Math.sin( y / 2 ); - var s3 = Math.sin( z / 2 ); - - this.x = s1 * c2 * c3 + c1 * s2 * s3; - this.y = c1 * s2 * c3 - s1 * c2 * s3; - this.z = c1 * c2 * s3 + s1 * s2 * c3; - this.w = c1 * c2 * c3 - s1 * s2 * s3; - - return this; - }, - - setFromEulerYXZ: function( x, y, z ) { - var c1 = Math.cos( x / 2 ); - var c2 = Math.cos( y / 2 ); - var c3 = Math.cos( z / 2 ); - var s1 = Math.sin( x / 2 ); - var s2 = Math.sin( y / 2 ); - var s3 = Math.sin( z / 2 ); - - this.x = s1 * c2 * c3 + c1 * s2 * s3; - this.y = c1 * s2 * c3 - s1 * c2 * s3; - this.z = c1 * c2 * s3 - s1 * s2 * c3; - this.w = c1 * c2 * c3 + s1 * s2 * s3; - - return this; - }, - - setFromAxisAngle: function ( axis, angle ) { - // http://www.euclideanspace.com/maths/geometry/rotations/conversions/angleToQuaternion/index.htm - // assumes axis is normalized - - var halfAngle = angle / 2, s = Math.sin( halfAngle ); - - this.x = axis.x * s; - this.y = axis.y * s; - this.z = axis.z * s; - this.w = Math.cos( halfAngle ); - - return this; - }, - - multiply: function ( q ) { - return this.multiplyQuaternions( this, q ); - }, - - multiplyQuaternions: function ( a, b ) { - // from http://www.euclideanspace.com/maths/algebra/realNormedAlgebra/quaternions/code/index.htm - - var qax = a.x, qay = a.y, qaz = a.z, qaw = a.w; - var qbx = b.x, qby = b.y, qbz = b.z, qbw = b.w; - - this.x = qax * qbw + qaw * qbx + qay * qbz - qaz * qby; - this.y = qay * qbw + qaw * qby + qaz * qbx - qax * qbz; - this.z = qaz * qbw + qaw * qbz + qax * qby - qay * qbx; - this.w = qaw * qbw - qax * qbx - qay * qby - qaz * qbz; - - return this; - }, - - inverse: function () { - this.x *= -1; - this.y *= -1; - this.z *= -1; - - this.normalize(); - - return this; - }, - - normalize: function () { - var l = Math.sqrt( this.x * this.x + this.y * this.y + this.z * this.z + this.w * this.w ); - - if ( l === 0 ) { - this.x = 0; - this.y = 0; - this.z = 0; - this.w = 1; - } else { - l = 1 / l; - - this.x = this.x * l; - this.y = this.y * l; - this.z = this.z * l; - this.w = this.w * l; - } - - return this; - }, - - slerp: function ( qb, t ) { - if ( t === 0 ) return this; - if ( t === 1 ) return this.copy( qb ); - - var x = this.x, y = this.y, z = this.z, w = this.w; - - // http://www.euclideanspace.com/maths/algebra/realNormedAlgebra/quaternions/slerp/ - - var cosHalfTheta = w * qb.w + x * qb.x + y * qb.y + z * qb.z; - - if ( cosHalfTheta < 0 ) { - this.w = - qb.w; - this.x = - qb.x; - this.y = - qb.y; - this.z = - qb.z; - - cosHalfTheta = - cosHalfTheta; - } else { - this.copy( qb ); - } - - if ( cosHalfTheta >= 1.0 ) { - this.w = w; - this.x = x; - this.y = y; - this.z = z; - - return this; - } - - var halfTheta = Math.acos( cosHalfTheta ); - var sinHalfTheta = Math.sqrt( 1.0 - cosHalfTheta * cosHalfTheta ); - - if ( Math.abs( sinHalfTheta ) < 0.001 ) { - this.w = 0.5 * ( w + this.w ); - this.x = 0.5 * ( x + this.x ); - this.y = 0.5 * ( y + this.y ); - this.z = 0.5 * ( z + this.z ); - - return this; - } - - var ratioA = Math.sin( ( 1 - t ) * halfTheta ) / sinHalfTheta, - ratioB = Math.sin( t * halfTheta ) / sinHalfTheta; - - this.w = ( w * ratioA + this.w * ratioB ); - this.x = ( x * ratioA + this.x * ratioB ); - this.y = ( y * ratioA + this.y * ratioB ); - this.z = ( z * ratioA + this.z * ratioB ); - - return this; - }, - - setFromUnitVectors: function () { - // http://lolengine.net/blog/2014/02/24/quaternion-from-two-vectors-final - // assumes direction vectors vFrom and vTo are normalized - - var v1, r; - var EPS = 0.000001; - - return function ( vFrom, vTo ) { - if ( v1 === undefined ) v1 = new MathUtil.Vector3(); - - r = vFrom.dot( vTo ) + 1; - - if ( r < EPS ) { - r = 0; - - if ( Math.abs( vFrom.x ) > Math.abs( vFrom.z ) ) { - v1.set( - vFrom.y, vFrom.x, 0 ); - } else { - v1.set( 0, - vFrom.z, vFrom.y ); - } - } else { - v1.crossVectors( vFrom, vTo ); - } - - this.x = v1.x; - this.y = v1.y; - this.z = v1.z; - this.w = r; - - this.normalize(); - - return this; - } - }(), -}; - -module.exports = MathUtil; - -},{}],15:[function(_dereq_,module,exports){ -/* - * Copyright 2016 Google Inc. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -var VRDisplay = _dereq_('./base.js').VRDisplay; -var MathUtil = _dereq_('./math-util.js'); -var Util = _dereq_('./util.js'); - -// How much to rotate per key stroke. -var KEY_SPEED = 0.15; -var KEY_ANIMATION_DURATION = 80; - -// How much to rotate for mouse events. -var MOUSE_SPEED_X = 0.5; -var MOUSE_SPEED_Y = 0.3; - -/** - * VRDisplay based on mouse and keyboard input. Designed for desktops/laptops - * where orientation events aren't supported. Cannot present. - */ -function MouseKeyboardVRDisplay() { - this.displayName = 'Mouse and Keyboard VRDisplay (webvr-polyfill)'; - - this.capabilities.hasOrientation = true; - - // Attach to mouse and keyboard events. - window.addEventListener('keydown', this.onKeyDown_.bind(this)); - window.addEventListener('mousemove', this.onMouseMove_.bind(this)); - window.addEventListener('mousedown', this.onMouseDown_.bind(this)); - window.addEventListener('mouseup', this.onMouseUp_.bind(this)); - - // "Private" members. - this.phi_ = 0; - this.theta_ = 0; - - // Variables for keyboard-based rotation animation. - this.targetAngle_ = null; - this.angleAnimation_ = null; - - // State variables for calculations. - this.orientation_ = new MathUtil.Quaternion(); - - // Variables for mouse-based rotation. - this.rotateStart_ = new MathUtil.Vector2(); - this.rotateEnd_ = new MathUtil.Vector2(); - this.rotateDelta_ = new MathUtil.Vector2(); - this.isDragging_ = false; - - this.orientationOut_ = new Float32Array(4); -} -MouseKeyboardVRDisplay.prototype = new VRDisplay(); - -MouseKeyboardVRDisplay.prototype.getImmediatePose = function() { - this.orientation_.setFromEulerYXZ(this.phi_, this.theta_, 0); - - this.orientationOut_[0] = this.orientation_.x; - this.orientationOut_[1] = this.orientation_.y; - this.orientationOut_[2] = this.orientation_.z; - this.orientationOut_[3] = this.orientation_.w; - - return { - position: null, - orientation: this.orientationOut_, - linearVelocity: null, - linearAcceleration: null, - angularVelocity: null, - angularAcceleration: null - }; -}; - -MouseKeyboardVRDisplay.prototype.onKeyDown_ = function(e) { - // Track WASD and arrow keys. - if (e.keyCode == 38) { // Up key. - this.animatePhi_(this.phi_ + KEY_SPEED); - } else if (e.keyCode == 39) { // Right key. - this.animateTheta_(this.theta_ - KEY_SPEED); - } else if (e.keyCode == 40) { // Down key. - this.animatePhi_(this.phi_ - KEY_SPEED); - } else if (e.keyCode == 37) { // Left key. - this.animateTheta_(this.theta_ + KEY_SPEED); - } -}; - -MouseKeyboardVRDisplay.prototype.animateTheta_ = function(targetAngle) { - this.animateKeyTransitions_('theta_', targetAngle); -}; - -MouseKeyboardVRDisplay.prototype.animatePhi_ = function(targetAngle) { - // Prevent looking too far up or down. - targetAngle = Util.clamp(targetAngle, -Math.PI/2, Math.PI/2); - this.animateKeyTransitions_('phi_', targetAngle); -}; - -/** - * Start an animation to transition an angle from one value to another. - */ -MouseKeyboardVRDisplay.prototype.animateKeyTransitions_ = function(angleName, targetAngle) { - // If an animation is currently running, cancel it. - if (this.angleAnimation_) { - cancelAnimationFrame(this.angleAnimation_); - } - var startAngle = this[angleName]; - var startTime = new Date(); - // Set up an interval timer to perform the animation. - this.angleAnimation_ = requestAnimationFrame(function animate() { - // Once we're finished the animation, we're done. - var elapsed = new Date() - startTime; - if (elapsed >= KEY_ANIMATION_DURATION) { - this[angleName] = targetAngle; - cancelAnimationFrame(this.angleAnimation_); - return; - } - // loop with requestAnimationFrame - this.angleAnimation_ = requestAnimationFrame(animate.bind(this)) - // Linearly interpolate the angle some amount. - var percent = elapsed / KEY_ANIMATION_DURATION; - this[angleName] = startAngle + (targetAngle - startAngle) * percent; - }.bind(this)); -}; - -MouseKeyboardVRDisplay.prototype.onMouseDown_ = function(e) { - this.rotateStart_.set(e.clientX, e.clientY); - this.isDragging_ = true; -}; - -// Very similar to https://gist.github.com/mrflix/8351020 -MouseKeyboardVRDisplay.prototype.onMouseMove_ = function(e) { - if (!this.isDragging_ && !this.isPointerLocked_()) { - return; - } - // Support pointer lock API. - if (this.isPointerLocked_()) { - var movementX = e.movementX || e.mozMovementX || 0; - var movementY = e.movementY || e.mozMovementY || 0; - this.rotateEnd_.set(this.rotateStart_.x - movementX, this.rotateStart_.y - movementY); - } else { - this.rotateEnd_.set(e.clientX, e.clientY); - } - // Calculate how much we moved in mouse space. - this.rotateDelta_.subVectors(this.rotateEnd_, this.rotateStart_); - this.rotateStart_.copy(this.rotateEnd_); - - // Keep track of the cumulative euler angles. - this.phi_ += 2 * Math.PI * this.rotateDelta_.y / screen.height * MOUSE_SPEED_Y; - this.theta_ += 2 * Math.PI * this.rotateDelta_.x / screen.width * MOUSE_SPEED_X; - - // Prevent looking too far up or down. - this.phi_ = Util.clamp(this.phi_, -Math.PI/2, Math.PI/2); -}; - -MouseKeyboardVRDisplay.prototype.onMouseUp_ = function(e) { - this.isDragging_ = false; -}; - -MouseKeyboardVRDisplay.prototype.isPointerLocked_ = function() { - var el = document.pointerLockElement || document.mozPointerLockElement || - document.webkitPointerLockElement; - return el !== undefined; -}; - -MouseKeyboardVRDisplay.prototype.resetPose = function() { - this.phi_ = 0; - this.theta_ = 0; -}; - -module.exports = MouseKeyboardVRDisplay; - -},{"./base.js":2,"./math-util.js":14,"./util.js":22}],16:[function(_dereq_,module,exports){ -/* - * Copyright 2015 Google Inc. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -var Util = _dereq_('./util.js'); - -function RotateInstructions() { - this.loadIcon_(); - - var overlay = document.createElement('div'); - var s = overlay.style; - s.position = 'fixed'; - s.top = 0; - s.right = 0; - s.bottom = 0; - s.left = 0; - s.backgroundColor = 'gray'; - s.fontFamily = 'sans-serif'; - // Force this to be above the fullscreen canvas, which is at zIndex: 999999. - s.zIndex = 1000000; - - var img = document.createElement('img'); - img.src = this.icon; - var s = img.style; - s.marginLeft = '25%'; - s.marginTop = '25%'; - s.width = '50%'; - overlay.appendChild(img); - - var text = document.createElement('div'); - var s = text.style; - s.textAlign = 'center'; - s.fontSize = '16px'; - s.lineHeight = '24px'; - s.margin = '24px 25%'; - s.width = '50%'; - text.innerHTML = 'Place your phone into your Cardboard viewer.'; - overlay.appendChild(text); - - var snackbar = document.createElement('div'); - var s = snackbar.style; - s.backgroundColor = '#CFD8DC'; - s.position = 'fixed'; - s.bottom = 0; - s.width = '100%'; - s.height = '48px'; - s.padding = '14px 24px'; - s.boxSizing = 'border-box'; - s.color = '#656A6B'; - overlay.appendChild(snackbar); - - var snackbarText = document.createElement('div'); - snackbarText.style.float = 'left'; - snackbarText.innerHTML = 'No Cardboard viewer?'; - - var snackbarButton = document.createElement('a'); - snackbarButton.href = 'https://www.google.com/get/cardboard/get-cardboard/'; - snackbarButton.innerHTML = 'get one'; - snackbarButton.target = '_blank'; - var s = snackbarButton.style; - s.float = 'right'; - s.fontWeight = 600; - s.textTransform = 'uppercase'; - s.borderLeft = '1px solid gray'; - s.paddingLeft = '24px'; - s.textDecoration = 'none'; - s.color = '#656A6B'; - - snackbar.appendChild(snackbarText); - snackbar.appendChild(snackbarButton); - - this.overlay = overlay; - this.text = text; - - this.hide(); -} - -RotateInstructions.prototype.show = function(parent) { - if (!parent && !this.overlay.parentElement) { - document.body.appendChild(this.overlay); - } else if (parent) { - if (this.overlay.parentElement && this.overlay.parentElement != parent) - this.overlay.parentElement.removeChild(this.overlay); - - parent.appendChild(this.overlay); - } - - this.overlay.style.display = 'block'; - - var img = this.overlay.querySelector('img'); - var s = img.style; - - if (Util.isLandscapeMode()) { - s.width = '20%'; - s.marginLeft = '40%'; - s.marginTop = '3%'; - } else { - s.width = '50%'; - s.marginLeft = '25%'; - s.marginTop = '25%'; - } -}; - -RotateInstructions.prototype.hide = function() { - this.overlay.style.display = 'none'; -}; - -RotateInstructions.prototype.showTemporarily = function(ms, parent) { - this.show(parent); - this.timer = setTimeout(this.hide.bind(this), ms); -}; - -RotateInstructions.prototype.disableShowTemporarily = function() { - clearTimeout(this.timer); -}; - -RotateInstructions.prototype.update = function() { - this.disableShowTemporarily(); - // In portrait VR mode, tell the user to rotate to landscape. Otherwise, hide - // the instructions. - if (!Util.isLandscapeMode() && Util.isMobile()) { - this.show(); - } else { - this.hide(); - } -}; - -RotateInstructions.prototype.loadIcon_ = function() { - // Encoded asset_src/rotate-instructions.svg - this.icon = Util.base64('image/svg+xml', 'PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiIHN0YW5kYWxvbmU9Im5vIj8+Cjxzdmcgd2lkdGg9IjE5OHB4IiBoZWlnaHQ9IjI0MHB4IiB2aWV3Qm94PSIwIDAgMTk4IDI0MCIgdmVyc2lvbj0iMS4xIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHhtbG5zOnhsaW5rPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hsaW5rIiB4bWxuczpza2V0Y2g9Imh0dHA6Ly93d3cuYm9oZW1pYW5jb2RpbmcuY29tL3NrZXRjaC9ucyI+CiAgICA8IS0tIEdlbmVyYXRvcjogU2tldGNoIDMuMy4zICgxMjA4MSkgLSBodHRwOi8vd3d3LmJvaGVtaWFuY29kaW5nLmNvbS9za2V0Y2ggLS0+CiAgICA8dGl0bGU+dHJhbnNpdGlvbjwvdGl0bGU+CiAgICA8ZGVzYz5DcmVhdGVkIHdpdGggU2tldGNoLjwvZGVzYz4KICAgIDxkZWZzPjwvZGVmcz4KICAgIDxnIGlkPSJQYWdlLTEiIHN0cm9rZT0ibm9uZSIgc3Ryb2tlLXdpZHRoPSIxIiBmaWxsPSJub25lIiBmaWxsLXJ1bGU9ImV2ZW5vZGQiIHNrZXRjaDp0eXBlPSJNU1BhZ2UiPgogICAgICAgIDxnIGlkPSJ0cmFuc2l0aW9uIiBza2V0Y2g6dHlwZT0iTVNBcnRib2FyZEdyb3VwIj4KICAgICAgICAgICAgPGcgaWQ9IkltcG9ydGVkLUxheWVycy1Db3B5LTQtKy1JbXBvcnRlZC1MYXllcnMtQ29weS0rLUltcG9ydGVkLUxheWVycy1Db3B5LTItQ29weSIgc2tldGNoOnR5cGU9Ik1TTGF5ZXJHcm91cCI+CiAgICAgICAgICAgICAgICA8ZyBpZD0iSW1wb3J0ZWQtTGF5ZXJzLUNvcHktNCIgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoMC4wMDAwMDAsIDEwNy4wMDAwMDApIiBza2V0Y2g6dHlwZT0iTVNTaGFwZUdyb3VwIj4KICAgICAgICAgICAgICAgICAgICA8cGF0aCBkPSJNMTQ5LjYyNSwyLjUyNyBDMTQ5LjYyNSwyLjUyNyAxNTUuODA1LDYuMDk2IDE1Ni4zNjIsNi40MTggTDE1Ni4zNjIsNy4zMDQgQzE1Ni4zNjIsNy40ODEgMTU2LjM3NSw3LjY2NCAxNTYuNCw3Ljg1MyBDMTU2LjQxLDcuOTM0IDE1Ni40Miw4LjAxNSAxNTYuNDI3LDguMDk1IEMxNTYuNTY3LDkuNTEgMTU3LjQwMSwxMS4wOTMgMTU4LjUzMiwxMi4wOTQgTDE2NC4yNTIsMTcuMTU2IEwxNjQuMzMzLDE3LjA2NiBDMTY0LjMzMywxNy4wNjYgMTY4LjcxNSwxNC41MzYgMTY5LjU2OCwxNC4wNDIgQzE3MS4wMjUsMTQuODgzIDE5NS41MzgsMjkuMDM1IDE5NS41MzgsMjkuMDM1IEwxOTUuNTM4LDgzLjAzNiBDMTk1LjUzOCw4My44MDcgMTk1LjE1Miw4NC4yNTMgMTk0LjU5LDg0LjI1MyBDMTk0LjM1Nyw4NC4yNTMgMTk0LjA5NSw4NC4xNzcgMTkzLjgxOCw4NC4wMTcgTDE2OS44NTEsNzAuMTc5IEwxNjkuODM3LDcwLjIwMyBMMTQyLjUxNSw4NS45NzggTDE0MS42NjUsODQuNjU1IEMxMzYuOTM0LDgzLjEyNiAxMzEuOTE3LDgxLjkxNSAxMjYuNzE0LDgxLjA0NSBDMTI2LjcwOSw4MS4wNiAxMjYuNzA3LDgxLjA2OSAxMjYuNzA3LDgxLjA2OSBMMTIxLjY0LDk4LjAzIEwxMTMuNzQ5LDEwMi41ODYgTDExMy43MTIsMTAyLjUyMyBMMTEzLjcxMiwxMzAuMTEzIEMxMTMuNzEyLDEzMC44ODUgMTEzLjMyNiwxMzEuMzMgMTEyLjc2NCwxMzEuMzMgQzExMi41MzIsMTMxLjMzIDExMi4yNjksMTMxLjI1NCAxMTEuOTkyLDEzMS4wOTQgTDY5LjUxOSwxMDYuNTcyIEM2OC41NjksMTA2LjAyMyA2Ny43OTksMTA0LjY5NSA2Ny43OTksMTAzLjYwNSBMNjcuNzk5LDEwMi41NyBMNjcuNzc4LDEwMi42MTcgQzY3LjI3LDEwMi4zOTMgNjYuNjQ4LDEwMi4yNDkgNjUuOTYyLDEwMi4yMTggQzY1Ljg3NSwxMDIuMjE0IDY1Ljc4OCwxMDIuMjEyIDY1LjcwMSwxMDIuMjEyIEM2NS42MDYsMTAyLjIxMiA2NS41MTEsMTAyLjIxNSA2NS40MTYsMTAyLjIxOSBDNjUuMTk1LDEwMi4yMjkgNjQuOTc0LDEwMi4yMzUgNjQuNzU0LDEwMi4yMzUgQzY0LjMzMSwxMDIuMjM1IDYzLjkxMSwxMDIuMjE2IDYzLjQ5OCwxMDIuMTc4IEM2MS44NDMsMTAyLjAyNSA2MC4yOTgsMTAxLjU3OCA1OS4wOTQsMTAwLjg4MiBMMTIuNTE4LDczLjk5MiBMMTIuNTIzLDc0LjAwNCBMMi4yNDUsNTUuMjU0IEMxLjI0NCw1My40MjcgMi4wMDQsNTEuMDM4IDMuOTQzLDQ5LjkxOCBMNTkuOTU0LDE3LjU3MyBDNjAuNjI2LDE3LjE4NSA2MS4zNSwxNy4wMDEgNjIuMDUzLDE3LjAwMSBDNjMuMzc5LDE3LjAwMSA2NC42MjUsMTcuNjYgNjUuMjgsMTguODU0IEw2NS4yODUsMTguODUxIEw2NS41MTIsMTkuMjY0IEw2NS41MDYsMTkuMjY4IEM2NS45MDksMjAuMDAzIDY2LjQwNSwyMC42OCA2Ni45ODMsMjEuMjg2IEw2Ny4yNiwyMS41NTYgQzY5LjE3NCwyMy40MDYgNzEuNzI4LDI0LjM1NyA3NC4zNzMsMjQuMzU3IEM3Ni4zMjIsMjQuMzU3IDc4LjMyMSwyMy44NCA4MC4xNDgsMjIuNzg1IEM4MC4xNjEsMjIuNzg1IDg3LjQ2NywxOC41NjYgODcuNDY3LDE4LjU2NiBDODguMTM5LDE4LjE3OCA4OC44NjMsMTcuOTk0IDg5LjU2NiwxNy45OTQgQzkwLjg5MiwxNy45OTQgOTIuMTM4LDE4LjY1MiA5Mi43OTIsMTkuODQ3IEw5Ni4wNDIsMjUuNzc1IEw5Ni4wNjQsMjUuNzU3IEwxMDIuODQ5LDI5LjY3NCBMMTAyLjc0NCwyOS40OTIgTDE0OS42MjUsMi41MjcgTTE0OS42MjUsMC44OTIgQzE0OS4zNDMsMC44OTIgMTQ5LjA2MiwwLjk2NSAxNDguODEsMS4xMSBMMTAyLjY0MSwyNy42NjYgTDk3LjIzMSwyNC41NDIgTDk0LjIyNiwxOS4wNjEgQzkzLjMxMywxNy4zOTQgOTEuNTI3LDE2LjM1OSA4OS41NjYsMTYuMzU4IEM4OC41NTUsMTYuMzU4IDg3LjU0NiwxNi42MzIgODYuNjQ5LDE3LjE1IEM4My44NzgsMTguNzUgNzkuNjg3LDIxLjE2OSA3OS4zNzQsMjEuMzQ1IEM3OS4zNTksMjEuMzUzIDc5LjM0NSwyMS4zNjEgNzkuMzMsMjEuMzY5IEM3Ny43OTgsMjIuMjU0IDc2LjA4NCwyMi43MjIgNzQuMzczLDIyLjcyMiBDNzIuMDgxLDIyLjcyMiA2OS45NTksMjEuODkgNjguMzk3LDIwLjM4IEw2OC4xNDUsMjAuMTM1IEM2Ny43MDYsMTkuNjcyIDY3LjMyMywxOS4xNTYgNjcuMDA2LDE4LjYwMSBDNjYuOTg4LDE4LjU1OSA2Ni45NjgsMTguNTE5IDY2Ljk0NiwxOC40NzkgTDY2LjcxOSwxOC4wNjUgQzY2LjY5LDE4LjAxMiA2Ni42NTgsMTcuOTYgNjYuNjI0LDE3LjkxMSBDNjUuNjg2LDE2LjMzNyA2My45NTEsMTUuMzY2IDYyLjA1MywxNS4zNjYgQzYxLjA0MiwxNS4zNjYgNjAuMDMzLDE1LjY0IDU5LjEzNiwxNi4xNTggTDMuMTI1LDQ4LjUwMiBDMC40MjYsNTAuMDYxIC0wLjYxMyw1My40NDIgMC44MTEsNTYuMDQgTDExLjA4OSw3NC43OSBDMTEuMjY2LDc1LjExMyAxMS41MzcsNzUuMzUzIDExLjg1LDc1LjQ5NCBMNTguMjc2LDEwMi4yOTggQzU5LjY3OSwxMDMuMTA4IDYxLjQzMywxMDMuNjMgNjMuMzQ4LDEwMy44MDYgQzYzLjgxMiwxMDMuODQ4IDY0LjI4NSwxMDMuODcgNjQuNzU0LDEwMy44NyBDNjUsMTAzLjg3IDY1LjI0OSwxMDMuODY0IDY1LjQ5NCwxMDMuODUyIEM2NS41NjMsMTAzLjg0OSA2NS42MzIsMTAzLjg0NyA2NS43MDEsMTAzLjg0NyBDNjUuNzY0LDEwMy44NDcgNjUuODI4LDEwMy44NDkgNjUuODksMTAzLjg1MiBDNjUuOTg2LDEwMy44NTYgNjYuMDgsMTAzLjg2MyA2Ni4xNzMsMTAzLjg3NCBDNjYuMjgyLDEwNS40NjcgNjcuMzMyLDEwNy4xOTcgNjguNzAyLDEwNy45ODggTDExMS4xNzQsMTMyLjUxIEMxMTEuNjk4LDEzMi44MTIgMTEyLjIzMiwxMzIuOTY1IDExMi43NjQsMTMyLjk2NSBDMTE0LjI2MSwxMzIuOTY1IDExNS4zNDcsMTMxLjc2NSAxMTUuMzQ3LDEzMC4xMTMgTDExNS4zNDcsMTAzLjU1MSBMMTIyLjQ1OCw5OS40NDYgQzEyMi44MTksOTkuMjM3IDEyMy4wODcsOTguODk4IDEyMy4yMDcsOTguNDk4IEwxMjcuODY1LDgyLjkwNSBDMTMyLjI3OSw4My43MDIgMTM2LjU1Nyw4NC43NTMgMTQwLjYwNyw4Ni4wMzMgTDE0MS4xNCw4Ni44NjIgQzE0MS40NTEsODcuMzQ2IDE0MS45NzcsODcuNjEzIDE0Mi41MTYsODcuNjEzIEMxNDIuNzk0LDg3LjYxMyAxNDMuMDc2LDg3LjU0MiAxNDMuMzMzLDg3LjM5MyBMMTY5Ljg2NSw3Mi4wNzYgTDE5Myw4NS40MzMgQzE5My41MjMsODUuNzM1IDE5NC4wNTgsODUuODg4IDE5NC41OSw4NS44ODggQzE5Ni4wODcsODUuODg4IDE5Ny4xNzMsODQuNjg5IDE5Ny4xNzMsODMuMDM2IEwxOTcuMTczLDI5LjAzNSBDMTk3LjE3MywyOC40NTEgMTk2Ljg2MSwyNy45MTEgMTk2LjM1NSwyNy42MTkgQzE5Ni4zNTUsMjcuNjE5IDE3MS44NDMsMTMuNDY3IDE3MC4zODUsMTIuNjI2IEMxNzAuMTMyLDEyLjQ4IDE2OS44NSwxMi40MDcgMTY5LjU2OCwxMi40MDcgQzE2OS4yODUsMTIuNDA3IDE2OS4wMDIsMTIuNDgxIDE2OC43NDksMTIuNjI3IEMxNjguMTQzLDEyLjk3OCAxNjUuNzU2LDE0LjM1NyAxNjQuNDI0LDE1LjEyNSBMMTU5LjYxNSwxMC44NyBDMTU4Ljc5NiwxMC4xNDUgMTU4LjE1NCw4LjkzNyAxNTguMDU0LDcuOTM0IEMxNTguMDQ1LDcuODM3IDE1OC4wMzQsNy43MzkgMTU4LjAyMSw3LjY0IEMxNTguMDA1LDcuNTIzIDE1Ny45OTgsNy40MSAxNTcuOTk4LDcuMzA0IEwxNTcuOTk4LDYuNDE4IEMxNTcuOTk4LDUuODM0IDE1Ny42ODYsNS4yOTUgMTU3LjE4MSw1LjAwMiBDMTU2LjYyNCw0LjY4IDE1MC40NDIsMS4xMTEgMTUwLjQ0MiwxLjExMSBDMTUwLjE4OSwwLjk2NSAxNDkuOTA3LDAuODkyIDE0OS42MjUsMC44OTIiIGlkPSJGaWxsLTEiIGZpbGw9IiM0NTVBNjQiPjwvcGF0aD4KICAgICAgICAgICAgICAgICAgICA8cGF0aCBkPSJNOTYuMDI3LDI1LjYzNiBMMTQyLjYwMyw1Mi41MjcgQzE0My44MDcsNTMuMjIyIDE0NC41ODIsNTQuMTE0IDE0NC44NDUsNTUuMDY4IEwxNDQuODM1LDU1LjA3NSBMNjMuNDYxLDEwMi4wNTcgTDYzLjQ2LDEwMi4wNTcgQzYxLjgwNiwxMDEuOTA1IDYwLjI2MSwxMDEuNDU3IDU5LjA1NywxMDAuNzYyIEwxMi40ODEsNzMuODcxIEw5Ni4wMjcsMjUuNjM2IiBpZD0iRmlsbC0yIiBmaWxsPSIjRkFGQUZBIj48L3BhdGg+CiAgICAgICAgICAgICAgICAgICAgPHBhdGggZD0iTTYzLjQ2MSwxMDIuMTc0IEM2My40NTMsMTAyLjE3NCA2My40NDYsMTAyLjE3NCA2My40MzksMTAyLjE3MiBDNjEuNzQ2LDEwMi4wMTYgNjAuMjExLDEwMS41NjMgNTguOTk4LDEwMC44NjMgTDEyLjQyMiw3My45NzMgQzEyLjM4Niw3My45NTIgMTIuMzY0LDczLjkxNCAxMi4zNjQsNzMuODcxIEMxMi4zNjQsNzMuODMgMTIuMzg2LDczLjc5MSAxMi40MjIsNzMuNzcgTDk1Ljk2OCwyNS41MzUgQzk2LjAwNCwyNS41MTQgOTYuMDQ5LDI1LjUxNCA5Ni4wODUsMjUuNTM1IEwxNDIuNjYxLDUyLjQyNiBDMTQzLjg4OCw1My4xMzQgMTQ0LjY4Miw1NC4wMzggMTQ0Ljk1Nyw1NS4wMzcgQzE0NC45Nyw1NS4wODMgMTQ0Ljk1Myw1NS4xMzMgMTQ0LjkxNSw1NS4xNjEgQzE0NC45MTEsNTUuMTY1IDE0NC44OTgsNTUuMTc0IDE0NC44OTQsNTUuMTc3IEw2My41MTksMTAyLjE1OCBDNjMuNTAxLDEwMi4xNjkgNjMuNDgxLDEwMi4xNzQgNjMuNDYxLDEwMi4xNzQgTDYzLjQ2MSwxMDIuMTc0IFogTTEyLjcxNCw3My44NzEgTDU5LjExNSwxMDAuNjYxIEM2MC4yOTMsMTAxLjM0MSA2MS43ODYsMTAxLjc4MiA2My40MzUsMTAxLjkzNyBMMTQ0LjcwNyw1NS4wMTUgQzE0NC40MjgsNTQuMTA4IDE0My42ODIsNTMuMjg1IDE0Mi41NDQsNTIuNjI4IEw5Ni4wMjcsMjUuNzcxIEwxMi43MTQsNzMuODcxIEwxMi43MTQsNzMuODcxIFoiIGlkPSJGaWxsLTMiIGZpbGw9IiM2MDdEOEIiPjwvcGF0aD4KICAgICAgICAgICAgICAgICAgICA8cGF0aCBkPSJNMTQ4LjMyNyw1OC40NzEgQzE0OC4xNDUsNTguNDggMTQ3Ljk2Miw1OC40OCAxNDcuNzgxLDU4LjQ3MiBDMTQ1Ljg4Nyw1OC4zODkgMTQ0LjQ3OSw1Ny40MzQgMTQ0LjYzNiw1Ni4zNCBDMTQ0LjY4OSw1NS45NjcgMTQ0LjY2NCw1NS41OTcgMTQ0LjU2NCw1NS4yMzUgTDYzLjQ2MSwxMDIuMDU3IEM2NC4wODksMTAyLjExNSA2NC43MzMsMTAyLjEzIDY1LjM3OSwxMDIuMDk5IEM2NS41NjEsMTAyLjA5IDY1Ljc0MywxMDIuMDkgNjUuOTI1LDEwMi4wOTggQzY3LjgxOSwxMDIuMTgxIDY5LjIyNywxMDMuMTM2IDY5LjA3LDEwNC4yMyBMMTQ4LjMyNyw1OC40NzEiIGlkPSJGaWxsLTQiIGZpbGw9IiNGRkZGRkYiPjwvcGF0aD4KICAgICAgICAgICAgICAgICAgICA8cGF0aCBkPSJNNjkuMDcsMTA0LjM0NyBDNjkuMDQ4LDEwNC4zNDcgNjkuMDI1LDEwNC4zNCA2OS4wMDUsMTA0LjMyNyBDNjguOTY4LDEwNC4zMDEgNjguOTQ4LDEwNC4yNTcgNjguOTU1LDEwNC4yMTMgQzY5LDEwMy44OTYgNjguODk4LDEwMy41NzYgNjguNjU4LDEwMy4yODggQzY4LjE1MywxMDIuNjc4IDY3LjEwMywxMDIuMjY2IDY1LjkyLDEwMi4yMTQgQzY1Ljc0MiwxMDIuMjA2IDY1LjU2MywxMDIuMjA3IDY1LjM4NSwxMDIuMjE1IEM2NC43NDIsMTAyLjI0NiA2NC4wODcsMTAyLjIzMiA2My40NSwxMDIuMTc0IEM2My4zOTksMTAyLjE2OSA2My4zNTgsMTAyLjEzMiA2My4zNDcsMTAyLjA4MiBDNjMuMzM2LDEwMi4wMzMgNjMuMzU4LDEwMS45ODEgNjMuNDAyLDEwMS45NTYgTDE0NC41MDYsNTUuMTM0IEMxNDQuNTM3LDU1LjExNiAxNDQuNTc1LDU1LjExMyAxNDQuNjA5LDU1LjEyNyBDMTQ0LjY0Miw1NS4xNDEgMTQ0LjY2OCw1NS4xNyAxNDQuNjc3LDU1LjIwNCBDMTQ0Ljc4MSw1NS41ODUgMTQ0LjgwNiw1NS45NzIgMTQ0Ljc1MSw1Ni4zNTcgQzE0NC43MDYsNTYuNjczIDE0NC44MDgsNTYuOTk0IDE0NS4wNDcsNTcuMjgyIEMxNDUuNTUzLDU3Ljg5MiAxNDYuNjAyLDU4LjMwMyAxNDcuNzg2LDU4LjM1NSBDMTQ3Ljk2NCw1OC4zNjMgMTQ4LjE0Myw1OC4zNjMgMTQ4LjMyMSw1OC4zNTQgQzE0OC4zNzcsNTguMzUyIDE0OC40MjQsNTguMzg3IDE0OC40MzksNTguNDM4IEMxNDguNDU0LDU4LjQ5IDE0OC40MzIsNTguNTQ1IDE0OC4zODUsNTguNTcyIEw2OS4xMjksMTA0LjMzMSBDNjkuMTExLDEwNC4zNDIgNjkuMDksMTA0LjM0NyA2OS4wNywxMDQuMzQ3IEw2OS4wNywxMDQuMzQ3IFogTTY1LjY2NSwxMDEuOTc1IEM2NS43NTQsMTAxLjk3NSA2NS44NDIsMTAxLjk3NyA2NS45MywxMDEuOTgxIEM2Ny4xOTYsMTAyLjAzNyA2OC4yODMsMTAyLjQ2OSA2OC44MzgsMTAzLjEzOSBDNjkuMDY1LDEwMy40MTMgNjkuMTg4LDEwMy43MTQgNjkuMTk4LDEwNC4wMjEgTDE0Ny44ODMsNTguNTkyIEMxNDcuODQ3LDU4LjU5MiAxNDcuODExLDU4LjU5MSAxNDcuNzc2LDU4LjU4OSBDMTQ2LjUwOSw1OC41MzMgMTQ1LjQyMiw1OC4xIDE0NC44NjcsNTcuNDMxIEMxNDQuNTg1LDU3LjA5MSAxNDQuNDY1LDU2LjcwNyAxNDQuNTIsNTYuMzI0IEMxNDQuNTYzLDU2LjAyMSAxNDQuNTUyLDU1LjcxNiAxNDQuNDg4LDU1LjQxNCBMNjMuODQ2LDEwMS45NyBDNjQuMzUzLDEwMi4wMDIgNjQuODY3LDEwMi4wMDYgNjUuMzc0LDEwMS45ODIgQzY1LjQ3MSwxMDEuOTc3IDY1LjU2OCwxMDEuOTc1IDY1LjY2NSwxMDEuOTc1IEw2NS42NjUsMTAxLjk3NSBaIiBpZD0iRmlsbC01IiBmaWxsPSIjNjA3RDhCIj48L3BhdGg+CiAgICAgICAgICAgICAgICAgICAgPHBhdGggZD0iTTIuMjA4LDU1LjEzNCBDMS4yMDcsNTMuMzA3IDEuOTY3LDUwLjkxNyAzLjkwNiw0OS43OTcgTDU5LjkxNywxNy40NTMgQzYxLjg1NiwxNi4zMzMgNjQuMjQxLDE2LjkwNyA2NS4yNDMsMTguNzM0IEw2NS40NzUsMTkuMTQ0IEM2NS44NzIsMTkuODgyIDY2LjM2OCwyMC41NiA2Ni45NDUsMjEuMTY1IEw2Ny4yMjMsMjEuNDM1IEM3MC41NDgsMjQuNjQ5IDc1LjgwNiwyNS4xNTEgODAuMTExLDIyLjY2NSBMODcuNDMsMTguNDQ1IEM4OS4zNywxNy4zMjYgOTEuNzU0LDE3Ljg5OSA5Mi43NTUsMTkuNzI3IEw5Ni4wMDUsMjUuNjU1IEwxMi40ODYsNzMuODg0IEwyLjIwOCw1NS4xMzQgWiIgaWQ9IkZpbGwtNiIgZmlsbD0iI0ZBRkFGQSI+PC9wYXRoPgogICAgICAgICAgICAgICAgICAgIDxwYXRoIGQ9Ik0xMi40ODYsNzQuMDAxIEMxMi40NzYsNzQuMDAxIDEyLjQ2NSw3My45OTkgMTIuNDU1LDczLjk5NiBDMTIuNDI0LDczLjk4OCAxMi4zOTksNzMuOTY3IDEyLjM4NCw3My45NCBMMi4xMDYsNTUuMTkgQzEuMDc1LDUzLjMxIDEuODU3LDUwLjg0NSAzLjg0OCw0OS42OTYgTDU5Ljg1OCwxNy4zNTIgQzYwLjUyNSwxNi45NjcgNjEuMjcxLDE2Ljc2NCA2Mi4wMTYsMTYuNzY0IEM2My40MzEsMTYuNzY0IDY0LjY2NiwxNy40NjYgNjUuMzI3LDE4LjY0NiBDNjUuMzM3LDE4LjY1NCA2NS4zNDUsMTguNjYzIDY1LjM1MSwxOC42NzQgTDY1LjU3OCwxOS4wODggQzY1LjU4NCwxOS4xIDY1LjU4OSwxOS4xMTIgNjUuNTkxLDE5LjEyNiBDNjUuOTg1LDE5LjgzOCA2Ni40NjksMjAuNDk3IDY3LjAzLDIxLjA4NSBMNjcuMzA1LDIxLjM1MSBDNjkuMTUxLDIzLjEzNyA3MS42NDksMjQuMTIgNzQuMzM2LDI0LjEyIEM3Ni4zMTMsMjQuMTIgNzguMjksMjMuNTgyIDgwLjA1MywyMi41NjMgQzgwLjA2NCwyMi41NTcgODAuMDc2LDIyLjU1MyA4MC4wODgsMjIuNTUgTDg3LjM3MiwxOC4zNDQgQzg4LjAzOCwxNy45NTkgODguNzg0LDE3Ljc1NiA4OS41MjksMTcuNzU2IEM5MC45NTYsMTcuNzU2IDkyLjIwMSwxOC40NzIgOTIuODU4LDE5LjY3IEw5Ni4xMDcsMjUuNTk5IEM5Ni4xMzgsMjUuNjU0IDk2LjExOCwyNS43MjQgOTYuMDYzLDI1Ljc1NiBMMTIuNTQ1LDczLjk4NSBDMTIuNTI2LDczLjk5NiAxMi41MDYsNzQuMDAxIDEyLjQ4Niw3NC4wMDEgTDEyLjQ4Niw3NC4wMDEgWiBNNjIuMDE2LDE2Ljk5NyBDNjEuMzEyLDE2Ljk5NyA2MC42MDYsMTcuMTkgNTkuOTc1LDE3LjU1NCBMMy45NjUsNDkuODk5IEMyLjA4Myw1MC45ODUgMS4zNDEsNTMuMzA4IDIuMzEsNTUuMDc4IEwxMi41MzEsNzMuNzIzIEw5NS44NDgsMjUuNjExIEw5Mi42NTMsMTkuNzgyIEM5Mi4wMzgsMTguNjYgOTAuODcsMTcuOTkgODkuNTI5LDE3Ljk5IEM4OC44MjUsMTcuOTkgODguMTE5LDE4LjE4MiA4Ny40ODksMTguNTQ3IEw4MC4xNzIsMjIuNzcyIEM4MC4xNjEsMjIuNzc4IDgwLjE0OSwyMi43ODIgODAuMTM3LDIyLjc4NSBDNzguMzQ2LDIzLjgxMSA3Ni4zNDEsMjQuMzU0IDc0LjMzNiwyNC4zNTQgQzcxLjU4OCwyNC4zNTQgNjkuMDMzLDIzLjM0NyA2Ny4xNDIsMjEuNTE5IEw2Ni44NjQsMjEuMjQ5IEM2Ni4yNzcsMjAuNjM0IDY1Ljc3NCwxOS45NDcgNjUuMzY3LDE5LjIwMyBDNjUuMzYsMTkuMTkyIDY1LjM1NiwxOS4xNzkgNjUuMzU0LDE5LjE2NiBMNjUuMTYzLDE4LjgxOSBDNjUuMTU0LDE4LjgxMSA2NS4xNDYsMTguODAxIDY1LjE0LDE4Ljc5IEM2NC41MjUsMTcuNjY3IDYzLjM1NywxNi45OTcgNjIuMDE2LDE2Ljk5NyBMNjIuMDE2LDE2Ljk5NyBaIiBpZD0iRmlsbC03IiBmaWxsPSIjNjA3RDhCIj48L3BhdGg+CiAgICAgICAgICAgICAgICAgICAgPHBhdGggZD0iTTQyLjQzNCw0OC44MDggTDQyLjQzNCw0OC44MDggQzM5LjkyNCw0OC44MDcgMzcuNzM3LDQ3LjU1IDM2LjU4Miw0NS40NDMgQzM0Ljc3MSw0Mi4xMzkgMzYuMTQ0LDM3LjgwOSAzOS42NDEsMzUuNzg5IEw1MS45MzIsMjguNjkxIEM1My4xMDMsMjguMDE1IDU0LjQxMywyNy42NTggNTUuNzIxLDI3LjY1OCBDNTguMjMxLDI3LjY1OCA2MC40MTgsMjguOTE2IDYxLjU3MywzMS4wMjMgQzYzLjM4NCwzNC4zMjcgNjIuMDEyLDM4LjY1NyA1OC41MTQsNDAuNjc3IEw0Ni4yMjMsNDcuNzc1IEM0NS4wNTMsNDguNDUgNDMuNzQyLDQ4LjgwOCA0Mi40MzQsNDguODA4IEw0Mi40MzQsNDguODA4IFogTTU1LjcyMSwyOC4xMjUgQzU0LjQ5NSwyOC4xMjUgNTMuMjY1LDI4LjQ2MSA1Mi4xNjYsMjkuMDk2IEwzOS44NzUsMzYuMTk0IEMzNi41OTYsMzguMDg3IDM1LjMwMiw0Mi4xMzYgMzYuOTkyLDQ1LjIxOCBDMzguMDYzLDQ3LjE3MyA0MC4wOTgsNDguMzQgNDIuNDM0LDQ4LjM0IEM0My42NjEsNDguMzQgNDQuODksNDguMDA1IDQ1Ljk5LDQ3LjM3IEw1OC4yODEsNDAuMjcyIEM2MS41NiwzOC4zNzkgNjIuODUzLDM0LjMzIDYxLjE2NCwzMS4yNDggQzYwLjA5MiwyOS4yOTMgNTguMDU4LDI4LjEyNSA1NS43MjEsMjguMTI1IEw1NS43MjEsMjguMTI1IFoiIGlkPSJGaWxsLTgiIGZpbGw9IiM2MDdEOEIiPjwvcGF0aD4KICAgICAgICAgICAgICAgICAgICA8cGF0aCBkPSJNMTQ5LjU4OCwyLjQwNyBDMTQ5LjU4OCwyLjQwNyAxNTUuNzY4LDUuOTc1IDE1Ni4zMjUsNi4yOTcgTDE1Ni4zMjUsNy4xODQgQzE1Ni4zMjUsNy4zNiAxNTYuMzM4LDcuNTQ0IDE1Ni4zNjIsNy43MzMgQzE1Ni4zNzMsNy44MTQgMTU2LjM4Miw3Ljg5NCAxNTYuMzksNy45NzUgQzE1Ni41Myw5LjM5IDE1Ny4zNjMsMTAuOTczIDE1OC40OTUsMTEuOTc0IEwxNjUuODkxLDE4LjUxOSBDMTY2LjA2OCwxOC42NzUgMTY2LjI0OSwxOC44MTQgMTY2LjQzMiwxOC45MzQgQzE2OC4wMTEsMTkuOTc0IDE2OS4zODIsMTkuNCAxNjkuNDk0LDE3LjY1MiBDMTY5LjU0MywxNi44NjggMTY5LjU1MSwxNi4wNTcgMTY5LjUxNywxNS4yMjMgTDE2OS41MTQsMTUuMDYzIEwxNjkuNTE0LDEzLjkxMiBDMTcwLjc4LDE0LjY0MiAxOTUuNTAxLDI4LjkxNSAxOTUuNTAxLDI4LjkxNSBMMTk1LjUwMSw4Mi45MTUgQzE5NS41MDEsODQuMDA1IDE5NC43MzEsODQuNDQ1IDE5My43ODEsODMuODk3IEwxNTEuMzA4LDU5LjM3NCBDMTUwLjM1OCw1OC44MjYgMTQ5LjU4OCw1Ny40OTcgMTQ5LjU4OCw1Ni40MDggTDE0OS41ODgsMjIuMzc1IiBpZD0iRmlsbC05IiBmaWxsPSIjRkFGQUZBIj48L3BhdGg+CiAgICAgICAgICAgICAgICAgICAgPHBhdGggZD0iTTE5NC41NTMsODQuMjUgQzE5NC4yOTYsODQuMjUgMTk0LjAxMyw4NC4xNjUgMTkzLjcyMiw4My45OTcgTDE1MS4yNSw1OS40NzYgQzE1MC4yNjksNTguOTA5IDE0OS40NzEsNTcuNTMzIDE0OS40NzEsNTYuNDA4IEwxNDkuNDcxLDIyLjM3NSBMMTQ5LjcwNSwyMi4zNzUgTDE0OS43MDUsNTYuNDA4IEMxNDkuNzA1LDU3LjQ1OSAxNTAuNDUsNTguNzQ0IDE1MS4zNjYsNTkuMjc0IEwxOTMuODM5LDgzLjc5NSBDMTk0LjI2Myw4NC4wNCAxOTQuNjU1LDg0LjA4MyAxOTQuOTQyLDgzLjkxNyBDMTk1LjIyNyw4My43NTMgMTk1LjM4NCw4My4zOTcgMTk1LjM4NCw4Mi45MTUgTDE5NS4zODQsMjguOTgyIEMxOTQuMTAyLDI4LjI0MiAxNzIuMTA0LDE1LjU0MiAxNjkuNjMxLDE0LjExNCBMMTY5LjYzNCwxNS4yMiBDMTY5LjY2OCwxNi4wNTIgMTY5LjY2LDE2Ljg3NCAxNjkuNjEsMTcuNjU5IEMxNjkuNTU2LDE4LjUwMyAxNjkuMjE0LDE5LjEyMyAxNjguNjQ3LDE5LjQwNSBDMTY4LjAyOCwxOS43MTQgMTY3LjE5NywxOS41NzggMTY2LjM2NywxOS4wMzIgQzE2Ni4xODEsMTguOTA5IDE2NS45OTUsMTguNzY2IDE2NS44MTQsMTguNjA2IEwxNTguNDE3LDEyLjA2MiBDMTU3LjI1OSwxMS4wMzYgMTU2LjQxOCw5LjQzNyAxNTYuMjc0LDcuOTg2IEMxNTYuMjY2LDcuOTA3IDE1Ni4yNTcsNy44MjcgMTU2LjI0Nyw3Ljc0OCBDMTU2LjIyMSw3LjU1NSAxNTYuMjA5LDcuMzY1IDE1Ni4yMDksNy4xODQgTDE1Ni4yMDksNi4zNjQgQzE1NS4zNzUsNS44ODMgMTQ5LjUyOSwyLjUwOCAxNDkuNTI5LDIuNTA4IEwxNDkuNjQ2LDIuMzA2IEMxNDkuNjQ2LDIuMzA2IDE1NS44MjcsNS44NzQgMTU2LjM4NCw2LjE5NiBMMTU2LjQ0Miw2LjIzIEwxNTYuNDQyLDcuMTg0IEMxNTYuNDQyLDcuMzU1IDE1Ni40NTQsNy41MzUgMTU2LjQ3OCw3LjcxNyBDMTU2LjQ4OSw3LjggMTU2LjQ5OSw3Ljg4MiAxNTYuNTA3LDcuOTYzIEMxNTYuNjQ1LDkuMzU4IDE1Ny40NTUsMTAuODk4IDE1OC41NzIsMTEuODg2IEwxNjUuOTY5LDE4LjQzMSBDMTY2LjE0MiwxOC41ODQgMTY2LjMxOSwxOC43MiAxNjYuNDk2LDE4LjgzNyBDMTY3LjI1NCwxOS4zMzYgMTY4LDE5LjQ2NyAxNjguNTQzLDE5LjE5NiBDMTY5LjAzMywxOC45NTMgMTY5LjMyOSwxOC40MDEgMTY5LjM3NywxNy42NDUgQzE2OS40MjcsMTYuODY3IDE2OS40MzQsMTYuMDU0IDE2OS40MDEsMTUuMjI4IEwxNjkuMzk3LDE1LjA2NSBMMTY5LjM5NywxMy43MSBMMTY5LjU3MiwxMy44MSBDMTcwLjgzOSwxNC41NDEgMTk1LjU1OSwyOC44MTQgMTk1LjU1OSwyOC44MTQgTDE5NS42MTgsMjguODQ3IEwxOTUuNjE4LDgyLjkxNSBDMTk1LjYxOCw4My40ODQgMTk1LjQyLDgzLjkxMSAxOTUuMDU5LDg0LjExOSBDMTk0LjkwOCw4NC4yMDYgMTk0LjczNyw4NC4yNSAxOTQuNTUzLDg0LjI1IiBpZD0iRmlsbC0xMCIgZmlsbD0iIzYwN0Q4QiI+PC9wYXRoPgogICAgICAgICAgICAgICAgICAgIDxwYXRoIGQ9Ik0xNDUuNjg1LDU2LjE2MSBMMTY5LjgsNzAuMDgzIEwxNDMuODIyLDg1LjA4MSBMMTQyLjM2LDg0Ljc3NCBDMTM1LjgyNiw4Mi42MDQgMTI4LjczMiw4MS4wNDYgMTIxLjM0MSw4MC4xNTggQzExNi45NzYsNzkuNjM0IDExMi42NzgsODEuMjU0IDExMS43NDMsODMuNzc4IEMxMTEuNTA2LDg0LjQxNCAxMTEuNTAzLDg1LjA3MSAxMTEuNzMyLDg1LjcwNiBDMTEzLjI3LDg5Ljk3MyAxMTUuOTY4LDk0LjA2OSAxMTkuNzI3LDk3Ljg0MSBMMTIwLjI1OSw5OC42ODYgQzEyMC4yNiw5OC42ODUgOTQuMjgyLDExMy42ODMgOTQuMjgyLDExMy42ODMgTDcwLjE2Nyw5OS43NjEgTDE0NS42ODUsNTYuMTYxIiBpZD0iRmlsbC0xMSIgZmlsbD0iI0ZGRkZGRiI+PC9wYXRoPgogICAgICAgICAgICAgICAgICAgIDxwYXRoIGQ9Ik05NC4yODIsMTEzLjgxOCBMOTQuMjIzLDExMy43ODUgTDY5LjkzMyw5OS43NjEgTDcwLjEwOCw5OS42NiBMMTQ1LjY4NSw1Ni4wMjYgTDE0NS43NDMsNTYuMDU5IEwxNzAuMDMzLDcwLjA4MyBMMTQzLjg0Miw4NS4yMDUgTDE0My43OTcsODUuMTk1IEMxNDMuNzcyLDg1LjE5IDE0Mi4zMzYsODQuODg4IDE0Mi4zMzYsODQuODg4IEMxMzUuNzg3LDgyLjcxNCAxMjguNzIzLDgxLjE2MyAxMjEuMzI3LDgwLjI3NCBDMTIwLjc4OCw4MC4yMDkgMTIwLjIzNiw4MC4xNzcgMTE5LjY4OSw4MC4xNzcgQzExNS45MzEsODAuMTc3IDExMi42MzUsODEuNzA4IDExMS44NTIsODMuODE5IEMxMTEuNjI0LDg0LjQzMiAxMTEuNjIxLDg1LjA1MyAxMTEuODQyLDg1LjY2NyBDMTEzLjM3Nyw4OS45MjUgMTE2LjA1OCw5My45OTMgMTE5LjgxLDk3Ljc1OCBMMTE5LjgyNiw5Ny43NzkgTDEyMC4zNTIsOTguNjE0IEMxMjAuMzU0LDk4LjYxNyAxMjAuMzU2LDk4LjYyIDEyMC4zNTgsOTguNjI0IEwxMjAuNDIyLDk4LjcyNiBMMTIwLjMxNyw5OC43ODcgQzEyMC4yNjQsOTguODE4IDk0LjU5OSwxMTMuNjM1IDk0LjM0LDExMy43ODUgTDk0LjI4MiwxMTMuODE4IEw5NC4yODIsMTEzLjgxOCBaIE03MC40MDEsOTkuNzYxIEw5NC4yODIsMTEzLjU0OSBMMTE5LjA4NCw5OS4yMjkgQzExOS42Myw5OC45MTQgMTE5LjkzLDk4Ljc0IDEyMC4xMDEsOTguNjU0IEwxMTkuNjM1LDk3LjkxNCBDMTE1Ljg2NCw5NC4xMjcgMTEzLjE2OCw5MC4wMzMgMTExLjYyMiw4NS43NDYgQzExMS4zODIsODUuMDc5IDExMS4zODYsODQuNDA0IDExMS42MzMsODMuNzM4IEMxMTIuNDQ4LDgxLjUzOSAxMTUuODM2LDc5Ljk0MyAxMTkuNjg5LDc5Ljk0MyBDMTIwLjI0Niw3OS45NDMgMTIwLjgwNiw3OS45NzYgMTIxLjM1NSw4MC4wNDIgQzEyOC43NjcsODAuOTMzIDEzNS44NDYsODIuNDg3IDE0Mi4zOTYsODQuNjYzIEMxNDMuMjMyLDg0LjgzOCAxNDMuNjExLDg0LjkxNyAxNDMuNzg2LDg0Ljk2NyBMMTY5LjU2Niw3MC4wODMgTDE0NS42ODUsNTYuMjk1IEw3MC40MDEsOTkuNzYxIEw3MC40MDEsOTkuNzYxIFoiIGlkPSJGaWxsLTEyIiBmaWxsPSIjNjA3RDhCIj48L3BhdGg+CiAgICAgICAgICAgICAgICAgICAgPHBhdGggZD0iTTE2Ny4yMywxOC45NzkgTDE2Ny4yMyw2OS44NSBMMTM5LjkwOSw4NS42MjMgTDEzMy40NDgsNzEuNDU2IEMxMzIuNTM4LDY5LjQ2IDEzMC4wMiw2OS43MTggMTI3LjgyNCw3Mi4wMyBDMTI2Ljc2OSw3My4xNCAxMjUuOTMxLDc0LjU4NSAxMjUuNDk0LDc2LjA0OCBMMTE5LjAzNCw5Ny42NzYgTDkxLjcxMiwxMTMuNDUgTDkxLjcxMiw2Mi41NzkgTDE2Ny4yMywxOC45NzkiIGlkPSJGaWxsLTEzIiBmaWxsPSIjRkZGRkZGIj48L3BhdGg+CiAgICAgICAgICAgICAgICAgICAgPHBhdGggZD0iTTkxLjcxMiwxMTMuNTY3IEM5MS42OTIsMTEzLjU2NyA5MS42NzIsMTEzLjU2MSA5MS42NTMsMTEzLjU1MSBDOTEuNjE4LDExMy41MyA5MS41OTUsMTEzLjQ5MiA5MS41OTUsMTEzLjQ1IEw5MS41OTUsNjIuNTc5IEM5MS41OTUsNjIuNTM3IDkxLjYxOCw2Mi40OTkgOTEuNjUzLDYyLjQ3OCBMMTY3LjE3MiwxOC44NzggQzE2Ny4yMDgsMTguODU3IDE2Ny4yNTIsMTguODU3IDE2Ny4yODgsMTguODc4IEMxNjcuMzI0LDE4Ljg5OSAxNjcuMzQ3LDE4LjkzNyAxNjcuMzQ3LDE4Ljk3OSBMMTY3LjM0Nyw2OS44NSBDMTY3LjM0Nyw2OS44OTEgMTY3LjMyNCw2OS45MyAxNjcuMjg4LDY5Ljk1IEwxMzkuOTY3LDg1LjcyNSBDMTM5LjkzOSw4NS43NDEgMTM5LjkwNSw4NS43NDUgMTM5Ljg3Myw4NS43MzUgQzEzOS44NDIsODUuNzI1IDEzOS44MTYsODUuNzAyIDEzOS44MDIsODUuNjcyIEwxMzMuMzQyLDcxLjUwNCBDMTMyLjk2Nyw3MC42ODIgMTMyLjI4LDcwLjIyOSAxMzEuNDA4LDcwLjIyOSBDMTMwLjMxOSw3MC4yMjkgMTI5LjA0NCw3MC45MTUgMTI3LjkwOCw3Mi4xMSBDMTI2Ljg3NCw3My4yIDEyNi4wMzQsNzQuNjQ3IDEyNS42MDYsNzYuMDgyIEwxMTkuMTQ2LDk3LjcwOSBDMTE5LjEzNyw5Ny43MzggMTE5LjExOCw5Ny43NjIgMTE5LjA5Miw5Ny43NzcgTDkxLjc3LDExMy41NTEgQzkxLjc1MiwxMTMuNTYxIDkxLjczMiwxMTMuNTY3IDkxLjcxMiwxMTMuNTY3IEw5MS43MTIsMTEzLjU2NyBaIE05MS44MjksNjIuNjQ3IEw5MS44MjksMTEzLjI0OCBMMTE4LjkzNSw5Ny41OTggTDEyNS4zODIsNzYuMDE1IEMxMjUuODI3LDc0LjUyNSAxMjYuNjY0LDczLjA4MSAxMjcuNzM5LDcxLjk1IEMxMjguOTE5LDcwLjcwOCAxMzAuMjU2LDY5Ljk5NiAxMzEuNDA4LDY5Ljk5NiBDMTMyLjM3Nyw2OS45OTYgMTMzLjEzOSw3MC40OTcgMTMzLjU1NCw3MS40MDcgTDEzOS45NjEsODUuNDU4IEwxNjcuMTEzLDY5Ljc4MiBMMTY3LjExMywxOS4xODEgTDkxLjgyOSw2Mi42NDcgTDkxLjgyOSw2Mi42NDcgWiIgaWQ9IkZpbGwtMTQiIGZpbGw9IiM2MDdEOEIiPjwvcGF0aD4KICAgICAgICAgICAgICAgICAgICA8cGF0aCBkPSJNMTY4LjU0MywxOS4yMTMgTDE2OC41NDMsNzAuMDgzIEwxNDEuMjIxLDg1Ljg1NyBMMTM0Ljc2MSw3MS42ODkgQzEzMy44NTEsNjkuNjk0IDEzMS4zMzMsNjkuOTUxIDEyOS4xMzcsNzIuMjYzIEMxMjguMDgyLDczLjM3NCAxMjcuMjQ0LDc0LjgxOSAxMjYuODA3LDc2LjI4MiBMMTIwLjM0Niw5Ny45MDkgTDkzLjAyNSwxMTMuNjgzIEw5My4wMjUsNjIuODEzIEwxNjguNTQzLDE5LjIxMyIgaWQ9IkZpbGwtMTUiIGZpbGw9IiNGRkZGRkYiPjwvcGF0aD4KICAgICAgICAgICAgICAgICAgICA8cGF0aCBkPSJNOTMuMDI1LDExMy44IEM5My4wMDUsMTEzLjggOTIuOTg0LDExMy43OTUgOTIuOTY2LDExMy43ODUgQzkyLjkzMSwxMTMuNzY0IDkyLjkwOCwxMTMuNzI1IDkyLjkwOCwxMTMuNjg0IEw5Mi45MDgsNjIuODEzIEM5Mi45MDgsNjIuNzcxIDkyLjkzMSw2Mi43MzMgOTIuOTY2LDYyLjcxMiBMMTY4LjQ4NCwxOS4xMTIgQzE2OC41MiwxOS4wOSAxNjguNTY1LDE5LjA5IDE2OC42MDEsMTkuMTEyIEMxNjguNjM3LDE5LjEzMiAxNjguNjYsMTkuMTcxIDE2OC42NiwxOS4yMTIgTDE2OC42Niw3MC4wODMgQzE2OC42Niw3MC4xMjUgMTY4LjYzNyw3MC4xNjQgMTY4LjYwMSw3MC4xODQgTDE0MS4yOCw4NS45NTggQzE0MS4yNTEsODUuOTc1IDE0MS4yMTcsODUuOTc5IDE0MS4xODYsODUuOTY4IEMxNDEuMTU0LDg1Ljk1OCAxNDEuMTI5LDg1LjkzNiAxNDEuMTE1LDg1LjkwNiBMMTM0LjY1NSw3MS43MzggQzEzNC4yOCw3MC45MTUgMTMzLjU5Myw3MC40NjMgMTMyLjcyLDcwLjQ2MyBDMTMxLjYzMiw3MC40NjMgMTMwLjM1Nyw3MS4xNDggMTI5LjIyMSw3Mi4zNDQgQzEyOC4xODYsNzMuNDMzIDEyNy4zNDcsNzQuODgxIDEyNi45MTksNzYuMzE1IEwxMjAuNDU4LDk3Ljk0MyBDMTIwLjQ1LDk3Ljk3MiAxMjAuNDMxLDk3Ljk5NiAxMjAuNDA1LDk4LjAxIEw5My4wODMsMTEzLjc4NSBDOTMuMDY1LDExMy43OTUgOTMuMDQ1LDExMy44IDkzLjAyNSwxMTMuOCBMOTMuMDI1LDExMy44IFogTTkzLjE0Miw2Mi44ODEgTDkzLjE0MiwxMTMuNDgxIEwxMjAuMjQ4LDk3LjgzMiBMMTI2LjY5NSw3Ni4yNDggQzEyNy4xNCw3NC43NTggMTI3Ljk3Nyw3My4zMTUgMTI5LjA1Miw3Mi4xODMgQzEzMC4yMzEsNzAuOTQyIDEzMS41NjgsNzAuMjI5IDEzMi43Miw3MC4yMjkgQzEzMy42ODksNzAuMjI5IDEzNC40NTIsNzAuNzMxIDEzNC44NjcsNzEuNjQxIEwxNDEuMjc0LDg1LjY5MiBMMTY4LjQyNiw3MC4wMTYgTDE2OC40MjYsMTkuNDE1IEw5My4xNDIsNjIuODgxIEw5My4xNDIsNjIuODgxIFoiIGlkPSJGaWxsLTE2IiBmaWxsPSIjNjA3RDhCIj48L3BhdGg+CiAgICAgICAgICAgICAgICAgICAgPHBhdGggZD0iTTE2OS44LDcwLjA4MyBMMTQyLjQ3OCw4NS44NTcgTDEzNi4wMTgsNzEuNjg5IEMxMzUuMTA4LDY5LjY5NCAxMzIuNTksNjkuOTUxIDEzMC4zOTMsNzIuMjYzIEMxMjkuMzM5LDczLjM3NCAxMjguNSw3NC44MTkgMTI4LjA2NCw3Ni4yODIgTDEyMS42MDMsOTcuOTA5IEw5NC4yODIsMTEzLjY4MyBMOTQuMjgyLDYyLjgxMyBMMTY5LjgsMTkuMjEzIEwxNjkuOCw3MC4wODMgWiIgaWQ9IkZpbGwtMTciIGZpbGw9IiNGQUZBRkEiPjwvcGF0aD4KICAgICAgICAgICAgICAgICAgICA8cGF0aCBkPSJNOTQuMjgyLDExMy45MTcgQzk0LjI0MSwxMTMuOTE3IDk0LjIwMSwxMTMuOTA3IDk0LjE2NSwxMTMuODg2IEM5NC4wOTMsMTEzLjg0NSA5NC4wNDgsMTEzLjc2NyA5NC4wNDgsMTEzLjY4NCBMOTQuMDQ4LDYyLjgxMyBDOTQuMDQ4LDYyLjczIDk0LjA5Myw2Mi42NTIgOTQuMTY1LDYyLjYxMSBMMTY5LjY4MywxOS4wMSBDMTY5Ljc1NSwxOC45NjkgMTY5Ljg0NCwxOC45NjkgMTY5LjkxNywxOS4wMSBDMTY5Ljk4OSwxOS4wNTIgMTcwLjAzMywxOS4xMjkgMTcwLjAzMywxOS4yMTIgTDE3MC4wMzMsNzAuMDgzIEMxNzAuMDMzLDcwLjE2NiAxNjkuOTg5LDcwLjI0NCAxNjkuOTE3LDcwLjI4NSBMMTQyLjU5NSw4Ni4wNiBDMTQyLjUzOCw4Ni4wOTIgMTQyLjQ2OSw4Ni4xIDE0Mi40MDcsODYuMDggQzE0Mi4zNDQsODYuMDYgMTQyLjI5Myw4Ni4wMTQgMTQyLjI2Niw4NS45NTQgTDEzNS44MDUsNzEuNzg2IEMxMzUuNDQ1LDcwLjk5NyAxMzQuODEzLDcwLjU4IDEzMy45NzcsNzAuNTggQzEzMi45MjEsNzAuNTggMTMxLjY3Niw3MS4yNTIgMTMwLjU2Miw3Mi40MjQgQzEyOS41NCw3My41MDEgMTI4LjcxMSw3NC45MzEgMTI4LjI4Nyw3Ni4zNDggTDEyMS44MjcsOTcuOTc2IEMxMjEuODEsOTguMDM0IDEyMS43NzEsOTguMDgyIDEyMS43Miw5OC4xMTIgTDk0LjM5OCwxMTMuODg2IEM5NC4zNjIsMTEzLjkwNyA5NC4zMjIsMTEzLjkxNyA5NC4yODIsMTEzLjkxNyBMOTQuMjgyLDExMy45MTcgWiBNOTQuNTE1LDYyLjk0OCBMOTQuNTE1LDExMy4yNzkgTDEyMS40MDYsOTcuNzU0IEwxMjcuODQsNzYuMjE1IEMxMjguMjksNzQuNzA4IDEyOS4xMzcsNzMuMjQ3IDEzMC4yMjQsNzIuMTAzIEMxMzEuNDI1LDcwLjgzOCAxMzIuNzkzLDcwLjExMiAxMzMuOTc3LDcwLjExMiBDMTM0Ljk5NSw3MC4xMTIgMTM1Ljc5NSw3MC42MzggMTM2LjIzLDcxLjU5MiBMMTQyLjU4NCw4NS41MjYgTDE2OS41NjYsNjkuOTQ4IEwxNjkuNTY2LDE5LjYxNyBMOTQuNTE1LDYyLjk0OCBMOTQuNTE1LDYyLjk0OCBaIiBpZD0iRmlsbC0xOCIgZmlsbD0iIzYwN0Q4QiI+PC9wYXRoPgogICAgICAgICAgICAgICAgICAgIDxwYXRoIGQ9Ik0xMDkuODk0LDkyLjk0MyBMMTA5Ljg5NCw5Mi45NDMgQzEwOC4xMiw5Mi45NDMgMTA2LjY1Myw5Mi4yMTggMTA1LjY1LDkwLjgyMyBDMTA1LjU4Myw5MC43MzEgMTA1LjU5Myw5MC42MSAxMDUuNjczLDkwLjUyOSBDMTA1Ljc1Myw5MC40NDggMTA1Ljg4LDkwLjQ0IDEwNS45NzQsOTAuNTA2IEMxMDYuNzU0LDkxLjA1MyAxMDcuNjc5LDkxLjMzMyAxMDguNzI0LDkxLjMzMyBDMTEwLjA0Nyw5MS4zMzMgMTExLjQ3OCw5MC44OTQgMTEyLjk4LDkwLjAyNyBDMTE4LjI5MSw4Ni45NiAxMjIuNjExLDc5LjUwOSAxMjIuNjExLDczLjQxNiBDMTIyLjYxMSw3MS40ODkgMTIyLjE2OSw2OS44NTYgMTIxLjMzMyw2OC42OTIgQzEyMS4yNjYsNjguNiAxMjEuMjc2LDY4LjQ3MyAxMjEuMzU2LDY4LjM5MiBDMTIxLjQzNiw2OC4zMTEgMTIxLjU2Myw2OC4yOTkgMTIxLjY1Niw2OC4zNjUgQzEyMy4zMjcsNjkuNTM3IDEyNC4yNDcsNzEuNzQ2IDEyNC4yNDcsNzQuNTg0IEMxMjQuMjQ3LDgwLjgyNiAxMTkuODIxLDg4LjQ0NyAxMTQuMzgyLDkxLjU4NyBDMTEyLjgwOCw5Mi40OTUgMTExLjI5OCw5Mi45NDMgMTA5Ljg5NCw5Mi45NDMgTDEwOS44OTQsOTIuOTQzIFogTTEwNi45MjUsOTEuNDAxIEMxMDcuNzM4LDkyLjA1MiAxMDguNzQ1LDkyLjI3OCAxMDkuODkzLDkyLjI3OCBMMTA5Ljg5NCw5Mi4yNzggQzExMS4yMTUsOTIuMjc4IDExMi42NDcsOTEuOTUxIDExNC4xNDgsOTEuMDg0IEMxMTkuNDU5LDg4LjAxNyAxMjMuNzgsODAuNjIxIDEyMy43OCw3NC41MjggQzEyMy43OCw3Mi41NDkgMTIzLjMxNyw3MC45MjkgMTIyLjQ1NCw2OS43NjcgQzEyMi44NjUsNzAuODAyIDEyMy4wNzksNzIuMDQyIDEyMy4wNzksNzMuNDAyIEMxMjMuMDc5LDc5LjY0NSAxMTguNjUzLDg3LjI4NSAxMTMuMjE0LDkwLjQyNSBDMTExLjY0LDkxLjMzNCAxMTAuMTMsOTEuNzQyIDEwOC43MjQsOTEuNzQyIEMxMDguMDgzLDkxLjc0MiAxMDcuNDgxLDkxLjU5MyAxMDYuOTI1LDkxLjQwMSBMMTA2LjkyNSw5MS40MDEgWiIgaWQ9IkZpbGwtMTkiIGZpbGw9IiM2MDdEOEIiPjwvcGF0aD4KICAgICAgICAgICAgICAgICAgICA8cGF0aCBkPSJNMTEzLjA5Nyw5MC4yMyBDMTE4LjQ4MSw4Ny4xMjIgMTIyLjg0NSw3OS41OTQgMTIyLjg0NSw3My40MTYgQzEyMi44NDUsNzEuMzY1IDEyMi4zNjIsNjkuNzI0IDEyMS41MjIsNjguNTU2IEMxMTkuNzM4LDY3LjMwNCAxMTcuMTQ4LDY3LjM2MiAxMTQuMjY1LDY5LjAyNiBDMTA4Ljg4MSw3Mi4xMzQgMTA0LjUxNyw3OS42NjIgMTA0LjUxNyw4NS44NCBDMTA0LjUxNyw4Ny44OTEgMTA1LDg5LjUzMiAxMDUuODQsOTAuNyBDMTA3LjYyNCw5MS45NTIgMTEwLjIxNCw5MS44OTQgMTEzLjA5Nyw5MC4yMyIgaWQ9IkZpbGwtMjAiIGZpbGw9IiNGQUZBRkEiPjwvcGF0aD4KICAgICAgICAgICAgICAgICAgICA8cGF0aCBkPSJNMTA4LjcyNCw5MS42MTQgTDEwOC43MjQsOTEuNjE0IEMxMDcuNTgyLDkxLjYxNCAxMDYuNTY2LDkxLjQwMSAxMDUuNzA1LDkwLjc5NyBDMTA1LjY4NCw5MC43ODMgMTA1LjY2NSw5MC44MTEgMTA1LjY1LDkwLjc5IEMxMDQuNzU2LDg5LjU0NiAxMDQuMjgzLDg3Ljg0MiAxMDQuMjgzLDg1LjgxNyBDMTA0LjI4Myw3OS41NzUgMTA4LjcwOSw3MS45NTMgMTE0LjE0OCw2OC44MTIgQzExNS43MjIsNjcuOTA0IDExNy4yMzIsNjcuNDQ5IDExOC42MzgsNjcuNDQ5IEMxMTkuNzgsNjcuNDQ5IDEyMC43OTYsNjcuNzU4IDEyMS42NTYsNjguMzYyIEMxMjEuNjc4LDY4LjM3NyAxMjEuNjk3LDY4LjM5NyAxMjEuNzEyLDY4LjQxOCBDMTIyLjYwNiw2OS42NjIgMTIzLjA3OSw3MS4zOSAxMjMuMDc5LDczLjQxNSBDMTIzLjA3OSw3OS42NTggMTE4LjY1Myw4Ny4xOTggMTEzLjIxNCw5MC4zMzggQzExMS42NCw5MS4yNDcgMTEwLjEzLDkxLjYxNCAxMDguNzI0LDkxLjYxNCBMMTA4LjcyNCw5MS42MTQgWiBNMTA2LjAwNiw5MC41MDUgQzEwNi43OCw5MS4wMzcgMTA3LjY5NCw5MS4yODEgMTA4LjcyNCw5MS4yODEgQzExMC4wNDcsOTEuMjgxIDExMS40NzgsOTAuODY4IDExMi45OCw5MC4wMDEgQzExOC4yOTEsODYuOTM1IDEyMi42MTEsNzkuNDk2IDEyMi42MTEsNzMuNDAzIEMxMjIuNjExLDcxLjQ5NCAxMjIuMTc3LDY5Ljg4IDEyMS4zNTYsNjguNzE4IEMxMjAuNTgyLDY4LjE4NSAxMTkuNjY4LDY3LjkxOSAxMTguNjM4LDY3LjkxOSBDMTE3LjMxNSw2Ny45MTkgMTE1Ljg4Myw2OC4zNiAxMTQuMzgyLDY5LjIyNyBDMTA5LjA3MSw3Mi4yOTMgMTA0Ljc1MSw3OS43MzMgMTA0Ljc1MSw4NS44MjYgQzEwNC43NTEsODcuNzM1IDEwNS4xODUsODkuMzQzIDEwNi4wMDYsOTAuNTA1IEwxMDYuMDA2LDkwLjUwNSBaIiBpZD0iRmlsbC0yMSIgZmlsbD0iIzYwN0Q4QiI+PC9wYXRoPgogICAgICAgICAgICAgICAgICAgIDxwYXRoIGQ9Ik0xNDkuMzE4LDcuMjYyIEwxMzkuMzM0LDE2LjE0IEwxNTUuMjI3LDI3LjE3MSBMMTYwLjgxNiwyMS4wNTkgTDE0OS4zMTgsNy4yNjIiIGlkPSJGaWxsLTIyIiBmaWxsPSIjRkFGQUZBIj48L3BhdGg+CiAgICAgICAgICAgICAgICAgICAgPHBhdGggZD0iTTE2OS42NzYsMTMuODQgTDE1OS45MjgsMTkuNDY3IEMxNTYuMjg2LDIxLjU3IDE1MC40LDIxLjU4IDE0Ni43ODEsMTkuNDkxIEMxNDMuMTYxLDE3LjQwMiAxNDMuMTgsMTQuMDAzIDE0Ni44MjIsMTEuOSBMMTU2LjMxNyw2LjI5MiBMMTQ5LjU4OCwyLjQwNyBMNjcuNzUyLDQ5LjQ3OCBMMTEzLjY3NSw3NS45OTIgTDExNi43NTYsNzQuMjEzIEMxMTcuMzg3LDczLjg0OCAxMTcuNjI1LDczLjMxNSAxMTcuMzc0LDcyLjgyMyBDMTE1LjAxNyw2OC4xOTEgMTE0Ljc4MSw2My4yNzcgMTE2LjY5MSw1OC41NjEgQzEyMi4zMjksNDQuNjQxIDE0MS4yLDMzLjc0NiAxNjUuMzA5LDMwLjQ5MSBDMTczLjQ3OCwyOS4zODggMTgxLjk4OSwyOS41MjQgMTkwLjAxMywzMC44ODUgQzE5MC44NjUsMzEuMDMgMTkxLjc4OSwzMC44OTMgMTkyLjQyLDMwLjUyOCBMMTk1LjUwMSwyOC43NSBMMTY5LjY3NiwxMy44NCIgaWQ9IkZpbGwtMjMiIGZpbGw9IiNGQUZBRkEiPjwvcGF0aD4KICAgICAgICAgICAgICAgICAgICA8cGF0aCBkPSJNMTEzLjY3NSw3Ni40NTkgQzExMy41OTQsNzYuNDU5IDExMy41MTQsNzYuNDM4IDExMy40NDIsNzYuMzk3IEw2Ny41MTgsNDkuODgyIEM2Ny4zNzQsNDkuNzk5IDY3LjI4NCw0OS42NDUgNjcuMjg1LDQ5LjQ3OCBDNjcuMjg1LDQ5LjMxMSA2Ny4zNzQsNDkuMTU3IDY3LjUxOSw0OS4wNzMgTDE0OS4zNTUsMi4wMDIgQzE0OS40OTksMS45MTkgMTQ5LjY3NywxLjkxOSAxNDkuODIxLDIuMDAyIEwxNTYuNTUsNS44ODcgQzE1Ni43NzQsNi4wMTcgMTU2Ljg1LDYuMzAyIDE1Ni43MjIsNi41MjYgQzE1Ni41OTIsNi43NDkgMTU2LjMwNyw2LjgyNiAxNTYuMDgzLDYuNjk2IEwxNDkuNTg3LDIuOTQ2IEw2OC42ODcsNDkuNDc5IEwxMTMuNjc1LDc1LjQ1MiBMMTE2LjUyMyw3My44MDggQzExNi43MTUsNzMuNjk3IDExNy4xNDMsNzMuMzk5IDExNi45NTgsNzMuMDM1IEMxMTQuNTQyLDY4LjI4NyAxMTQuMyw2My4yMjEgMTE2LjI1OCw1OC4zODUgQzExOS4wNjQsNTEuNDU4IDEyNS4xNDMsNDUuMTQzIDEzMy44NCw0MC4xMjIgQzE0Mi40OTcsMzUuMTI0IDE1My4zNTgsMzEuNjMzIDE2NS4yNDcsMzAuMDI4IEMxNzMuNDQ1LDI4LjkyMSAxODIuMDM3LDI5LjA1OCAxOTAuMDkxLDMwLjQyNSBDMTkwLjgzLDMwLjU1IDE5MS42NTIsMzAuNDMyIDE5Mi4xODYsMzAuMTI0IEwxOTQuNTY3LDI4Ljc1IEwxNjkuNDQyLDE0LjI0NCBDMTY5LjIxOSwxNC4xMTUgMTY5LjE0MiwxMy44MjkgMTY5LjI3MSwxMy42MDYgQzE2OS40LDEzLjM4MiAxNjkuNjg1LDEzLjMwNiAxNjkuOTA5LDEzLjQzNSBMMTk1LjczNCwyOC4zNDUgQzE5NS44NzksMjguNDI4IDE5NS45NjgsMjguNTgzIDE5NS45NjgsMjguNzUgQzE5NS45NjgsMjguOTE2IDE5NS44NzksMjkuMDcxIDE5NS43MzQsMjkuMTU0IEwxOTIuNjUzLDMwLjkzMyBDMTkxLjkzMiwzMS4zNSAxOTAuODksMzEuNTA4IDE4OS45MzUsMzEuMzQ2IEMxODEuOTcyLDI5Ljk5NSAxNzMuNDc4LDI5Ljg2IDE2NS4zNzIsMzAuOTU0IEMxNTMuNjAyLDMyLjU0MyAxNDIuODYsMzUuOTkzIDEzNC4zMDcsNDAuOTMxIEMxMjUuNzkzLDQ1Ljg0NyAxMTkuODUxLDUyLjAwNCAxMTcuMTI0LDU4LjczNiBDMTE1LjI3LDYzLjMxNCAxMTUuNTAxLDY4LjExMiAxMTcuNzksNzIuNjExIEMxMTguMTYsNzMuMzM2IDExNy44NDUsNzQuMTI0IDExNi45OSw3NC42MTcgTDExMy45MDksNzYuMzk3IEMxMTMuODM2LDc2LjQzOCAxMTMuNzU2LDc2LjQ1OSAxMTMuNjc1LDc2LjQ1OSIgaWQ9IkZpbGwtMjQiIGZpbGw9IiM0NTVBNjQiPjwvcGF0aD4KICAgICAgICAgICAgICAgICAgICA8cGF0aCBkPSJNMTUzLjMxNiwyMS4yNzkgQzE1MC45MDMsMjEuMjc5IDE0OC40OTUsMjAuNzUxIDE0Ni42NjQsMTkuNjkzIEMxNDQuODQ2LDE4LjY0NCAxNDMuODQ0LDE3LjIzMiAxNDMuODQ0LDE1LjcxOCBDMTQzLjg0NCwxNC4xOTEgMTQ0Ljg2LDEyLjc2MyAxNDYuNzA1LDExLjY5OCBMMTU2LjE5OCw2LjA5MSBDMTU2LjMwOSw2LjAyNSAxNTYuNDUyLDYuMDYyIDE1Ni41MTgsNi4xNzMgQzE1Ni41ODMsNi4yODQgMTU2LjU0Nyw2LjQyNyAxNTYuNDM2LDYuNDkzIEwxNDYuOTQsMTIuMTAyIEMxNDUuMjQ0LDEzLjA4MSAxNDQuMzEyLDE0LjM2NSAxNDQuMzEyLDE1LjcxOCBDMTQ0LjMxMiwxNy4wNTggMTQ1LjIzLDE4LjMyNiAxNDYuODk3LDE5LjI4OSBDMTUwLjQ0NiwyMS4zMzggMTU2LjI0LDIxLjMyNyAxNTkuODExLDE5LjI2NSBMMTY5LjU1OSwxMy42MzcgQzE2OS42NywxMy41NzMgMTY5LjgxMywxMy42MTEgMTY5Ljg3OCwxMy43MjMgQzE2OS45NDMsMTMuODM0IDE2OS45MDQsMTMuOTc3IDE2OS43OTMsMTQuMDQyIEwxNjAuMDQ1LDE5LjY3IEMxNTguMTg3LDIwLjc0MiAxNTUuNzQ5LDIxLjI3OSAxNTMuMzE2LDIxLjI3OSIgaWQ9IkZpbGwtMjUiIGZpbGw9IiM2MDdEOEIiPjwvcGF0aD4KICAgICAgICAgICAgICAgICAgICA8cGF0aCBkPSJNMTEzLjY3NSw3NS45OTIgTDY3Ljc2Miw0OS40ODQiIGlkPSJGaWxsLTI2IiBmaWxsPSIjNDU1QTY0Ij48L3BhdGg+CiAgICAgICAgICAgICAgICAgICAgPHBhdGggZD0iTTExMy42NzUsNzYuMzQyIEMxMTMuNjE1LDc2LjM0MiAxMTMuNTU1LDc2LjMyNyAxMTMuNSw3Ni4yOTUgTDY3LjU4Nyw0OS43ODcgQzY3LjQxOSw0OS42OSA2Ny4zNjIsNDkuNDc2IDY3LjQ1OSw0OS4zMDkgQzY3LjU1Niw0OS4xNDEgNjcuNzcsNDkuMDgzIDY3LjkzNyw0OS4xOCBMMTEzLjg1LDc1LjY4OCBDMTE0LjAxOCw3NS43ODUgMTE0LjA3NSw3NiAxMTMuOTc4LDc2LjE2NyBDMTEzLjkxNCw3Ni4yNzkgMTEzLjc5Niw3Ni4zNDIgMTEzLjY3NSw3Ni4zNDIiIGlkPSJGaWxsLTI3IiBmaWxsPSIjNDU1QTY0Ij48L3BhdGg+CiAgICAgICAgICAgICAgICAgICAgPHBhdGggZD0iTTY3Ljc2Miw0OS40ODQgTDY3Ljc2MiwxMDMuNDg1IEM2Ny43NjIsMTA0LjU3NSA2OC41MzIsMTA1LjkwMyA2OS40ODIsMTA2LjQ1MiBMMTExLjk1NSwxMzAuOTczIEMxMTIuOTA1LDEzMS41MjIgMTEzLjY3NSwxMzEuMDgzIDExMy42NzUsMTI5Ljk5MyBMMTEzLjY3NSw3NS45OTIiIGlkPSJGaWxsLTI4IiBmaWxsPSIjRkFGQUZBIj48L3BhdGg+CiAgICAgICAgICAgICAgICAgICAgPHBhdGggZD0iTTExMi43MjcsMTMxLjU2MSBDMTEyLjQzLDEzMS41NjEgMTEyLjEwNywxMzEuNDY2IDExMS43OCwxMzEuMjc2IEw2OS4zMDcsMTA2Ljc1NSBDNjguMjQ0LDEwNi4xNDIgNjcuNDEyLDEwNC43MDUgNjcuNDEyLDEwMy40ODUgTDY3LjQxMiw0OS40ODQgQzY3LjQxMiw0OS4yOSA2Ny41NjksNDkuMTM0IDY3Ljc2Miw0OS4xMzQgQzY3Ljk1Niw0OS4xMzQgNjguMTEzLDQ5LjI5IDY4LjExMyw0OS40ODQgTDY4LjExMywxMDMuNDg1IEM2OC4xMTMsMTA0LjQ0NSA2OC44MiwxMDUuNjY1IDY5LjY1NywxMDYuMTQ4IEwxMTIuMTMsMTMwLjY3IEMxMTIuNDc0LDEzMC44NjggMTEyLjc5MSwxMzAuOTEzIDExMywxMzAuNzkyIEMxMTMuMjA2LDEzMC42NzMgMTEzLjMyNSwxMzAuMzgxIDExMy4zMjUsMTI5Ljk5MyBMMTEzLjMyNSw3NS45OTIgQzExMy4zMjUsNzUuNzk4IDExMy40ODIsNzUuNjQxIDExMy42NzUsNzUuNjQxIEMxMTMuODY5LDc1LjY0MSAxMTQuMDI1LDc1Ljc5OCAxMTQuMDI1LDc1Ljk5MiBMMTE0LjAyNSwxMjkuOTkzIEMxMTQuMDI1LDEzMC42NDggMTEzLjc4NiwxMzEuMTQ3IDExMy4zNSwxMzEuMzk5IEMxMTMuMTYyLDEzMS41MDcgMTEyLjk1MiwxMzEuNTYxIDExMi43MjcsMTMxLjU2MSIgaWQ9IkZpbGwtMjkiIGZpbGw9IiM0NTVBNjQiPjwvcGF0aD4KICAgICAgICAgICAgICAgICAgICA8cGF0aCBkPSJNMTEyLjg2LDQwLjUxMiBDMTEyLjg2LDQwLjUxMiAxMTIuODYsNDAuNTEyIDExMi44NTksNDAuNTEyIEMxMTAuNTQxLDQwLjUxMiAxMDguMzYsMzkuOTkgMTA2LjcxNywzOS4wNDEgQzEwNS4wMTIsMzguMDU3IDEwNC4wNzQsMzYuNzI2IDEwNC4wNzQsMzUuMjkyIEMxMDQuMDc0LDMzLjg0NyAxMDUuMDI2LDMyLjUwMSAxMDYuNzU0LDMxLjUwNCBMMTE4Ljc5NSwyNC41NTEgQzEyMC40NjMsMjMuNTg5IDEyMi42NjksMjMuMDU4IDEyNS4wMDcsMjMuMDU4IEMxMjcuMzI1LDIzLjA1OCAxMjkuNTA2LDIzLjU4MSAxMzEuMTUsMjQuNTMgQzEzMi44NTQsMjUuNTE0IDEzMy43OTMsMjYuODQ1IDEzMy43OTMsMjguMjc4IEMxMzMuNzkzLDI5LjcyNCAxMzIuODQxLDMxLjA2OSAxMzEuMTEzLDMyLjA2NyBMMTE5LjA3MSwzOS4wMTkgQzExNy40MDMsMzkuOTgyIDExNS4xOTcsNDAuNTEyIDExMi44Niw0MC41MTIgTDExMi44Niw0MC41MTIgWiBNMTI1LjAwNywyMy43NTkgQzEyMi43OSwyMy43NTkgMTIwLjcwOSwyNC4yNTYgMTE5LjE0NiwyNS4xNTggTDEwNy4xMDQsMzIuMTEgQzEwNS42MDIsMzIuOTc4IDEwNC43NzQsMzQuMTA4IDEwNC43NzQsMzUuMjkyIEMxMDQuNzc0LDM2LjQ2NSAxMDUuNTg5LDM3LjU4MSAxMDcuMDY3LDM4LjQzNCBDMTA4LjYwNSwzOS4zMjMgMTEwLjY2MywzOS44MTIgMTEyLjg1OSwzOS44MTIgTDExMi44NiwzOS44MTIgQzExNS4wNzYsMzkuODEyIDExNy4xNTgsMzkuMzE1IDExOC43MjEsMzguNDEzIEwxMzAuNzYyLDMxLjQ2IEMxMzIuMjY0LDMwLjU5MyAxMzMuMDkyLDI5LjQ2MyAxMzMuMDkyLDI4LjI3OCBDMTMzLjA5MiwyNy4xMDYgMTMyLjI3OCwyNS45OSAxMzAuOCwyNS4xMzYgQzEyOS4yNjEsMjQuMjQ4IDEyNy4yMDQsMjMuNzU5IDEyNS4wMDcsMjMuNzU5IEwxMjUuMDA3LDIzLjc1OSBaIiBpZD0iRmlsbC0zMCIgZmlsbD0iIzYwN0Q4QiI+PC9wYXRoPgogICAgICAgICAgICAgICAgICAgIDxwYXRoIGQ9Ik0xNjUuNjMsMTYuMjE5IEwxNTkuODk2LDE5LjUzIEMxNTYuNzI5LDIxLjM1OCAxNTEuNjEsMjEuMzY3IDE0OC40NjMsMTkuNTUgQzE0NS4zMTYsMTcuNzMzIDE0NS4zMzIsMTQuNzc4IDE0OC40OTksMTIuOTQ5IEwxNTQuMjMzLDkuNjM5IEwxNjUuNjMsMTYuMjE5IiBpZD0iRmlsbC0zMSIgZmlsbD0iI0ZBRkFGQSI+PC9wYXRoPgogICAgICAgICAgICAgICAgICAgIDxwYXRoIGQ9Ik0xNTQuMjMzLDEwLjQ0OCBMMTY0LjIyOCwxNi4yMTkgTDE1OS41NDYsMTguOTIzIEMxNTguMTEyLDE5Ljc1IDE1Ni4xOTQsMjAuMjA2IDE1NC4xNDcsMjAuMjA2IEMxNTIuMTE4LDIwLjIwNiAxNTAuMjI0LDE5Ljc1NyAxNDguODE0LDE4Ljk0MyBDMTQ3LjUyNCwxOC4xOTkgMTQ2LjgxNCwxNy4yNDkgMTQ2LjgxNCwxNi4yNjkgQzE0Ni44MTQsMTUuMjc4IDE0Ny41MzcsMTQuMzE0IDE0OC44NSwxMy41NTYgTDE1NC4yMzMsMTAuNDQ4IE0xNTQuMjMzLDkuNjM5IEwxNDguNDk5LDEyLjk0OSBDMTQ1LjMzMiwxNC43NzggMTQ1LjMxNiwxNy43MzMgMTQ4LjQ2MywxOS41NSBDMTUwLjAzMSwyMC40NTUgMTUyLjA4NiwyMC45MDcgMTU0LjE0NywyMC45MDcgQzE1Ni4yMjQsMjAuOTA3IDE1OC4zMDYsMjAuNDQ3IDE1OS44OTYsMTkuNTMgTDE2NS42MywxNi4yMTkgTDE1NC4yMzMsOS42MzkiIGlkPSJGaWxsLTMyIiBmaWxsPSIjNjA3RDhCIj48L3BhdGg+CiAgICAgICAgICAgICAgICAgICAgPHBhdGggZD0iTTE0NS40NDUsNzIuNjY3IEwxNDUuNDQ1LDcyLjY2NyBDMTQzLjY3Miw3Mi42NjcgMTQyLjIwNCw3MS44MTcgMTQxLjIwMiw3MC40MjIgQzE0MS4xMzUsNzAuMzMgMTQxLjE0NSw3MC4xNDcgMTQxLjIyNSw3MC4wNjYgQzE0MS4zMDUsNjkuOTg1IDE0MS40MzIsNjkuOTQ2IDE0MS41MjUsNzAuMDExIEMxNDIuMzA2LDcwLjU1OSAxNDMuMjMxLDcwLjgyMyAxNDQuMjc2LDcwLjgyMiBDMTQ1LjU5OCw3MC44MjIgMTQ3LjAzLDcwLjM3NiAxNDguNTMyLDY5LjUwOSBDMTUzLjg0Miw2Ni40NDMgMTU4LjE2Myw1OC45ODcgMTU4LjE2Myw1Mi44OTQgQzE1OC4xNjMsNTAuOTY3IDE1Ny43MjEsNDkuMzMyIDE1Ni44ODQsNDguMTY4IEMxNTYuODE4LDQ4LjA3NiAxNTYuODI4LDQ3Ljk0OCAxNTYuOTA4LDQ3Ljg2NyBDMTU2Ljk4OCw0Ny43ODYgMTU3LjExNCw0Ny43NzQgMTU3LjIwOCw0Ny44NCBDMTU4Ljg3OCw0OS4wMTIgMTU5Ljc5OCw1MS4yMiAxNTkuNzk4LDU0LjA1OSBDMTU5Ljc5OCw2MC4zMDEgMTU1LjM3Myw2OC4wNDYgMTQ5LjkzMyw3MS4xODYgQzE0OC4zNiw3Mi4wOTQgMTQ2Ljg1LDcyLjY2NyAxNDUuNDQ1LDcyLjY2NyBMMTQ1LjQ0NSw3Mi42NjcgWiBNMTQyLjQ3Niw3MSBDMTQzLjI5LDcxLjY1MSAxNDQuMjk2LDcyLjAwMiAxNDUuNDQ1LDcyLjAwMiBDMTQ2Ljc2Nyw3Mi4wMDIgMTQ4LjE5OCw3MS41NSAxNDkuNyw3MC42ODIgQzE1NS4wMSw2Ny42MTcgMTU5LjMzMSw2MC4xNTkgMTU5LjMzMSw1NC4wNjUgQzE1OS4zMzEsNTIuMDg1IDE1OC44NjgsNTAuNDM1IDE1OC4wMDYsNDkuMjcyIEMxNTguNDE3LDUwLjMwNyAxNTguNjMsNTEuNTMyIDE1OC42Myw1Mi44OTIgQzE1OC42Myw1OS4xMzQgMTU0LjIwNSw2Ni43NjcgMTQ4Ljc2NSw2OS45MDcgQzE0Ny4xOTIsNzAuODE2IDE0NS42ODEsNzEuMjgzIDE0NC4yNzYsNzEuMjgzIEMxNDMuNjM0LDcxLjI4MyAxNDMuMDMzLDcxLjE5MiAxNDIuNDc2LDcxIEwxNDIuNDc2LDcxIFoiIGlkPSJGaWxsLTMzIiBmaWxsPSIjNjA3RDhCIj48L3BhdGg+CiAgICAgICAgICAgICAgICAgICAgPHBhdGggZD0iTTE0OC42NDgsNjkuNzA0IEMxNTQuMDMyLDY2LjU5NiAxNTguMzk2LDU5LjA2OCAxNTguMzk2LDUyLjg5MSBDMTU4LjM5Niw1MC44MzkgMTU3LjkxMyw0OS4xOTggMTU3LjA3NCw0OC4wMyBDMTU1LjI4OSw0Ni43NzggMTUyLjY5OSw0Ni44MzYgMTQ5LjgxNiw0OC41MDEgQzE0NC40MzMsNTEuNjA5IDE0MC4wNjgsNTkuMTM3IDE0MC4wNjgsNjUuMzE0IEMxNDAuMDY4LDY3LjM2NSAxNDAuNTUyLDY5LjAwNiAxNDEuMzkxLDcwLjE3NCBDMTQzLjE3Niw3MS40MjcgMTQ1Ljc2NSw3MS4zNjkgMTQ4LjY0OCw2OS43MDQiIGlkPSJGaWxsLTM0IiBmaWxsPSIjRkFGQUZBIj48L3BhdGg+CiAgICAgICAgICAgICAgICAgICAgPHBhdGggZD0iTTE0NC4yNzYsNzEuMjc2IEwxNDQuMjc2LDcxLjI3NiBDMTQzLjEzMyw3MS4yNzYgMTQyLjExOCw3MC45NjkgMTQxLjI1Nyw3MC4zNjUgQzE0MS4yMzYsNzAuMzUxIDE0MS4yMTcsNzAuMzMyIDE0MS4yMDIsNzAuMzExIEMxNDAuMzA3LDY5LjA2NyAxMzkuODM1LDY3LjMzOSAxMzkuODM1LDY1LjMxNCBDMTM5LjgzNSw1OS4wNzMgMTQ0LjI2LDUxLjQzOSAxNDkuNyw0OC4yOTggQzE1MS4yNzMsNDcuMzkgMTUyLjc4NCw0Ni45MjkgMTU0LjE4OSw0Ni45MjkgQzE1NS4zMzIsNDYuOTI5IDE1Ni4zNDcsNDcuMjM2IDE1Ny4yMDgsNDcuODM5IEMxNTcuMjI5LDQ3Ljg1NCAxNTcuMjQ4LDQ3Ljg3MyAxNTcuMjYzLDQ3Ljg5NCBDMTU4LjE1Nyw0OS4xMzggMTU4LjYzLDUwLjg2NSAxNTguNjMsNTIuODkxIEMxNTguNjMsNTkuMTMyIDE1NC4yMDUsNjYuNzY2IDE0OC43NjUsNjkuOTA3IEMxNDcuMTkyLDcwLjgxNSAxNDUuNjgxLDcxLjI3NiAxNDQuMjc2LDcxLjI3NiBMMTQ0LjI3Niw3MS4yNzYgWiBNMTQxLjU1OCw3MC4xMDQgQzE0Mi4zMzEsNzAuNjM3IDE0My4yNDUsNzEuMDA1IDE0NC4yNzYsNzEuMDA1IEMxNDUuNTk4LDcxLjAwNSAxNDcuMDMsNzAuNDY3IDE0OC41MzIsNjkuNiBDMTUzLjg0Miw2Ni41MzQgMTU4LjE2Myw1OS4wMzMgMTU4LjE2Myw1Mi45MzkgQzE1OC4xNjMsNTEuMDMxIDE1Ny43MjksNDkuMzg1IDE1Ni45MDcsNDguMjIzIEMxNTYuMTMzLDQ3LjY5MSAxNTUuMjE5LDQ3LjQwOSAxNTQuMTg5LDQ3LjQwOSBDMTUyLjg2Nyw0Ny40MDkgMTUxLjQzNSw0Ny44NDIgMTQ5LjkzMyw0OC43MDkgQzE0NC42MjMsNTEuNzc1IDE0MC4zMDIsNTkuMjczIDE0MC4zMDIsNjUuMzY2IEMxNDAuMzAyLDY3LjI3NiAxNDAuNzM2LDY4Ljk0MiAxNDEuNTU4LDcwLjEwNCBMMTQxLjU1OCw3MC4xMDQgWiIgaWQ9IkZpbGwtMzUiIGZpbGw9IiM2MDdEOEIiPjwvcGF0aD4KICAgICAgICAgICAgICAgICAgICA8cGF0aCBkPSJNMTUwLjcyLDY1LjM2MSBMMTUwLjM1Nyw2NS4wNjYgQzE1MS4xNDcsNjQuMDkyIDE1MS44NjksNjMuMDQgMTUyLjUwNSw2MS45MzggQzE1My4zMTMsNjAuNTM5IDE1My45NzgsNTkuMDY3IDE1NC40ODIsNTcuNTYzIEwxNTQuOTI1LDU3LjcxMiBDMTU0LjQxMiw1OS4yNDUgMTUzLjczMyw2MC43NDUgMTUyLjkxLDYyLjE3MiBDMTUyLjI2Miw2My4yOTUgMTUxLjUyNSw2NC4zNjggMTUwLjcyLDY1LjM2MSIgaWQ9IkZpbGwtMzYiIGZpbGw9IiM2MDdEOEIiPjwvcGF0aD4KICAgICAgICAgICAgICAgICAgICA8cGF0aCBkPSJNMTE1LjkxNyw4NC41MTQgTDExNS41NTQsODQuMjIgQzExNi4zNDQsODMuMjQ1IDExNy4wNjYsODIuMTk0IDExNy43MDIsODEuMDkyIEMxMTguNTEsNzkuNjkyIDExOS4xNzUsNzguMjIgMTE5LjY3OCw3Ni43MTcgTDEyMC4xMjEsNzYuODY1IEMxMTkuNjA4LDc4LjM5OCAxMTguOTMsNzkuODk5IDExOC4xMDYsODEuMzI2IEMxMTcuNDU4LDgyLjQ0OCAxMTYuNzIyLDgzLjUyMSAxMTUuOTE3LDg0LjUxNCIgaWQ9IkZpbGwtMzciIGZpbGw9IiM2MDdEOEIiPjwvcGF0aD4KICAgICAgICAgICAgICAgICAgICA8cGF0aCBkPSJNMTE0LDEzMC40NzYgTDExNCwxMzAuMDA4IEwxMTQsNzYuMDUyIEwxMTQsNzUuNTg0IEwxMTQsNzYuMDUyIEwxMTQsMTMwLjAwOCBMMTE0LDEzMC40NzYiIGlkPSJGaWxsLTM4IiBmaWxsPSIjNjA3RDhCIj48L3BhdGg+CiAgICAgICAgICAgICAgICA8L2c+CiAgICAgICAgICAgICAgICA8ZyBpZD0iSW1wb3J0ZWQtTGF5ZXJzLUNvcHkiIHRyYW5zZm9ybT0idHJhbnNsYXRlKDYyLjAwMDAwMCwgMC4wMDAwMDApIiBza2V0Y2g6dHlwZT0iTVNTaGFwZUdyb3VwIj4KICAgICAgICAgICAgICAgICAgICA8cGF0aCBkPSJNMTkuODIyLDM3LjQ3NCBDMTkuODM5LDM3LjMzOSAxOS43NDcsMzcuMTk0IDE5LjU1NSwzNy4wODIgQzE5LjIyOCwzNi44OTQgMTguNzI5LDM2Ljg3MiAxOC40NDYsMzcuMDM3IEwxMi40MzQsNDAuNTA4IEMxMi4zMDMsNDAuNTg0IDEyLjI0LDQwLjY4NiAxMi4yNDMsNDAuNzkzIEMxMi4yNDUsNDAuOTI1IDEyLjI0NSw0MS4yNTQgMTIuMjQ1LDQxLjM3MSBMMTIuMjQ1LDQxLjQxNCBMMTIuMjM4LDQxLjU0MiBDOC4xNDgsNDMuODg3IDUuNjQ3LDQ1LjMyMSA1LjY0Nyw0NS4zMjEgQzUuNjQ2LDQ1LjMyMSAzLjU3LDQ2LjM2NyAyLjg2LDUwLjUxMyBDMi44Niw1MC41MTMgMS45NDgsNTcuNDc0IDEuOTYyLDcwLjI1OCBDMS45NzcsODIuODI4IDIuNTY4LDg3LjMyOCAzLjEyOSw5MS42MDkgQzMuMzQ5LDkzLjI5MyA2LjEzLDkzLjczNCA2LjEzLDkzLjczNCBDNi40NjEsOTMuNzc0IDYuODI4LDkzLjcwNyA3LjIxLDkzLjQ4NiBMODIuNDgzLDQ5LjkzNSBDODQuMjkxLDQ4Ljg2NiA4NS4xNSw0Ni4yMTYgODUuNTM5LDQzLjY1MSBDODYuNzUyLDM1LjY2MSA4Ny4yMTQsMTAuNjczIDg1LjI2NCwzLjc3MyBDODUuMDY4LDMuMDggODQuNzU0LDIuNjkgODQuMzk2LDIuNDkxIEw4Mi4zMSwxLjcwMSBDODEuNTgzLDEuNzI5IDgwLjg5NCwyLjE2OCA4MC43NzYsMi4yMzYgQzgwLjYzNiwyLjMxNyA0MS44MDcsMjQuNTg1IDIwLjAzMiwzNy4wNzIgTDE5LjgyMiwzNy40NzQiIGlkPSJGaWxsLTEiIGZpbGw9IiNGRkZGRkYiPjwvcGF0aD4KICAgICAgICAgICAgICAgICAgICA8cGF0aCBkPSJNODIuMzExLDEuNzAxIEw4NC4zOTYsMi40OTEgQzg0Ljc1NCwyLjY5IDg1LjA2OCwzLjA4IDg1LjI2NCwzLjc3MyBDODcuMjEzLDEwLjY3MyA4Ni43NTEsMzUuNjYgODUuNTM5LDQzLjY1MSBDODUuMTQ5LDQ2LjIxNiA4NC4yOSw0OC44NjYgODIuNDgzLDQ5LjkzNSBMNy4yMSw5My40ODYgQzYuODk3LDkzLjY2NyA2LjU5NSw5My43NDQgNi4zMTQsOTMuNzQ0IEw2LjEzMSw5My43MzMgQzYuMTMxLDkzLjczNCAzLjM0OSw5My4yOTMgMy4xMjgsOTEuNjA5IEMyLjU2OCw4Ny4zMjcgMS45NzcsODIuODI4IDEuOTYzLDcwLjI1OCBDMS45NDgsNTcuNDc0IDIuODYsNTAuNTEzIDIuODYsNTAuNTEzIEMzLjU3LDQ2LjM2NyA1LjY0Nyw0NS4zMjEgNS42NDcsNDUuMzIxIEM1LjY0Nyw0NS4zMjEgOC4xNDgsNDMuODg3IDEyLjIzOCw0MS41NDIgTDEyLjI0NSw0MS40MTQgTDEyLjI0NSw0MS4zNzEgQzEyLjI0NSw0MS4yNTQgMTIuMjQ1LDQwLjkyNSAxMi4yNDMsNDAuNzkzIEMxMi4yNCw0MC42ODYgMTIuMzAyLDQwLjU4MyAxMi40MzQsNDAuNTA4IEwxOC40NDYsMzcuMDM2IEMxOC41NzQsMzYuOTYyIDE4Ljc0NiwzNi45MjYgMTguOTI3LDM2LjkyNiBDMTkuMTQ1LDM2LjkyNiAxOS4zNzYsMzYuOTc5IDE5LjU1NCwzNy4wODIgQzE5Ljc0NywzNy4xOTQgMTkuODM5LDM3LjM0IDE5LjgyMiwzNy40NzQgTDIwLjAzMywzNy4wNzIgQzQxLjgwNiwyNC41ODUgODAuNjM2LDIuMzE4IDgwLjc3NywyLjIzNiBDODAuODk0LDIuMTY4IDgxLjU4MywxLjcyOSA4Mi4zMTEsMS43MDEgTTgyLjMxMSwwLjcwNCBMODIuMjcyLDAuNzA1IEM4MS42NTQsMC43MjggODAuOTg5LDAuOTQ5IDgwLjI5OCwxLjM2MSBMODAuMjc3LDEuMzczIEM4MC4xMjksMS40NTggNTkuNzY4LDEzLjEzNSAxOS43NTgsMzYuMDc5IEMxOS41LDM1Ljk4MSAxOS4yMTQsMzUuOTI5IDE4LjkyNywzNS45MjkgQzE4LjU2MiwzNS45MjkgMTguMjIzLDM2LjAxMyAxNy45NDcsMzYuMTczIEwxMS45MzUsMzkuNjQ0IEMxMS40OTMsMzkuODk5IDExLjIzNiw0MC4zMzQgMTEuMjQ2LDQwLjgxIEwxMS4yNDcsNDAuOTYgTDUuMTY3LDQ0LjQ0NyBDNC43OTQsNDQuNjQ2IDIuNjI1LDQ1Ljk3OCAxLjg3Nyw1MC4zNDUgTDEuODcxLDUwLjM4NCBDMS44NjIsNTAuNDU0IDAuOTUxLDU3LjU1NyAwLjk2NSw3MC4yNTkgQzAuOTc5LDgyLjg3OSAxLjU2OCw4Ny4zNzUgMi4xMzcsOTEuNzI0IEwyLjEzOSw5MS43MzkgQzIuNDQ3LDk0LjA5NCA1LjYxNCw5NC42NjIgNS45NzUsOTQuNzE5IEw2LjAwOSw5NC43MjMgQzYuMTEsOTQuNzM2IDYuMjEzLDk0Ljc0MiA2LjMxNCw5NC43NDIgQzYuNzksOTQuNzQyIDcuMjYsOTQuNjEgNy43MSw5NC4zNSBMODIuOTgzLDUwLjc5OCBDODQuNzk0LDQ5LjcyNyA4NS45ODIsNDcuMzc1IDg2LjUyNSw0My44MDEgQzg3LjcxMSwzNS45ODcgODguMjU5LDEwLjcwNSA4Ni4yMjQsMy41MDIgQzg1Ljk3MSwyLjYwOSA4NS41MiwxLjk3NSA4NC44ODEsMS42MiBMODQuNzQ5LDEuNTU4IEw4Mi42NjQsMC43NjkgQzgyLjU1MSwwLjcyNSA4Mi40MzEsMC43MDQgODIuMzExLDAuNzA0IiBpZD0iRmlsbC0yIiBmaWxsPSIjNDU1QTY0Ij48L3BhdGg+CiAgICAgICAgICAgICAgICAgICAgPHBhdGggZD0iTTY2LjI2NywxMS41NjUgTDY3Ljc2MiwxMS45OTkgTDExLjQyMyw0NC4zMjUiIGlkPSJGaWxsLTMiIGZpbGw9IiNGRkZGRkYiPjwvcGF0aD4KICAgICAgICAgICAgICAgICAgICA8cGF0aCBkPSJNMTIuMjAyLDkwLjU0NSBDMTIuMDI5LDkwLjU0NSAxMS44NjIsOTAuNDU1IDExLjc2OSw5MC4yOTUgQzExLjYzMiw5MC4wNTcgMTEuNzEzLDg5Ljc1MiAxMS45NTIsODkuNjE0IEwzMC4zODksNzguOTY5IEMzMC42MjgsNzguODMxIDMwLjkzMyw3OC45MTMgMzEuMDcxLDc5LjE1MiBDMzEuMjA4LDc5LjM5IDMxLjEyNyw3OS42OTYgMzAuODg4LDc5LjgzMyBMMTIuNDUxLDkwLjQ3OCBMMTIuMjAyLDkwLjU0NSIgaWQ9IkZpbGwtNCIgZmlsbD0iIzYwN0Q4QiI+PC9wYXRoPgogICAgICAgICAgICAgICAgICAgIDxwYXRoIGQ9Ik0xMy43NjQsNDIuNjU0IEwxMy42NTYsNDIuNTkyIEwxMy43MDIsNDIuNDIxIEwxOC44MzcsMzkuNDU3IEwxOS4wMDcsMzkuNTAyIEwxOC45NjIsMzkuNjczIEwxMy44MjcsNDIuNjM3IEwxMy43NjQsNDIuNjU0IiBpZD0iRmlsbC01IiBmaWxsPSIjNjA3RDhCIj48L3BhdGg+CiAgICAgICAgICAgICAgICAgICAgPHBhdGggZD0iTTguNTIsOTAuMzc1IEw4LjUyLDQ2LjQyMSBMOC41ODMsNDYuMzg1IEw3NS44NCw3LjU1NCBMNzUuODQsNTEuNTA4IEw3NS43NzgsNTEuNTQ0IEw4LjUyLDkwLjM3NSBMOC41Miw5MC4zNzUgWiBNOC43Nyw0Ni41NjQgTDguNzcsODkuOTQ0IEw3NS41OTEsNTEuMzY1IEw3NS41OTEsNy45ODUgTDguNzcsNDYuNTY0IEw4Ljc3LDQ2LjU2NCBaIiBpZD0iRmlsbC02IiBmaWxsPSIjNjA3RDhCIj48L3BhdGg+CiAgICAgICAgICAgICAgICAgICAgPHBhdGggZD0iTTI0Ljk4Niw4My4xODIgQzI0Ljc1Niw4My4zMzEgMjQuMzc0LDgzLjU2NiAyNC4xMzcsODMuNzA1IEwxMi42MzIsOTAuNDA2IEMxMi4zOTUsOTAuNTQ1IDEyLjQyNiw5MC42NTggMTIuNyw5MC42NTggTDEzLjI2NSw5MC42NTggQzEzLjU0LDkwLjY1OCAxMy45NTgsOTAuNTQ1IDE0LjE5NSw5MC40MDYgTDI1LjcsODMuNzA1IEMyNS45MzcsODMuNTY2IDI2LjEyOCw4My40NTIgMjYuMTI1LDgzLjQ0OSBDMjYuMTIyLDgzLjQ0NyAyNi4xMTksODMuMjIgMjYuMTE5LDgyLjk0NiBDMjYuMTE5LDgyLjY3MiAyNS45MzEsODIuNTY5IDI1LjcwMSw4Mi43MTkgTDI0Ljk4Niw4My4xODIiIGlkPSJGaWxsLTciIGZpbGw9IiM2MDdEOEIiPjwvcGF0aD4KICAgICAgICAgICAgICAgICAgICA8cGF0aCBkPSJNMTMuMjY2LDkwLjc4MiBMMTIuNyw5MC43ODIgQzEyLjUsOTAuNzgyIDEyLjM4NCw5MC43MjYgMTIuMzU0LDkwLjYxNiBDMTIuMzI0LDkwLjUwNiAxMi4zOTcsOTAuMzk5IDEyLjU2OSw5MC4yOTkgTDI0LjA3NCw4My41OTcgQzI0LjMxLDgzLjQ1OSAyNC42ODksODMuMjI2IDI0LjkxOCw4My4wNzggTDI1LjYzMyw4Mi42MTQgQzI1LjcyMyw4Mi41NTUgMjUuODEzLDgyLjUyNSAyNS44OTksODIuNTI1IEMyNi4wNzEsODIuNTI1IDI2LjI0NCw4Mi42NTUgMjYuMjQ0LDgyLjk0NiBDMjYuMjQ0LDgzLjE2IDI2LjI0NSw4My4zMDkgMjYuMjQ3LDgzLjM4MyBMMjYuMjUzLDgzLjM4NyBMMjYuMjQ5LDgzLjQ1NiBDMjYuMjQ2LDgzLjUzMSAyNi4yNDYsODMuNTMxIDI1Ljc2Myw4My44MTIgTDE0LjI1OCw5MC41MTQgQzE0LDkwLjY2NSAxMy41NjQsOTAuNzgyIDEzLjI2Niw5MC43ODIgTDEzLjI2Niw5MC43ODIgWiBNMTIuNjY2LDkwLjUzMiBMMTIuNyw5MC41MzMgTDEzLjI2Niw5MC41MzMgQzEzLjUxOCw5MC41MzMgMTMuOTE1LDkwLjQyNSAxNC4xMzIsOTAuMjk5IEwyNS42MzcsODMuNTk3IEMyNS44MDUsODMuNDk5IDI1LjkzMSw4My40MjQgMjUuOTk4LDgzLjM4MyBDMjUuOTk0LDgzLjI5OSAyNS45OTQsODMuMTY1IDI1Ljk5NCw4Mi45NDYgTDI1Ljg5OSw4Mi43NzUgTDI1Ljc2OCw4Mi44MjQgTDI1LjA1NCw4My4yODcgQzI0LjgyMiw4My40MzcgMjQuNDM4LDgzLjY3MyAyNC4yLDgzLjgxMiBMMTIuNjk1LDkwLjUxNCBMMTIuNjY2LDkwLjUzMiBMMTIuNjY2LDkwLjUzMiBaIiBpZD0iRmlsbC04IiBmaWxsPSIjNjA3RDhCIj48L3BhdGg+CiAgICAgICAgICAgICAgICAgICAgPHBhdGggZD0iTTEzLjI2Niw4OS44NzEgTDEyLjcsODkuODcxIEMxMi41LDg5Ljg3MSAxMi4zODQsODkuODE1IDEyLjM1NCw4OS43MDUgQzEyLjMyNCw4OS41OTUgMTIuMzk3LDg5LjQ4OCAxMi41NjksODkuMzg4IEwyNC4wNzQsODIuNjg2IEMyNC4zMzIsODIuNTM1IDI0Ljc2OCw4Mi40MTggMjUuMDY3LDgyLjQxOCBMMjUuNjMyLDgyLjQxOCBDMjUuODMyLDgyLjQxOCAyNS45NDgsODIuNDc0IDI1Ljk3OCw4Mi41ODQgQzI2LjAwOCw4Mi42OTQgMjUuOTM1LDgyLjgwMSAyNS43NjMsODIuOTAxIEwxNC4yNTgsODkuNjAzIEMxNCw4OS43NTQgMTMuNTY0LDg5Ljg3MSAxMy4yNjYsODkuODcxIEwxMy4yNjYsODkuODcxIFogTTEyLjY2Niw4OS42MjEgTDEyLjcsODkuNjIyIEwxMy4yNjYsODkuNjIyIEMxMy41MTgsODkuNjIyIDEzLjkxNSw4OS41MTUgMTQuMTMyLDg5LjM4OCBMMjUuNjM3LDgyLjY4NiBMMjUuNjY3LDgyLjY2OCBMMjUuNjMyLDgyLjY2NyBMMjUuMDY3LDgyLjY2NyBDMjQuODE1LDgyLjY2NyAyNC40MTgsODIuNzc1IDI0LjIsODIuOTAxIEwxMi42OTUsODkuNjAzIEwxMi42NjYsODkuNjIxIEwxMi42NjYsODkuNjIxIFoiIGlkPSJGaWxsLTkiIGZpbGw9IiM2MDdEOEIiPjwvcGF0aD4KICAgICAgICAgICAgICAgICAgICA8cGF0aCBkPSJNMTIuMzcsOTAuODAxIEwxMi4zNyw4OS41NTQgTDEyLjM3LDkwLjgwMSIgaWQ9IkZpbGwtMTAiIGZpbGw9IiM2MDdEOEIiPjwvcGF0aD4KICAgICAgICAgICAgICAgICAgICA8cGF0aCBkPSJNNi4xMyw5My45MDEgQzUuMzc5LDkzLjgwOCA0LjgxNiw5My4xNjQgNC42OTEsOTIuNTI1IEMzLjg2LDg4LjI4NyAzLjU0LDgzLjc0MyAzLjUyNiw3MS4xNzMgQzMuNTExLDU4LjM4OSA0LjQyMyw1MS40MjggNC40MjMsNTEuNDI4IEM1LjEzNCw0Ny4yODIgNy4yMSw0Ni4yMzYgNy4yMSw0Ni4yMzYgQzcuMjEsNDYuMjM2IDgxLjY2NywzLjI1IDgyLjA2OSwzLjAxNyBDODIuMjkyLDIuODg4IDg0LjU1NiwxLjQzMyA4NS4yNjQsMy45NCBDODcuMjE0LDEwLjg0IDg2Ljc1MiwzNS44MjcgODUuNTM5LDQzLjgxOCBDODUuMTUsNDYuMzgzIDg0LjI5MSw0OS4wMzMgODIuNDgzLDUwLjEwMSBMNy4yMSw5My42NTMgQzYuODI4LDkzLjg3NCA2LjQ2MSw5My45NDEgNi4xMyw5My45MDEgQzYuMTMsOTMuOTAxIDMuMzQ5LDkzLjQ2IDMuMTI5LDkxLjc3NiBDMi41NjgsODcuNDk1IDEuOTc3LDgyLjk5NSAxLjk2Miw3MC40MjUgQzEuOTQ4LDU3LjY0MSAyLjg2LDUwLjY4IDIuODYsNTAuNjggQzMuNTcsNDYuNTM0IDUuNjQ3LDQ1LjQ4OSA1LjY0Nyw0NS40ODkgQzUuNjQ2LDQ1LjQ4OSA4LjA2NSw0NC4wOTIgMTIuMjQ1LDQxLjY3OSBMMTMuMTE2LDQxLjU2IEwxOS43MTUsMzcuNzMgTDE5Ljc2MSwzNy4yNjkgTDYuMTMsOTMuOTAxIiBpZD0iRmlsbC0xMSIgZmlsbD0iI0ZBRkFGQSI+PC9wYXRoPgogICAgICAgICAgICAgICAgICAgIDxwYXRoIGQ9Ik02LjMxNyw5NC4xNjEgTDYuMTAyLDk0LjE0OCBMNi4xMDEsOTQuMTQ4IEw1Ljg1Nyw5NC4xMDEgQzUuMTM4LDkzLjk0NSAzLjA4NSw5My4zNjUgMi44ODEsOTEuODA5IEMyLjMxMyw4Ny40NjkgMS43MjcsODIuOTk2IDEuNzEzLDcwLjQyNSBDMS42OTksNTcuNzcxIDIuNjA0LDUwLjcxOCAyLjYxMyw1MC42NDggQzMuMzM4LDQ2LjQxNyA1LjQ0NSw0NS4zMSA1LjUzNSw0NS4yNjYgTDEyLjE2Myw0MS40MzkgTDEzLjAzMyw0MS4zMiBMMTkuNDc5LDM3LjU3OCBMMTkuNTEzLDM3LjI0NCBDMTkuNTI2LDM3LjEwNyAxOS42NDcsMzcuMDA4IDE5Ljc4NiwzNy4wMjEgQzE5LjkyMiwzNy4wMzQgMjAuMDIzLDM3LjE1NiAyMC4wMDksMzcuMjkzIEwxOS45NSwzNy44ODIgTDEzLjE5OCw0MS44MDEgTDEyLjMyOCw0MS45MTkgTDUuNzcyLDQ1LjcwNCBDNS43NDEsNDUuNzIgMy43ODIsNDYuNzcyIDMuMTA2LDUwLjcyMiBDMy4wOTksNTAuNzgyIDIuMTk4LDU3LjgwOCAyLjIxMiw3MC40MjQgQzIuMjI2LDgyLjk2MyAyLjgwOSw4Ny40MiAzLjM3Myw5MS43MjkgQzMuNDY0LDkyLjQyIDQuMDYyLDkyLjg4MyA0LjY4Miw5My4xODEgQzQuNTY2LDkyLjk4NCA0LjQ4Niw5Mi43NzYgNC40NDYsOTIuNTcyIEMzLjY2NSw4OC41ODggMy4yOTEsODQuMzcgMy4yNzYsNzEuMTczIEMzLjI2Miw1OC41MiA0LjE2Nyw1MS40NjYgNC4xNzYsNTEuMzk2IEM0LjkwMSw0Ny4xNjUgNy4wMDgsNDYuMDU5IDcuMDk4LDQ2LjAxNCBDNy4wOTQsNDYuMDE1IDgxLjU0MiwzLjAzNCA4MS45NDQsMi44MDIgTDgxLjk3MiwyLjc4NSBDODIuODc2LDIuMjQ3IDgzLjY5MiwyLjA5NyA4NC4zMzIsMi4zNTIgQzg0Ljg4NywyLjU3MyA4NS4yODEsMy4wODUgODUuNTA0LDMuODcyIEM4Ny41MTgsMTEgODYuOTY0LDM2LjA5MSA4NS43ODUsNDMuODU1IEM4NS4yNzgsNDcuMTk2IDg0LjIxLDQ5LjM3IDgyLjYxLDUwLjMxNyBMNy4zMzUsOTMuODY5IEM2Ljk5OSw5NC4wNjMgNi42NTgsOTQuMTYxIDYuMzE3LDk0LjE2MSBMNi4zMTcsOTQuMTYxIFogTTYuMTcsOTMuNjU0IEM2LjQ2Myw5My42OSA2Ljc3NCw5My42MTcgNy4wODUsOTMuNDM3IEw4Mi4zNTgsNDkuODg2IEM4NC4xODEsNDguODA4IDg0Ljk2LDQ1Ljk3MSA4NS4yOTIsNDMuNzggQzg2LjQ2NiwzNi4wNDkgODcuMDIzLDExLjA4NSA4NS4wMjQsNC4wMDggQzg0Ljg0NiwzLjM3NyA4NC41NTEsMi45NzYgODQuMTQ4LDIuODE2IEM4My42NjQsMi42MjMgODIuOTgyLDIuNzY0IDgyLjIyNywzLjIxMyBMODIuMTkzLDMuMjM0IEM4MS43OTEsMy40NjYgNy4zMzUsNDYuNDUyIDcuMzM1LDQ2LjQ1MiBDNy4zMDQsNDYuNDY5IDUuMzQ2LDQ3LjUyMSA0LjY2OSw1MS40NzEgQzQuNjYyLDUxLjUzIDMuNzYxLDU4LjU1NiAzLjc3NSw3MS4xNzMgQzMuNzksODQuMzI4IDQuMTYxLDg4LjUyNCA0LjkzNiw5Mi40NzYgQzUuMDI2LDkyLjkzNyA1LjQxMiw5My40NTkgNS45NzMsOTMuNjE1IEM2LjA4Nyw5My42NCA2LjE1OCw5My42NTIgNi4xNjksOTMuNjU0IEw2LjE3LDkzLjY1NCBMNi4xNyw5My42NTQgWiIgaWQ9IkZpbGwtMTIiIGZpbGw9IiM0NTVBNjQiPjwvcGF0aD4KICAgICAgICAgICAgICAgICAgICA8cGF0aCBkPSJNNy4zMTcsNjguOTgyIEM3LjgwNiw2OC43MDEgOC4yMDIsNjguOTI2IDguMjAyLDY5LjQ4NyBDOC4yMDIsNzAuMDQ3IDcuODA2LDcwLjczIDcuMzE3LDcxLjAxMiBDNi44MjksNzEuMjk0IDYuNDMzLDcxLjA2OSA2LjQzMyw3MC41MDggQzYuNDMzLDY5Ljk0OCA2LjgyOSw2OS4yNjUgNy4zMTcsNjguOTgyIiBpZD0iRmlsbC0xMyIgZmlsbD0iI0ZGRkZGRiI+PC9wYXRoPgogICAgICAgICAgICAgICAgICAgIDxwYXRoIGQ9Ik02LjkyLDcxLjEzMyBDNi42MzEsNzEuMTMzIDYuNDMzLDcwLjkwNSA2LjQzMyw3MC41MDggQzYuNDMzLDY5Ljk0OCA2LjgyOSw2OS4yNjUgNy4zMTcsNjguOTgyIEM3LjQ2LDY4LjkgNy41OTUsNjguODYxIDcuNzE0LDY4Ljg2MSBDOC4wMDMsNjguODYxIDguMjAyLDY5LjA5IDguMjAyLDY5LjQ4NyBDOC4yMDIsNzAuMDQ3IDcuODA2LDcwLjczIDcuMzE3LDcxLjAxMiBDNy4xNzQsNzEuMDk0IDcuMDM5LDcxLjEzMyA2LjkyLDcxLjEzMyBNNy43MTQsNjguNjc0IEM3LjU1Nyw2OC42NzQgNy4zOTIsNjguNzIzIDcuMjI0LDY4LjgyMSBDNi42NzYsNjkuMTM4IDYuMjQ2LDY5Ljg3OSA2LjI0Niw3MC41MDggQzYuMjQ2LDcwLjk5NCA2LjUxNyw3MS4zMiA2LjkyLDcxLjMyIEM3LjA3OCw3MS4zMiA3LjI0Myw3MS4yNzEgNy40MTEsNzEuMTc0IEM3Ljk1OSw3MC44NTcgOC4zODksNzAuMTE3IDguMzg5LDY5LjQ4NyBDOC4zODksNjkuMDAxIDguMTE3LDY4LjY3NCA3LjcxNCw2OC42NzQiIGlkPSJGaWxsLTE0IiBmaWxsPSIjODA5N0EyIj48L3BhdGg+CiAgICAgICAgICAgICAgICAgICAgPHBhdGggZD0iTTYuOTIsNzAuOTQ3IEM2LjY0OSw3MC45NDcgNi42MjEsNzAuNjQgNi42MjEsNzAuNTA4IEM2LjYyMSw3MC4wMTcgNi45ODIsNjkuMzkyIDcuNDExLDY5LjE0NSBDNy41MjEsNjkuMDgyIDcuNjI1LDY5LjA0OSA3LjcxNCw2OS4wNDkgQzcuOTg2LDY5LjA0OSA4LjAxNSw2OS4zNTUgOC4wMTUsNjkuNDg3IEM4LjAxNSw2OS45NzggNy42NTIsNzAuNjAzIDcuMjI0LDcwLjg1MSBDNy4xMTUsNzAuOTE0IDcuMDEsNzAuOTQ3IDYuOTIsNzAuOTQ3IE03LjcxNCw2OC44NjEgQzcuNTk1LDY4Ljg2MSA3LjQ2LDY4LjkgNy4zMTcsNjguOTgyIEM2LjgyOSw2OS4yNjUgNi40MzMsNjkuOTQ4IDYuNDMzLDcwLjUwOCBDNi40MzMsNzAuOTA1IDYuNjMxLDcxLjEzMyA2LjkyLDcxLjEzMyBDNy4wMzksNzEuMTMzIDcuMTc0LDcxLjA5NCA3LjMxNyw3MS4wMTIgQzcuODA2LDcwLjczIDguMjAyLDcwLjA0NyA4LjIwMiw2OS40ODcgQzguMjAyLDY5LjA5IDguMDAzLDY4Ljg2MSA3LjcxNCw2OC44NjEiIGlkPSJGaWxsLTE1IiBmaWxsPSIjODA5N0EyIj48L3BhdGg+CiAgICAgICAgICAgICAgICAgICAgPHBhdGggZD0iTTcuNDQ0LDg1LjM1IEM3LjcwOCw4NS4xOTggNy45MjEsODUuMzE5IDcuOTIxLDg1LjYyMiBDNy45MjEsODUuOTI1IDcuNzA4LDg2LjI5MiA3LjQ0NCw4Ni40NDQgQzcuMTgxLDg2LjU5NyA2Ljk2Nyw4Ni40NzUgNi45NjcsODYuMTczIEM2Ljk2Nyw4NS44NzEgNy4xODEsODUuNTAyIDcuNDQ0LDg1LjM1IiBpZD0iRmlsbC0xNiIgZmlsbD0iI0ZGRkZGRiI+PC9wYXRoPgogICAgICAgICAgICAgICAgICAgIDxwYXRoIGQ9Ik03LjIzLDg2LjUxIEM3LjA3NCw4Ni41MSA2Ljk2Nyw4Ni4zODcgNi45NjcsODYuMTczIEM2Ljk2Nyw4NS44NzEgNy4xODEsODUuNTAyIDcuNDQ0LDg1LjM1IEM3LjUyMSw4NS4zMDUgNy41OTQsODUuMjg0IDcuNjU4LDg1LjI4NCBDNy44MTQsODUuMjg0IDcuOTIxLDg1LjQwOCA3LjkyMSw4NS42MjIgQzcuOTIxLDg1LjkyNSA3LjcwOCw4Ni4yOTIgNy40NDQsODYuNDQ0IEM3LjM2Nyw4Ni40ODkgNy4yOTQsODYuNTEgNy4yMyw4Ni41MSBNNy42NTgsODUuMDk4IEM3LjU1OCw4NS4wOTggNy40NTUsODUuMTI3IDcuMzUxLDg1LjE4OCBDNy4wMzEsODUuMzczIDYuNzgxLDg1LjgwNiA2Ljc4MSw4Ni4xNzMgQzYuNzgxLDg2LjQ4MiA2Ljk2Niw4Ni42OTcgNy4yMyw4Ni42OTcgQzcuMzMsODYuNjk3IDcuNDMzLDg2LjY2NiA3LjUzOCw4Ni42MDcgQzcuODU4LDg2LjQyMiA4LjEwOCw4NS45ODkgOC4xMDgsODUuNjIyIEM4LjEwOCw4NS4zMTMgNy45MjMsODUuMDk4IDcuNjU4LDg1LjA5OCIgaWQ9IkZpbGwtMTciIGZpbGw9IiM4MDk3QTIiPjwvcGF0aD4KICAgICAgICAgICAgICAgICAgICA8cGF0aCBkPSJNNy4yMyw4Ni4zMjIgTDcuMTU0LDg2LjE3MyBDNy4xNTQsODUuOTM4IDcuMzMzLDg1LjYyOSA3LjUzOCw4NS41MTIgTDcuNjU4LDg1LjQ3MSBMNy43MzQsODUuNjIyIEM3LjczNCw4NS44NTYgNy41NTUsODYuMTY0IDcuMzUxLDg2LjI4MiBMNy4yMyw4Ni4zMjIgTTcuNjU4LDg1LjI4NCBDNy41OTQsODUuMjg0IDcuNTIxLDg1LjMwNSA3LjQ0NCw4NS4zNSBDNy4xODEsODUuNTAyIDYuOTY3LDg1Ljg3MSA2Ljk2Nyw4Ni4xNzMgQzYuOTY3LDg2LjM4NyA3LjA3NCw4Ni41MSA3LjIzLDg2LjUxIEM3LjI5NCw4Ni41MSA3LjM2Nyw4Ni40ODkgNy40NDQsODYuNDQ0IEM3LjcwOCw4Ni4yOTIgNy45MjEsODUuOTI1IDcuOTIxLDg1LjYyMiBDNy45MjEsODUuNDA4IDcuODE0LDg1LjI4NCA3LjY1OCw4NS4yODQiIGlkPSJGaWxsLTE4IiBmaWxsPSIjODA5N0EyIj48L3BhdGg+CiAgICAgICAgICAgICAgICAgICAgPHBhdGggZD0iTTc3LjI3OCw3Ljc2OSBMNzcuMjc4LDUxLjQzNiBMMTAuMjA4LDkwLjE2IEwxMC4yMDgsNDYuNDkzIEw3Ny4yNzgsNy43NjkiIGlkPSJGaWxsLTE5IiBmaWxsPSIjNDU1QTY0Ij48L3BhdGg+CiAgICAgICAgICAgICAgICAgICAgPHBhdGggZD0iTTEwLjA4Myw5MC4zNzUgTDEwLjA4Myw0Ni40MjEgTDEwLjE0Niw0Ni4zODUgTDc3LjQwMyw3LjU1NCBMNzcuNDAzLDUxLjUwOCBMNzcuMzQxLDUxLjU0NCBMMTAuMDgzLDkwLjM3NSBMMTAuMDgzLDkwLjM3NSBaIE0xMC4zMzMsNDYuNTY0IEwxMC4zMzMsODkuOTQ0IEw3Ny4xNTQsNTEuMzY1IEw3Ny4xNTQsNy45ODUgTDEwLjMzMyw0Ni41NjQgTDEwLjMzMyw0Ni41NjQgWiIgaWQ9IkZpbGwtMjAiIGZpbGw9IiM2MDdEOEIiPjwvcGF0aD4KICAgICAgICAgICAgICAgIDwvZz4KICAgICAgICAgICAgICAgIDxwYXRoIGQ9Ik0xMjUuNzM3LDg4LjY0NyBMMTE4LjA5OCw5MS45ODEgTDExOC4wOTgsODQgTDEwNi42MzksODguNzEzIEwxMDYuNjM5LDk2Ljk4MiBMOTksMTAwLjMxNSBMMTEyLjM2OSwxMDMuOTYxIEwxMjUuNzM3LDg4LjY0NyIgaWQ9IkltcG9ydGVkLUxheWVycy1Db3B5LTIiIGZpbGw9IiM0NTVBNjQiIHNrZXRjaDp0eXBlPSJNU1NoYXBlR3JvdXAiPjwvcGF0aD4KICAgICAgICAgICAgPC9nPgogICAgICAgIDwvZz4KICAgIDwvZz4KPC9zdmc+'); -}; - -module.exports = RotateInstructions; - -},{"./util.js":22}],17:[function(_dereq_,module,exports){ -/* - * Copyright 2015 Google Inc. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** - * TODO: Fix up all "new THREE" instantiations to improve performance. - */ -var SensorSample = _dereq_('./sensor-sample.js'); -var MathUtil = _dereq_('../math-util.js'); -var Util = _dereq_('../util.js'); - -var DEBUG = false; - -/** - * An implementation of a simple complementary filter, which fuses gyroscope and - * accelerometer data from the 'devicemotion' event. - * - * Accelerometer data is very noisy, but stable over the long term. - * Gyroscope data is smooth, but tends to drift over the long term. - * - * This fusion is relatively simple: - * 1. Get orientation estimates from accelerometer by applying a low-pass filter - * on that data. - * 2. Get orientation estimates from gyroscope by integrating over time. - * 3. Combine the two estimates, weighing (1) in the long term, but (2) for the - * short term. - */ -function ComplementaryFilter(kFilter) { - this.kFilter = kFilter; - - // Raw sensor measurements. - this.currentAccelMeasurement = new SensorSample(); - this.currentGyroMeasurement = new SensorSample(); - this.previousGyroMeasurement = new SensorSample(); - - // Set the quaternion to be looking in the -z direction by default. - this.filterQ = new MathUtil.Quaternion(1, 0, 0, 1); - this.previousFilterQ = new MathUtil.Quaternion(); - - // Orientation based on the accelerometer. - this.accelQ = new MathUtil.Quaternion(); - // Whether or not the orientation has been initialized. - this.isOrientationInitialized = false; - // Running estimate of gravity based on the current orientation. - this.estimatedGravity = new MathUtil.Vector3(); - // Measured gravity based on accelerometer. - this.measuredGravity = new MathUtil.Vector3(); - - // Debug only quaternion of gyro-based orientation. - this.gyroIntegralQ = new MathUtil.Quaternion(); -} - -ComplementaryFilter.prototype.addAccelMeasurement = function(vector, timestampS) { - this.currentAccelMeasurement.set(vector, timestampS); -}; - -ComplementaryFilter.prototype.addGyroMeasurement = function(vector, timestampS) { - this.currentGyroMeasurement.set(vector, timestampS); - - var deltaT = timestampS - this.previousGyroMeasurement.timestampS; - if (Util.isTimestampDeltaValid(deltaT)) { - this.run_(); - } - - this.previousGyroMeasurement.copy(this.currentGyroMeasurement); -}; - -ComplementaryFilter.prototype.run_ = function() { - - if (!this.isOrientationInitialized) { - this.accelQ = this.accelToQuaternion_(this.currentAccelMeasurement.sample); - this.previousFilterQ.copy(this.accelQ); - this.isOrientationInitialized = true; - return; - } - - var deltaT = this.currentGyroMeasurement.timestampS - - this.previousGyroMeasurement.timestampS; - - // Convert gyro rotation vector to a quaternion delta. - var gyroDeltaQ = this.gyroToQuaternionDelta_(this.currentGyroMeasurement.sample, deltaT); - this.gyroIntegralQ.multiply(gyroDeltaQ); - - // filter_1 = K * (filter_0 + gyro * dT) + (1 - K) * accel. - this.filterQ.copy(this.previousFilterQ); - this.filterQ.multiply(gyroDeltaQ); - - // Calculate the delta between the current estimated gravity and the real - // gravity vector from accelerometer. - var invFilterQ = new MathUtil.Quaternion(); - invFilterQ.copy(this.filterQ); - invFilterQ.inverse(); - - this.estimatedGravity.set(0, 0, -1); - this.estimatedGravity.applyQuaternion(invFilterQ); - this.estimatedGravity.normalize(); - - this.measuredGravity.copy(this.currentAccelMeasurement.sample); - this.measuredGravity.normalize(); - - // Compare estimated gravity with measured gravity, get the delta quaternion - // between the two. - var deltaQ = new MathUtil.Quaternion(); - deltaQ.setFromUnitVectors(this.estimatedGravity, this.measuredGravity); - deltaQ.inverse(); - - if (DEBUG) { - console.log('Delta: %d deg, G_est: (%s, %s, %s), G_meas: (%s, %s, %s)', - MathUtil.radToDeg * Util.getQuaternionAngle(deltaQ), - (this.estimatedGravity.x).toFixed(1), - (this.estimatedGravity.y).toFixed(1), - (this.estimatedGravity.z).toFixed(1), - (this.measuredGravity.x).toFixed(1), - (this.measuredGravity.y).toFixed(1), - (this.measuredGravity.z).toFixed(1)); - } - - // Calculate the SLERP target: current orientation plus the measured-estimated - // quaternion delta. - var targetQ = new MathUtil.Quaternion(); - targetQ.copy(this.filterQ); - targetQ.multiply(deltaQ); - - // SLERP factor: 0 is pure gyro, 1 is pure accel. - this.filterQ.slerp(targetQ, 1 - this.kFilter); - - this.previousFilterQ.copy(this.filterQ); -}; - -ComplementaryFilter.prototype.getOrientation = function() { - return this.filterQ; -}; - -ComplementaryFilter.prototype.accelToQuaternion_ = function(accel) { - var normAccel = new MathUtil.Vector3(); - normAccel.copy(accel); - normAccel.normalize(); - var quat = new MathUtil.Quaternion(); - quat.setFromUnitVectors(new MathUtil.Vector3(0, 0, -1), normAccel); - quat.inverse(); - return quat; -}; - -ComplementaryFilter.prototype.gyroToQuaternionDelta_ = function(gyro, dt) { - // Extract axis and angle from the gyroscope data. - var quat = new MathUtil.Quaternion(); - var axis = new MathUtil.Vector3(); - axis.copy(gyro); - axis.normalize(); - quat.setFromAxisAngle(axis, gyro.length() * dt); - return quat; -}; - - -module.exports = ComplementaryFilter; - -},{"../math-util.js":14,"../util.js":22,"./sensor-sample.js":20}],18:[function(_dereq_,module,exports){ -/* - * Copyright 2015 Google Inc. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -var ComplementaryFilter = _dereq_('./complementary-filter.js'); -var PosePredictor = _dereq_('./pose-predictor.js'); -var TouchPanner = _dereq_('../touch-panner.js'); -var MathUtil = _dereq_('../math-util.js'); -var Util = _dereq_('../util.js'); - -/** - * The pose sensor, implemented using DeviceMotion APIs. - */ -function FusionPoseSensor() { - this.deviceId = 'webvr-polyfill:fused'; - this.deviceName = 'VR Position Device (webvr-polyfill:fused)'; - - this.accelerometer = new MathUtil.Vector3(); - this.gyroscope = new MathUtil.Vector3(); - - window.addEventListener('devicemotion', this.onDeviceMotionChange_.bind(this)); - window.addEventListener('orientationchange', this.onScreenOrientationChange_.bind(this)); - - this.filter = new ComplementaryFilter(WebVRConfig.K_FILTER); - this.posePredictor = new PosePredictor(WebVRConfig.PREDICTION_TIME_S); - this.touchPanner = new TouchPanner(); - - this.filterToWorldQ = new MathUtil.Quaternion(); - - // Set the filter to world transform, depending on OS. - if (Util.isIOS()) { - this.filterToWorldQ.setFromAxisAngle(new MathUtil.Vector3(1, 0, 0), Math.PI / 2); - } else { - this.filterToWorldQ.setFromAxisAngle(new MathUtil.Vector3(1, 0, 0), -Math.PI / 2); - } - - this.inverseWorldToScreenQ = new MathUtil.Quaternion(); - this.worldToScreenQ = new MathUtil.Quaternion(); - this.originalPoseAdjustQ = new MathUtil.Quaternion(); - this.originalPoseAdjustQ.setFromAxisAngle(new MathUtil.Vector3(0, 0, 1), - -window.orientation * Math.PI / 180); - - this.setScreenTransform_(); - // Adjust this filter for being in landscape mode. - if (Util.isLandscapeMode()) { - this.filterToWorldQ.multiply(this.inverseWorldToScreenQ); - } - - // Keep track of a reset transform for resetSensor. - this.resetQ = new MathUtil.Quaternion(); - - this.isFirefoxAndroid = Util.isFirefoxAndroid(); - this.isIOS = Util.isIOS(); - - this.orientationOut_ = new Float32Array(4); -} - -FusionPoseSensor.prototype.getPosition = function() { - // This PoseSensor doesn't support position - return null; -}; - -FusionPoseSensor.prototype.getOrientation = function() { - // Convert from filter space to the the same system used by the - // deviceorientation event. - var orientation = this.filter.getOrientation(); - - // Predict orientation. - this.predictedQ = this.posePredictor.getPrediction(orientation, this.gyroscope, this.previousTimestampS); - - // Convert to THREE coordinate system: -Z forward, Y up, X right. - var out = new MathUtil.Quaternion(); - out.copy(this.filterToWorldQ); - out.multiply(this.resetQ); - if (!WebVRConfig.TOUCH_PANNER_DISABLED) { - out.multiply(this.touchPanner.getOrientation()); - } - out.multiply(this.predictedQ); - out.multiply(this.worldToScreenQ); - - // Handle the yaw-only case. - if (WebVRConfig.YAW_ONLY) { - // Make a quaternion that only turns around the Y-axis. - out.x = 0; - out.z = 0; - out.normalize(); - } - - this.orientationOut_[0] = out.x; - this.orientationOut_[1] = out.y; - this.orientationOut_[2] = out.z; - this.orientationOut_[3] = out.w; - return this.orientationOut_; -}; - -FusionPoseSensor.prototype.resetPose = function() { - // Reduce to inverted yaw-only. - this.resetQ.copy(this.filter.getOrientation()); - this.resetQ.x = 0; - this.resetQ.y = 0; - this.resetQ.z *= -1; - this.resetQ.normalize(); - - // Take into account extra transformations in landscape mode. - if (Util.isLandscapeMode()) { - this.resetQ.multiply(this.inverseWorldToScreenQ); - } - - // Take into account original pose. - this.resetQ.multiply(this.originalPoseAdjustQ); - - if (!WebVRConfig.TOUCH_PANNER_DISABLED) { - this.touchPanner.resetSensor(); - } -}; - -FusionPoseSensor.prototype.onDeviceMotionChange_ = function(deviceMotion) { - var accGravity = deviceMotion.accelerationIncludingGravity; - var rotRate = deviceMotion.rotationRate; - var timestampS = deviceMotion.timeStamp / 1000; - - // Firefox Android timeStamp returns one thousandth of a millisecond. - if (this.isFirefoxAndroid) { - timestampS /= 1000; - } - - var deltaS = timestampS - this.previousTimestampS; - if (deltaS <= Util.MIN_TIMESTEP || deltaS > Util.MAX_TIMESTEP) { - console.warn('Invalid timestamps detected. Time step between successive ' + - 'gyroscope sensor samples is very small or not monotonic'); - this.previousTimestampS = timestampS; - return; - } - this.accelerometer.set(-accGravity.x, -accGravity.y, -accGravity.z); - this.gyroscope.set(rotRate.alpha, rotRate.beta, rotRate.gamma); - - // With iOS and Firefox Android, rotationRate is reported in degrees, - // so we first convert to radians. - if (this.isIOS || this.isFirefoxAndroid) { - this.gyroscope.multiplyScalar(Math.PI / 180); - } - - this.filter.addAccelMeasurement(this.accelerometer, timestampS); - this.filter.addGyroMeasurement(this.gyroscope, timestampS); - - this.previousTimestampS = timestampS; -}; - -FusionPoseSensor.prototype.onScreenOrientationChange_ = - function(screenOrientation) { - this.setScreenTransform_(); -}; - -FusionPoseSensor.prototype.setScreenTransform_ = function() { - this.worldToScreenQ.set(0, 0, 0, 1); - switch (window.orientation) { - case 0: - break; - case 90: - this.worldToScreenQ.setFromAxisAngle(new MathUtil.Vector3(0, 0, 1), -Math.PI / 2); - break; - case -90: - this.worldToScreenQ.setFromAxisAngle(new MathUtil.Vector3(0, 0, 1), Math.PI / 2); - break; - case 180: - // TODO. - break; - } - this.inverseWorldToScreenQ.copy(this.worldToScreenQ); - this.inverseWorldToScreenQ.inverse(); -}; - -module.exports = FusionPoseSensor; - -},{"../math-util.js":14,"../touch-panner.js":21,"../util.js":22,"./complementary-filter.js":17,"./pose-predictor.js":19}],19:[function(_dereq_,module,exports){ -/* - * Copyright 2015 Google Inc. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -var MathUtil = _dereq_('../math-util.js'); -var DEBUG = false; - -/** - * Given an orientation and the gyroscope data, predicts the future orientation - * of the head. This makes rendering appear faster. - * - * Also see: http://msl.cs.uiuc.edu/~lavalle/papers/LavYerKatAnt14.pdf - * - * @param {Number} predictionTimeS time from head movement to the appearance of - * the corresponding image. - */ -function PosePredictor(predictionTimeS) { - this.predictionTimeS = predictionTimeS; - - // The quaternion corresponding to the previous state. - this.previousQ = new MathUtil.Quaternion(); - // Previous time a prediction occurred. - this.previousTimestampS = null; - - // The delta quaternion that adjusts the current pose. - this.deltaQ = new MathUtil.Quaternion(); - // The output quaternion. - this.outQ = new MathUtil.Quaternion(); -} - -PosePredictor.prototype.getPrediction = function(currentQ, gyro, timestampS) { - if (!this.previousTimestampS) { - this.previousQ.copy(currentQ); - this.previousTimestampS = timestampS; - return currentQ; - } - - // Calculate axis and angle based on gyroscope rotation rate data. - var axis = new MathUtil.Vector3(); - axis.copy(gyro); - axis.normalize(); - - var angularSpeed = gyro.length(); - - // If we're rotating slowly, don't do prediction. - if (angularSpeed < MathUtil.degToRad * 20) { - if (DEBUG) { - console.log('Moving slowly, at %s deg/s: no prediction', - (MathUtil.radToDeg * angularSpeed).toFixed(1)); - } - this.outQ.copy(currentQ); - this.previousQ.copy(currentQ); - return this.outQ; - } - - // Get the predicted angle based on the time delta and latency. - var deltaT = timestampS - this.previousTimestampS; - var predictAngle = angularSpeed * this.predictionTimeS; - - this.deltaQ.setFromAxisAngle(axis, predictAngle); - this.outQ.copy(this.previousQ); - this.outQ.multiply(this.deltaQ); - - this.previousQ.copy(currentQ); - - return this.outQ; -}; - - -module.exports = PosePredictor; - -},{"../math-util.js":14}],20:[function(_dereq_,module,exports){ -function SensorSample(sample, timestampS) { - this.set(sample, timestampS); -}; - -SensorSample.prototype.set = function(sample, timestampS) { - this.sample = sample; - this.timestampS = timestampS; -}; - -SensorSample.prototype.copy = function(sensorSample) { - this.set(sensorSample.sample, sensorSample.timestampS); -}; - -module.exports = SensorSample; - -},{}],21:[function(_dereq_,module,exports){ -/* - * Copyright 2015 Google Inc. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -var MathUtil = _dereq_('./math-util.js'); -var Util = _dereq_('./util.js'); - -var ROTATE_SPEED = 0.5; -/** - * Provides a quaternion responsible for pre-panning the scene before further - * transformations due to device sensors. - */ -function TouchPanner() { - window.addEventListener('touchstart', this.onTouchStart_.bind(this)); - window.addEventListener('touchmove', this.onTouchMove_.bind(this)); - window.addEventListener('touchend', this.onTouchEnd_.bind(this)); - - this.isTouching = false; - this.rotateStart = new MathUtil.Vector2(); - this.rotateEnd = new MathUtil.Vector2(); - this.rotateDelta = new MathUtil.Vector2(); - - this.theta = 0; - this.orientation = new MathUtil.Quaternion(); -} - -TouchPanner.prototype.getOrientation = function() { - this.orientation.setFromEulerXYZ(0, 0, this.theta); - return this.orientation; -}; - -TouchPanner.prototype.resetSensor = function() { - this.theta = 0; -}; - -TouchPanner.prototype.onTouchStart_ = function(e) { - // Only respond if there is exactly one touch. - if (e.touches.length != 1) { - return; - } - this.rotateStart.set(e.touches[0].pageX, e.touches[0].pageY); - this.isTouching = true; -}; - -TouchPanner.prototype.onTouchMove_ = function(e) { - if (!this.isTouching) { - return; - } - this.rotateEnd.set(e.touches[0].pageX, e.touches[0].pageY); - this.rotateDelta.subVectors(this.rotateEnd, this.rotateStart); - this.rotateStart.copy(this.rotateEnd); - - // On iOS, direction is inverted. - if (Util.isIOS()) { - this.rotateDelta.x *= -1; - } - - var element = document.body; - this.theta += 2 * Math.PI * this.rotateDelta.x / element.clientWidth * ROTATE_SPEED; -}; - -TouchPanner.prototype.onTouchEnd_ = function(e) { - this.isTouching = false; -}; - -module.exports = TouchPanner; - -},{"./math-util.js":14,"./util.js":22}],22:[function(_dereq_,module,exports){ -/* - * Copyright 2015 Google Inc. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -var objectAssign = _dereq_('object-assign'); - -var Util = window.Util || {}; - -Util.MIN_TIMESTEP = 0.001; -Util.MAX_TIMESTEP = 1; - -Util.base64 = function(mimeType, base64) { - return 'data:' + mimeType + ';base64,' + base64; -}; - -Util.clamp = function(value, min, max) { - return Math.min(Math.max(min, value), max); -}; - -Util.lerp = function(a, b, t) { - return a + ((b - a) * t); -}; - -Util.isIOS = (function() { - var isIOS = /iPad|iPhone|iPod/.test(navigator.platform); - return function() { - return isIOS; - }; -})(); - -Util.isSafari = (function() { - var isSafari = /^((?!chrome|android).)*safari/i.test(navigator.userAgent); - return function() { - return isSafari; - }; -})(); - -Util.isFirefoxAndroid = (function() { - var isFirefoxAndroid = navigator.userAgent.indexOf('Firefox') !== -1 && - navigator.userAgent.indexOf('Android') !== -1; - return function() { - return isFirefoxAndroid; - }; -})(); - -Util.isLandscapeMode = function() { - return (window.orientation == 90 || window.orientation == -90); -}; - -// Helper method to validate the time steps of sensor timestamps. -Util.isTimestampDeltaValid = function(timestampDeltaS) { - if (isNaN(timestampDeltaS)) { - return false; - } - if (timestampDeltaS <= Util.MIN_TIMESTEP) { - return false; - } - if (timestampDeltaS > Util.MAX_TIMESTEP) { - return false; - } - return true; -}; - -Util.getScreenWidth = function() { - return Math.max(window.screen.width, window.screen.height) * - window.devicePixelRatio; -}; - -Util.getScreenHeight = function() { - return Math.min(window.screen.width, window.screen.height) * - window.devicePixelRatio; -}; - -Util.requestFullscreen = function(element) { - if (element.requestFullscreen) { - element.requestFullscreen(); - } else if (element.webkitRequestFullscreen) { - element.webkitRequestFullscreen(); - } else if (element.mozRequestFullScreen) { - element.mozRequestFullScreen(); - } else if (element.msRequestFullscreen) { - element.msRequestFullscreen(); - } else { - return false; - } - - return true; -}; - -Util.exitFullscreen = function() { - if (document.exitFullscreen) { - document.exitFullscreen(); - } else if (document.webkitExitFullscreen) { - document.webkitExitFullscreen(); - } else if (document.mozCancelFullScreen) { - document.mozCancelFullScreen(); - } else if (document.msExitFullscreen) { - document.msExitFullscreen(); - } else { - return false; - } - - return true; -}; - -Util.getFullscreenElement = function() { - return document.fullscreenElement || - document.webkitFullscreenElement || - document.mozFullScreenElement || - document.msFullscreenElement; -}; - -Util.linkProgram = function(gl, vertexSource, fragmentSource, attribLocationMap) { - // No error checking for brevity. - var vertexShader = gl.createShader(gl.VERTEX_SHADER); - gl.shaderSource(vertexShader, vertexSource); - gl.compileShader(vertexShader); - - var fragmentShader = gl.createShader(gl.FRAGMENT_SHADER); - gl.shaderSource(fragmentShader, fragmentSource); - gl.compileShader(fragmentShader); - - var program = gl.createProgram(); - gl.attachShader(program, vertexShader); - gl.attachShader(program, fragmentShader); - - for (var attribName in attribLocationMap) - gl.bindAttribLocation(program, attribLocationMap[attribName], attribName); - - gl.linkProgram(program); - - gl.deleteShader(vertexShader); - gl.deleteShader(fragmentShader); - - return program; -}; - -Util.getProgramUniforms = function(gl, program) { - var uniforms = {}; - var uniformCount = gl.getProgramParameter(program, gl.ACTIVE_UNIFORMS); - var uniformName = ''; - for (var i = 0; i < uniformCount; i++) { - var uniformInfo = gl.getActiveUniform(program, i); - uniformName = uniformInfo.name.replace('[0]', ''); - uniforms[uniformName] = gl.getUniformLocation(program, uniformName); - } - return uniforms; -}; - -Util.orthoMatrix = function (out, left, right, bottom, top, near, far) { - var lr = 1 / (left - right), - bt = 1 / (bottom - top), - nf = 1 / (near - far); - out[0] = -2 * lr; - out[1] = 0; - out[2] = 0; - out[3] = 0; - out[4] = 0; - out[5] = -2 * bt; - out[6] = 0; - out[7] = 0; - out[8] = 0; - out[9] = 0; - out[10] = 2 * nf; - out[11] = 0; - out[12] = (left + right) * lr; - out[13] = (top + bottom) * bt; - out[14] = (far + near) * nf; - out[15] = 1; - return out; -}; - -Util.isMobile = function() { - var check = false; - (function(a){if(/(android|bb\d+|meego).+mobile|avantgo|bada\/|blackberry|blazer|compal|elaine|fennec|hiptop|iemobile|ip(hone|od)|iris|kindle|lge |maemo|midp|mmp|mobile.+firefox|netfront|opera m(ob|in)i|palm( os)?|phone|p(ixi|re)\/|plucker|pocket|psp|series(4|6)0|symbian|treo|up\.(browser|link)|vodafone|wap|windows ce|xda|xiino/i.test(a)||/1207|6310|6590|3gso|4thp|50[1-6]i|770s|802s|a wa|abac|ac(er|oo|s\-)|ai(ko|rn)|al(av|ca|co)|amoi|an(ex|ny|yw)|aptu|ar(ch|go)|as(te|us)|attw|au(di|\-m|r |s )|avan|be(ck|ll|nq)|bi(lb|rd)|bl(ac|az)|br(e|v)w|bumb|bw\-(n|u)|c55\/|capi|ccwa|cdm\-|cell|chtm|cldc|cmd\-|co(mp|nd)|craw|da(it|ll|ng)|dbte|dc\-s|devi|dica|dmob|do(c|p)o|ds(12|\-d)|el(49|ai)|em(l2|ul)|er(ic|k0)|esl8|ez([4-7]0|os|wa|ze)|fetc|fly(\-|_)|g1 u|g560|gene|gf\-5|g\-mo|go(\.w|od)|gr(ad|un)|haie|hcit|hd\-(m|p|t)|hei\-|hi(pt|ta)|hp( i|ip)|hs\-c|ht(c(\-| |_|a|g|p|s|t)|tp)|hu(aw|tc)|i\-(20|go|ma)|i230|iac( |\-|\/)|ibro|idea|ig01|ikom|im1k|inno|ipaq|iris|ja(t|v)a|jbro|jemu|jigs|kddi|keji|kgt( |\/)|klon|kpt |kwc\-|kyo(c|k)|le(no|xi)|lg( g|\/(k|l|u)|50|54|\-[a-w])|libw|lynx|m1\-w|m3ga|m50\/|ma(te|ui|xo)|mc(01|21|ca)|m\-cr|me(rc|ri)|mi(o8|oa|ts)|mmef|mo(01|02|bi|de|do|t(\-| |o|v)|zz)|mt(50|p1|v )|mwbp|mywa|n10[0-2]|n20[2-3]|n30(0|2)|n50(0|2|5)|n7(0(0|1)|10)|ne((c|m)\-|on|tf|wf|wg|wt)|nok(6|i)|nzph|o2im|op(ti|wv)|oran|owg1|p800|pan(a|d|t)|pdxg|pg(13|\-([1-8]|c))|phil|pire|pl(ay|uc)|pn\-2|po(ck|rt|se)|prox|psio|pt\-g|qa\-a|qc(07|12|21|32|60|\-[2-7]|i\-)|qtek|r380|r600|raks|rim9|ro(ve|zo)|s55\/|sa(ge|ma|mm|ms|ny|va)|sc(01|h\-|oo|p\-)|sdk\/|se(c(\-|0|1)|47|mc|nd|ri)|sgh\-|shar|sie(\-|m)|sk\-0|sl(45|id)|sm(al|ar|b3|it|t5)|so(ft|ny)|sp(01|h\-|v\-|v )|sy(01|mb)|t2(18|50)|t6(00|10|18)|ta(gt|lk)|tcl\-|tdg\-|tel(i|m)|tim\-|t\-mo|to(pl|sh)|ts(70|m\-|m3|m5)|tx\-9|up(\.b|g1|si)|utst|v400|v750|veri|vi(rg|te)|vk(40|5[0-3]|\-v)|vm40|voda|vulc|vx(52|53|60|61|70|80|81|83|85|98)|w3c(\-| )|webc|whit|wi(g |nc|nw)|wmlb|wonu|x700|yas\-|your|zeto|zte\-/i.test(a.substr(0,4)))check = true})(navigator.userAgent||navigator.vendor||window.opera); - return check; -}; - -Util.extend = objectAssign; - -Util.safariCssSizeWorkaround = function(canvas) { - // TODO(smus): Remove this workaround when Safari for iOS is fixed. - // iOS only workaround (for https://bugs.webkit.org/show_bug.cgi?id=152556). - // - // "To the last I grapple with thee; - // from hell's heart I stab at thee; - // for hate's sake I spit my last breath at thee." - // -- Moby Dick, by Herman Melville - if (Util.isIOS()) { - var width = canvas.style.width; - var height = canvas.style.height; - canvas.style.width = (parseInt(width) + 1) + 'px'; - canvas.style.height = (parseInt(height)) + 'px'; - console.log('Resetting width to...', width); - setTimeout(function() { - console.log('Done. Width is now', width); - canvas.style.width = width; - canvas.style.height = height; - }, 100); - } - - // Debug only. - window.Util = Util; - window.canvas = canvas; -}; - -Util.frameDataFromPose = (function() { - var piOver180 = Math.PI / 180.0; - var rad45 = Math.PI * 0.25; - - // Borrowed from glMatrix. - function mat4_perspectiveFromFieldOfView(out, fov, near, far) { - var upTan = Math.tan(fov ? (fov.upDegrees * piOver180) : rad45), - downTan = Math.tan(fov ? (fov.downDegrees * piOver180) : rad45), - leftTan = Math.tan(fov ? (fov.leftDegrees * piOver180) : rad45), - rightTan = Math.tan(fov ? (fov.rightDegrees * piOver180) : rad45), - xScale = 2.0 / (leftTan + rightTan), - yScale = 2.0 / (upTan + downTan); - - out[0] = xScale; - out[1] = 0.0; - out[2] = 0.0; - out[3] = 0.0; - out[4] = 0.0; - out[5] = yScale; - out[6] = 0.0; - out[7] = 0.0; - out[8] = -((leftTan - rightTan) * xScale * 0.5); - out[9] = ((upTan - downTan) * yScale * 0.5); - out[10] = far / (near - far); - out[11] = -1.0; - out[12] = 0.0; - out[13] = 0.0; - out[14] = (far * near) / (near - far); - out[15] = 0.0; - return out; - } - - function mat4_fromRotationTranslation(out, q, v) { - // Quaternion math - var x = q[0], y = q[1], z = q[2], w = q[3], - x2 = x + x, - y2 = y + y, - z2 = z + z, - - xx = x * x2, - xy = x * y2, - xz = x * z2, - yy = y * y2, - yz = y * z2, - zz = z * z2, - wx = w * x2, - wy = w * y2, - wz = w * z2; - - out[0] = 1 - (yy + zz); - out[1] = xy + wz; - out[2] = xz - wy; - out[3] = 0; - out[4] = xy - wz; - out[5] = 1 - (xx + zz); - out[6] = yz + wx; - out[7] = 0; - out[8] = xz + wy; - out[9] = yz - wx; - out[10] = 1 - (xx + yy); - out[11] = 0; - out[12] = v[0]; - out[13] = v[1]; - out[14] = v[2]; - out[15] = 1; - - return out; - }; - - function mat4_translate(out, a, v) { - var x = v[0], y = v[1], z = v[2], - a00, a01, a02, a03, - a10, a11, a12, a13, - a20, a21, a22, a23; - - if (a === out) { - out[12] = a[0] * x + a[4] * y + a[8] * z + a[12]; - out[13] = a[1] * x + a[5] * y + a[9] * z + a[13]; - out[14] = a[2] * x + a[6] * y + a[10] * z + a[14]; - out[15] = a[3] * x + a[7] * y + a[11] * z + a[15]; - } else { - a00 = a[0]; a01 = a[1]; a02 = a[2]; a03 = a[3]; - a10 = a[4]; a11 = a[5]; a12 = a[6]; a13 = a[7]; - a20 = a[8]; a21 = a[9]; a22 = a[10]; a23 = a[11]; - - out[0] = a00; out[1] = a01; out[2] = a02; out[3] = a03; - out[4] = a10; out[5] = a11; out[6] = a12; out[7] = a13; - out[8] = a20; out[9] = a21; out[10] = a22; out[11] = a23; - - out[12] = a00 * x + a10 * y + a20 * z + a[12]; - out[13] = a01 * x + a11 * y + a21 * z + a[13]; - out[14] = a02 * x + a12 * y + a22 * z + a[14]; - out[15] = a03 * x + a13 * y + a23 * z + a[15]; - } - - return out; - }; - - mat4_invert = function(out, a) { - var a00 = a[0], a01 = a[1], a02 = a[2], a03 = a[3], - a10 = a[4], a11 = a[5], a12 = a[6], a13 = a[7], - a20 = a[8], a21 = a[9], a22 = a[10], a23 = a[11], - a30 = a[12], a31 = a[13], a32 = a[14], a33 = a[15], - - b00 = a00 * a11 - a01 * a10, - b01 = a00 * a12 - a02 * a10, - b02 = a00 * a13 - a03 * a10, - b03 = a01 * a12 - a02 * a11, - b04 = a01 * a13 - a03 * a11, - b05 = a02 * a13 - a03 * a12, - b06 = a20 * a31 - a21 * a30, - b07 = a20 * a32 - a22 * a30, - b08 = a20 * a33 - a23 * a30, - b09 = a21 * a32 - a22 * a31, - b10 = a21 * a33 - a23 * a31, - b11 = a22 * a33 - a23 * a32, - - // Calculate the determinant - det = b00 * b11 - b01 * b10 + b02 * b09 + b03 * b08 - b04 * b07 + b05 * b06; - - if (!det) { - return null; - } - det = 1.0 / det; - - out[0] = (a11 * b11 - a12 * b10 + a13 * b09) * det; - out[1] = (a02 * b10 - a01 * b11 - a03 * b09) * det; - out[2] = (a31 * b05 - a32 * b04 + a33 * b03) * det; - out[3] = (a22 * b04 - a21 * b05 - a23 * b03) * det; - out[4] = (a12 * b08 - a10 * b11 - a13 * b07) * det; - out[5] = (a00 * b11 - a02 * b08 + a03 * b07) * det; - out[6] = (a32 * b02 - a30 * b05 - a33 * b01) * det; - out[7] = (a20 * b05 - a22 * b02 + a23 * b01) * det; - out[8] = (a10 * b10 - a11 * b08 + a13 * b06) * det; - out[9] = (a01 * b08 - a00 * b10 - a03 * b06) * det; - out[10] = (a30 * b04 - a31 * b02 + a33 * b00) * det; - out[11] = (a21 * b02 - a20 * b04 - a23 * b00) * det; - out[12] = (a11 * b07 - a10 * b09 - a12 * b06) * det; - out[13] = (a00 * b09 - a01 * b07 + a02 * b06) * det; - out[14] = (a31 * b01 - a30 * b03 - a32 * b00) * det; - out[15] = (a20 * b03 - a21 * b01 + a22 * b00) * det; - - return out; - }; - - var defaultOrientation = new Float32Array([0, 0, 0, 1]); - var defaultPosition = new Float32Array([0, 0, 0]); - - function updateEyeMatrices(projection, view, pose, parameters, vrDisplay) { - mat4_perspectiveFromFieldOfView(projection, parameters ? parameters.fieldOfView : null, vrDisplay.depthNear, vrDisplay.depthFar); - - var orientation = pose.orientation || defaultOrientation; - var position = pose.position || defaultPosition; - - mat4_fromRotationTranslation(view, orientation, position); - if (parameters) - mat4_translate(view, view, parameters.offset); - mat4_invert(view, view); - } - - return function(frameData, pose, vrDisplay) { - if (!frameData || !pose) - return false; - - frameData.pose = pose; - frameData.timestamp = pose.timestamp; - - updateEyeMatrices( - frameData.leftProjectionMatrix, frameData.leftViewMatrix, - pose, vrDisplay.getEyeParameters("left"), vrDisplay); - updateEyeMatrices( - frameData.rightProjectionMatrix, frameData.rightViewMatrix, - pose, vrDisplay.getEyeParameters("right"), vrDisplay); - - return true; - }; -})(); - -module.exports = Util; - -},{"object-assign":1}],23:[function(_dereq_,module,exports){ -/* - * Copyright 2015 Google Inc. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -var Emitter = _dereq_('./emitter.js'); -var Util = _dereq_('./util.js'); -var DeviceInfo = _dereq_('./device-info.js'); - -var DEFAULT_VIEWER = 'CardboardV1'; -var VIEWER_KEY = 'WEBVR_CARDBOARD_VIEWER'; -var CLASS_NAME = 'webvr-polyfill-viewer-selector'; - -/** - * Creates a viewer selector with the options specified. Supports being shown - * and hidden. Generates events when viewer parameters change. Also supports - * saving the currently selected index in localStorage. - */ -function ViewerSelector() { - // Try to load the selected key from local storage. If none exists, use the - // default key. - try { - this.selectedKey = localStorage.getItem(VIEWER_KEY) || DEFAULT_VIEWER; - } catch (error) { - console.error('Failed to load viewer profile: %s', error); - } - this.dialog = this.createDialog_(DeviceInfo.Viewers); - this.root = null; -} -ViewerSelector.prototype = new Emitter(); - -ViewerSelector.prototype.show = function(root) { - this.root = root; - - root.appendChild(this.dialog); - //console.log('ViewerSelector.show'); - - // Ensure the currently selected item is checked. - var selected = this.dialog.querySelector('#' + this.selectedKey); - selected.checked = true; - - // Show the UI. - this.dialog.style.display = 'block'; -}; - -ViewerSelector.prototype.hide = function() { - if (this.root && this.root.contains(this.dialog)) { - this.root.removeChild(this.dialog); - } - //console.log('ViewerSelector.hide'); - this.dialog.style.display = 'none'; -}; - -ViewerSelector.prototype.getCurrentViewer = function() { - return DeviceInfo.Viewers[this.selectedKey]; -}; - -ViewerSelector.prototype.getSelectedKey_ = function() { - var input = this.dialog.querySelector('input[name=field]:checked'); - if (input) { - return input.id; - } - return null; -}; - -ViewerSelector.prototype.onSave_ = function() { - this.selectedKey = this.getSelectedKey_(); - if (!this.selectedKey || !DeviceInfo.Viewers[this.selectedKey]) { - console.error('ViewerSelector.onSave_: this should never happen!'); - return; - } - - this.emit('change', DeviceInfo.Viewers[this.selectedKey]); - - // Attempt to save the viewer profile, but fails in private mode. - try { - localStorage.setItem(VIEWER_KEY, this.selectedKey); - } catch(error) { - console.error('Failed to save viewer profile: %s', error); - } - this.hide(); -}; - -/** - * Creates the dialog. - */ -ViewerSelector.prototype.createDialog_ = function(options) { - var container = document.createElement('div'); - container.classList.add(CLASS_NAME); - container.style.display = 'none'; - // Create an overlay that dims the background, and which goes away when you - // tap it. - var overlay = document.createElement('div'); - var s = overlay.style; - s.position = 'fixed'; - s.left = 0; - s.top = 0; - s.width = '100%'; - s.height = '100%'; - s.background = 'rgba(0, 0, 0, 0.3)'; - overlay.addEventListener('click', this.hide.bind(this)); - - var width = 280; - var dialog = document.createElement('div'); - var s = dialog.style; - s.boxSizing = 'border-box'; - s.position = 'fixed'; - s.top = '24px'; - s.left = '50%'; - s.marginLeft = (-width/2) + 'px'; - s.width = width + 'px'; - s.padding = '24px'; - s.overflow = 'hidden'; - s.background = '#fafafa'; - s.fontFamily = "'Roboto', sans-serif"; - s.boxShadow = '0px 5px 20px #666'; - - dialog.appendChild(this.createH1_('Select your viewer')); - for (var id in options) { - dialog.appendChild(this.createChoice_(id, options[id].label)); - } - dialog.appendChild(this.createButton_('Save', this.onSave_.bind(this))); - - container.appendChild(overlay); - container.appendChild(dialog); - - return container; -}; - -ViewerSelector.prototype.createH1_ = function(name) { - var h1 = document.createElement('h1'); - var s = h1.style; - s.color = 'black'; - s.fontSize = '20px'; - s.fontWeight = 'bold'; - s.marginTop = 0; - s.marginBottom = '24px'; - h1.innerHTML = name; - return h1; -}; - -ViewerSelector.prototype.createChoice_ = function(id, name) { - /* -

- - -
- */ - var div = document.createElement('div'); - div.style.marginTop = '8px'; - div.style.color = 'black'; - - var input = document.createElement('input'); - input.style.fontSize = '30px'; - input.setAttribute('id', id); - input.setAttribute('type', 'radio'); - input.setAttribute('value', id); - input.setAttribute('name', 'field'); - - var label = document.createElement('label'); - label.style.marginLeft = '4px'; - label.setAttribute('for', id); - label.innerHTML = name; - - div.appendChild(input); - div.appendChild(label); - - return div; -}; - -ViewerSelector.prototype.createButton_ = function(label, onclick) { - var button = document.createElement('button'); - button.innerHTML = label; - var s = button.style; - s.float = 'right'; - s.textTransform = 'uppercase'; - s.color = '#1094f7'; - s.fontSize = '14px'; - s.letterSpacing = 0; - s.border = 0; - s.background = 'none'; - s.marginTop = '16px'; - - button.addEventListener('click', onclick); - - return button; -}; - -module.exports = ViewerSelector; - -},{"./device-info.js":7,"./emitter.js":12,"./util.js":22}],24:[function(_dereq_,module,exports){ -/* - * Copyright 2015 Google Inc. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -var Util = _dereq_('./util.js'); - -/** - * Android and iOS compatible wakelock implementation. - * - * Refactored thanks to dkovalev@. - */ -function AndroidWakeLock() { - var video = document.createElement('video'); - - video.addEventListener('ended', function() { - video.play(); - }); - - this.request = function() { - if (video.paused) { - // Base64 version of videos_src/no-sleep-120s.mp4. - video.src = Util.base64('video/mp4', 'AAAAGGZ0eXBpc29tAAAAAG1wNDFhdmMxAAAIA21vb3YAAABsbXZoZAAAAADSa9v60mvb+gABX5AAlw/gAAEAAAEAAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIAAAdkdHJhawAAAFx0a2hkAAAAAdJr2/rSa9v6AAAAAQAAAAAAlw/gAAAAAAAAAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAQAAAAAAQAAAAHAAAAAAAJGVkdHMAAAAcZWxzdAAAAAAAAAABAJcP4AAAAAAAAQAAAAAG3G1kaWEAAAAgbWRoZAAAAADSa9v60mvb+gAPQkAGjneAFccAAAAAAC1oZGxyAAAAAAAAAAB2aWRlAAAAAAAAAAAAAAAAVmlkZW9IYW5kbGVyAAAABodtaW5mAAAAFHZtaGQAAAABAAAAAAAAAAAAAAAkZGluZgAAABxkcmVmAAAAAAAAAAEAAAAMdXJsIAAAAAEAAAZHc3RibAAAAJdzdHNkAAAAAAAAAAEAAACHYXZjMQAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAMABwASAAAAEgAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABj//wAAADFhdmNDAWQAC//hABlnZAALrNlfllw4QAAAAwBAAAADAKPFCmWAAQAFaOvssiwAAAAYc3R0cwAAAAAAAAABAAAAbgAPQkAAAAAUc3RzcwAAAAAAAAABAAAAAQAAA4BjdHRzAAAAAAAAAG4AAAABAD0JAAAAAAEAehIAAAAAAQA9CQAAAAABAAAAAAAAAAEAD0JAAAAAAQBMS0AAAAABAB6EgAAAAAEAAAAAAAAAAQAPQkAAAAABAExLQAAAAAEAHoSAAAAAAQAAAAAAAAABAA9CQAAAAAEATEtAAAAAAQAehIAAAAABAAAAAAAAAAEAD0JAAAAAAQBMS0AAAAABAB6EgAAAAAEAAAAAAAAAAQAPQkAAAAABAExLQAAAAAEAHoSAAAAAAQAAAAAAAAABAA9CQAAAAAEATEtAAAAAAQAehIAAAAABAAAAAAAAAAEAD0JAAAAAAQBMS0AAAAABAB6EgAAAAAEAAAAAAAAAAQAPQkAAAAABAExLQAAAAAEAHoSAAAAAAQAAAAAAAAABAA9CQAAAAAEATEtAAAAAAQAehIAAAAABAAAAAAAAAAEAD0JAAAAAAQBMS0AAAAABAB6EgAAAAAEAAAAAAAAAAQAPQkAAAAABAExLQAAAAAEAHoSAAAAAAQAAAAAAAAABAA9CQAAAAAEATEtAAAAAAQAehIAAAAABAAAAAAAAAAEAD0JAAAAAAQBMS0AAAAABAB6EgAAAAAEAAAAAAAAAAQAPQkAAAAABAExLQAAAAAEAHoSAAAAAAQAAAAAAAAABAA9CQAAAAAEATEtAAAAAAQAehIAAAAABAAAAAAAAAAEAD0JAAAAAAQBMS0AAAAABAB6EgAAAAAEAAAAAAAAAAQAPQkAAAAABAExLQAAAAAEAHoSAAAAAAQAAAAAAAAABAA9CQAAAAAEATEtAAAAAAQAehIAAAAABAAAAAAAAAAEAD0JAAAAAAQBMS0AAAAABAB6EgAAAAAEAAAAAAAAAAQAPQkAAAAABAExLQAAAAAEAHoSAAAAAAQAAAAAAAAABAA9CQAAAAAEATEtAAAAAAQAehIAAAAABAAAAAAAAAAEAD0JAAAAAAQBMS0AAAAABAB6EgAAAAAEAAAAAAAAAAQAPQkAAAAABAExLQAAAAAEAHoSAAAAAAQAAAAAAAAABAA9CQAAAAAEATEtAAAAAAQAehIAAAAABAAAAAAAAAAEAD0JAAAAAAQBMS0AAAAABAB6EgAAAAAEAAAAAAAAAAQAPQkAAAAABAExLQAAAAAEAHoSAAAAAAQAAAAAAAAABAA9CQAAAAAEALcbAAAAAHHN0c2MAAAAAAAAAAQAAAAEAAABuAAAAAQAAAcxzdHN6AAAAAAAAAAAAAABuAAADCQAAABgAAAAOAAAADgAAAAwAAAASAAAADgAAAAwAAAAMAAAAEgAAAA4AAAAMAAAADAAAABIAAAAOAAAADAAAAAwAAAASAAAADgAAAAwAAAAMAAAAEgAAAA4AAAAMAAAADAAAABIAAAAOAAAADAAAAAwAAAASAAAADgAAAAwAAAAMAAAAEgAAAA4AAAAMAAAADAAAABIAAAAOAAAADAAAAAwAAAASAAAADgAAAAwAAAAMAAAAEgAAAA4AAAAMAAAADAAAABIAAAAOAAAADAAAAAwAAAASAAAADgAAAAwAAAAMAAAAEgAAAA4AAAAMAAAADAAAABIAAAAOAAAADAAAAAwAAAASAAAADgAAAAwAAAAMAAAAEgAAAA4AAAAMAAAADAAAABIAAAAOAAAADAAAAAwAAAASAAAADgAAAAwAAAAMAAAAEgAAAA4AAAAMAAAADAAAABIAAAAOAAAADAAAAAwAAAASAAAADgAAAAwAAAAMAAAAEgAAAA4AAAAMAAAADAAAABIAAAAOAAAADAAAAAwAAAASAAAADgAAAAwAAAAMAAAAEgAAAA4AAAAMAAAADAAAABMAAAAUc3RjbwAAAAAAAAABAAAIKwAAACt1ZHRhAAAAI6llbmMAFwAAdmxjIDIuMi4xIHN0cmVhbSBvdXRwdXQAAAAId2lkZQAACRRtZGF0AAACrgX//6vcRem95tlIt5Ys2CDZI+7veDI2NCAtIGNvcmUgMTQyIC0gSC4yNjQvTVBFRy00IEFWQyBjb2RlYyAtIENvcHlsZWZ0IDIwMDMtMjAxNCAtIGh0dHA6Ly93d3cudmlkZW9sYW4ub3JnL3gyNjQuaHRtbCAtIG9wdGlvbnM6IGNhYmFjPTEgcmVmPTMgZGVibG9jaz0xOjA6MCBhbmFseXNlPTB4MzoweDEzIG1lPWhleCBzdWJtZT03IHBzeT0xIHBzeV9yZD0xLjAwOjAuMDAgbWl4ZWRfcmVmPTEgbWVfcmFuZ2U9MTYgY2hyb21hX21lPTEgdHJlbGxpcz0xIDh4OGRjdD0xIGNxbT0wIGRlYWR6b25lPTIxLDExIGZhc3RfcHNraXA9MSBjaHJvbWFfcXBfb2Zmc2V0PS0yIHRocmVhZHM9MTIgbG9va2FoZWFkX3RocmVhZHM9MSBzbGljZWRfdGhyZWFkcz0wIG5yPTAgZGVjaW1hdGU9MSBpbnRlcmxhY2VkPTAgYmx1cmF5X2NvbXBhdD0wIGNvbnN0cmFpbmVkX2ludHJhPTAgYmZyYW1lcz0zIGJfcHlyYW1pZD0yIGJfYWRhcHQ9MSBiX2JpYXM9MCBkaXJlY3Q9MSB3ZWlnaHRiPTEgb3Blbl9nb3A9MCB3ZWlnaHRwPTIga2V5aW50PTI1MCBrZXlpbnRfbWluPTEgc2NlbmVjdXQ9NDAgaW50cmFfcmVmcmVzaD0wIHJjX2xvb2thaGVhZD00MCByYz1hYnIgbWJ0cmVlPTEgYml0cmF0ZT0xMDAgcmF0ZXRvbD0xLjAgcWNvbXA9MC42MCBxcG1pbj0xMCBxcG1heD01MSBxcHN0ZXA9NCBpcF9yYXRpbz0xLjQwIGFxPTE6MS4wMACAAAAAU2WIhAAQ/8ltlOe+cTZuGkKg+aRtuivcDZ0pBsfsEi9p/i1yU9DxS2lq4dXTinViF1URBKXgnzKBd/Uh1bkhHtMrwrRcOJslD01UB+fyaL6ef+DBAAAAFEGaJGxBD5B+v+a+4QqF3MgBXz9MAAAACkGeQniH/+94r6EAAAAKAZ5hdEN/8QytwAAAAAgBnmNqQ3/EgQAAAA5BmmhJqEFomUwIIf/+4QAAAApBnoZFESw//76BAAAACAGepXRDf8SBAAAACAGep2pDf8SAAAAADkGarEmoQWyZTAgh//7gAAAACkGeykUVLD//voEAAAAIAZ7pdEN/xIAAAAAIAZ7rakN/xIAAAAAOQZrwSahBbJlMCCH//uEAAAAKQZ8ORRUsP/++gQAAAAgBny10Q3/EgQAAAAgBny9qQ3/EgAAAAA5BmzRJqEFsmUwIIf/+4AAAAApBn1JFFSw//76BAAAACAGfcXRDf8SAAAAACAGfc2pDf8SAAAAADkGbeEmoQWyZTAgh//7hAAAACkGflkUVLD//voAAAAAIAZ+1dEN/xIEAAAAIAZ+3akN/xIEAAAAOQZu8SahBbJlMCCH//uAAAAAKQZ/aRRUsP/++gQAAAAgBn/l0Q3/EgAAAAAgBn/tqQ3/EgQAAAA5Bm+BJqEFsmUwIIf/+4QAAAApBnh5FFSw//76AAAAACAGePXRDf8SAAAAACAGeP2pDf8SBAAAADkGaJEmoQWyZTAgh//7gAAAACkGeQkUVLD//voEAAAAIAZ5hdEN/xIAAAAAIAZ5jakN/xIEAAAAOQZpoSahBbJlMCCH//uEAAAAKQZ6GRRUsP/++gQAAAAgBnqV0Q3/EgQAAAAgBnqdqQ3/EgAAAAA5BmqxJqEFsmUwIIf/+4AAAAApBnspFFSw//76BAAAACAGe6XRDf8SAAAAACAGe62pDf8SAAAAADkGa8EmoQWyZTAgh//7hAAAACkGfDkUVLD//voEAAAAIAZ8tdEN/xIEAAAAIAZ8vakN/xIAAAAAOQZs0SahBbJlMCCH//uAAAAAKQZ9SRRUsP/++gQAAAAgBn3F0Q3/EgAAAAAgBn3NqQ3/EgAAAAA5Bm3hJqEFsmUwIIf/+4QAAAApBn5ZFFSw//76AAAAACAGftXRDf8SBAAAACAGft2pDf8SBAAAADkGbvEmoQWyZTAgh//7gAAAACkGf2kUVLD//voEAAAAIAZ/5dEN/xIAAAAAIAZ/7akN/xIEAAAAOQZvgSahBbJlMCCH//uEAAAAKQZ4eRRUsP/++gAAAAAgBnj10Q3/EgAAAAAgBnj9qQ3/EgQAAAA5BmiRJqEFsmUwIIf/+4AAAAApBnkJFFSw//76BAAAACAGeYXRDf8SAAAAACAGeY2pDf8SBAAAADkGaaEmoQWyZTAgh//7hAAAACkGehkUVLD//voEAAAAIAZ6ldEN/xIEAAAAIAZ6nakN/xIAAAAAOQZqsSahBbJlMCCH//uAAAAAKQZ7KRRUsP/++gQAAAAgBnul0Q3/EgAAAAAgBnutqQ3/EgAAAAA5BmvBJqEFsmUwIIf/+4QAAAApBnw5FFSw//76BAAAACAGfLXRDf8SBAAAACAGfL2pDf8SAAAAADkGbNEmoQWyZTAgh//7gAAAACkGfUkUVLD//voEAAAAIAZ9xdEN/xIAAAAAIAZ9zakN/xIAAAAAOQZt4SahBbJlMCCH//uEAAAAKQZ+WRRUsP/++gAAAAAgBn7V0Q3/EgQAAAAgBn7dqQ3/EgQAAAA5Bm7xJqEFsmUwIIf/+4AAAAApBn9pFFSw//76BAAAACAGf+XRDf8SAAAAACAGf+2pDf8SBAAAADkGb4EmoQWyZTAgh//7hAAAACkGeHkUVLD//voAAAAAIAZ49dEN/xIAAAAAIAZ4/akN/xIEAAAAOQZokSahBbJlMCCH//uAAAAAKQZ5CRRUsP/++gQAAAAgBnmF0Q3/EgAAAAAgBnmNqQ3/EgQAAAA5BmmhJqEFsmUwIIf/+4QAAAApBnoZFFSw//76BAAAACAGepXRDf8SBAAAACAGep2pDf8SAAAAADkGarEmoQWyZTAgh//7gAAAACkGeykUVLD//voEAAAAIAZ7pdEN/xIAAAAAIAZ7rakN/xIAAAAAPQZruSahBbJlMFEw3//7B'); - video.play(); - } - }; - - this.release = function() { - video.pause(); - video.src = ''; - }; -} - -function iOSWakeLock() { - var timer = null; - - this.request = function() { - if (!timer) { - timer = setInterval(function() { - window.location = window.location; - setTimeout(window.stop, 0); - }, 30000); - } - } - - this.release = function() { - if (timer) { - clearInterval(timer); - timer = null; - } - } -} - - -function getWakeLock() { - var userAgent = navigator.userAgent || navigator.vendor || window.opera; - if (userAgent.match(/iPhone/i) || userAgent.match(/iPod/i)) { - return iOSWakeLock; - } else { - return AndroidWakeLock; - } -} - -module.exports = getWakeLock(); -},{"./util.js":22}],25:[function(_dereq_,module,exports){ -/* - * Copyright 2015 Google Inc. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -var Util = _dereq_('./util.js'); -var CardboardVRDisplay = _dereq_('./cardboard-vr-display.js'); -var MouseKeyboardVRDisplay = _dereq_('./mouse-keyboard-vr-display.js'); -// Uncomment to add positional tracking via webcam. -//var WebcamPositionSensorVRDevice = require('./webcam-position-sensor-vr-device.js'); -var VRDisplay = _dereq_('./base.js').VRDisplay; -var VRFrameData = _dereq_('./base.js').VRFrameData; -var HMDVRDevice = _dereq_('./base.js').HMDVRDevice; -var PositionSensorVRDevice = _dereq_('./base.js').PositionSensorVRDevice; -var VRDisplayHMDDevice = _dereq_('./display-wrappers.js').VRDisplayHMDDevice; -var VRDisplayPositionSensorDevice = _dereq_('./display-wrappers.js').VRDisplayPositionSensorDevice; - -function WebVRPolyfill() { - this.displays = []; - this.devices = []; // For deprecated objects - this.devicesPopulated = false; - this.nativeWebVRAvailable = this.isWebVRAvailable(); - this.nativeLegacyWebVRAvailable = this.isDeprecatedWebVRAvailable(); - - if (!this.nativeLegacyWebVRAvailable) { - if (!this.nativeWebVRAvailable) { - this.enablePolyfill(); - } - if (WebVRConfig.ENABLE_DEPRECATED_API) { - this.enableDeprecatedPolyfill(); - } - } - - // Put a shim in place to update the API to 1.1 if needed. - InstallWebVRSpecShim(); -} - -WebVRPolyfill.prototype.isWebVRAvailable = function() { - return ('getVRDisplays' in navigator); -}; - -WebVRPolyfill.prototype.isDeprecatedWebVRAvailable = function() { - return ('getVRDevices' in navigator) || ('mozGetVRDevices' in navigator); -}; - -WebVRPolyfill.prototype.populateDevices = function() { - if (this.devicesPopulated) { - return; - } - - // Initialize our virtual VR devices. - var vrDisplay = null; - - // Add a Cardboard VRDisplay on compatible mobile devices - if (this.isCardboardCompatible()) { - vrDisplay = new CardboardVRDisplay(); - this.displays.push(vrDisplay); - - // For backwards compatibility - if (WebVRConfig.ENABLE_DEPRECATED_API) { - this.devices.push(new VRDisplayHMDDevice(vrDisplay)); - this.devices.push(new VRDisplayPositionSensorDevice(vrDisplay)); - } - } - - // Add a Mouse and Keyboard driven VRDisplay for desktops/laptops - if (!this.isMobile() && !WebVRConfig.MOUSE_KEYBOARD_CONTROLS_DISABLED) { - vrDisplay = new MouseKeyboardVRDisplay(); - this.displays.push(vrDisplay); - - // For backwards compatibility - if (WebVRConfig.ENABLE_DEPRECATED_API) { - this.devices.push(new VRDisplayHMDDevice(vrDisplay)); - this.devices.push(new VRDisplayPositionSensorDevice(vrDisplay)); - } - } - - // Uncomment to add positional tracking via webcam. - //if (!this.isMobile() && WebVRConfig.ENABLE_DEPRECATED_API) { - // positionDevice = new WebcamPositionSensorVRDevice(); - // this.devices.push(positionDevice); - //} - - this.devicesPopulated = true; -}; - -WebVRPolyfill.prototype.enablePolyfill = function() { - // Provide navigator.getVRDisplays. - navigator.getVRDisplays = this.getVRDisplays.bind(this); - - // Provide the VRDisplay object. - window.VRDisplay = VRDisplay; - // Provide the VRFrameData object. - window.VRFrameData = VRFrameData; -}; - -WebVRPolyfill.prototype.enableDeprecatedPolyfill = function() { - // Provide navigator.getVRDevices. - navigator.getVRDevices = this.getVRDevices.bind(this); - - // Provide the CardboardHMDVRDevice and PositionSensorVRDevice objects. - window.HMDVRDevice = HMDVRDevice; - window.PositionSensorVRDevice = PositionSensorVRDevice; -}; - -WebVRPolyfill.prototype.getVRDisplays = function() { - this.populateDevices(); - var displays = this.displays; - return new Promise(function(resolve, reject) { - try { - resolve(displays); - } catch (e) { - reject(e); - } - }); -}; - -WebVRPolyfill.prototype.getVRDevices = function() { - console.warn('getVRDevices is deprecated. Please update your code to use getVRDisplays instead.'); - var self = this; - return new Promise(function(resolve, reject) { - try { - if (!self.devicesPopulated) { - if (self.nativeWebVRAvailable) { - return navigator.getVRDisplays(function(displays) { - for (var i = 0; i < displays.length; ++i) { - self.devices.push(new VRDisplayHMDDevice(displays[i])); - self.devices.push(new VRDisplayPositionSensorDevice(displays[i])); - } - self.devicesPopulated = true; - resolve(self.devices); - }, reject); - } - - if (self.nativeLegacyWebVRAvailable) { - return (navigator.getVRDDevices || navigator.mozGetVRDevices)(function(devices) { - for (var i = 0; i < devices.length; ++i) { - if (devices[i] instanceof HMDVRDevice) { - self.devices.push(devices[i]); - } - if (devices[i] instanceof PositionSensorVRDevice) { - self.devices.push(devices[i]); - } - } - self.devicesPopulated = true; - resolve(self.devices); - }, reject); - } - } - - self.populateDevices(); - resolve(self.devices); - } catch (e) { - reject(e); - } - }); -}; - -/** - * Determine if a device is mobile. - */ -WebVRPolyfill.prototype.isMobile = function() { - return /Android/i.test(navigator.userAgent) || - /iPhone|iPad|iPod/i.test(navigator.userAgent); -}; - -WebVRPolyfill.prototype.isCardboardCompatible = function() { - // For now, support all iOS and Android devices. - // Also enable the WebVRConfig.FORCE_VR flag for debugging. - return this.isMobile() || WebVRConfig.FORCE_ENABLE_VR; -}; - -// Installs a shim that updates a WebVR 1.0 spec implementation to WebVR 1.1 -function InstallWebVRSpecShim() { - if ('VRDisplay' in window && !('VRFrameData' in window)) { - // Provide the VRFrameData object. - window.VRFrameData = VRFrameData; - - // A lot of Chrome builds don't have depthNear and depthFar, even - // though they're in the WebVR 1.0 spec. Patch them in if they're not present. - if(!('depthNear' in window.VRDisplay.prototype)) { - window.VRDisplay.prototype.depthNear = 0.01; - } - - if(!('depthFar' in window.VRDisplay.prototype)) { - window.VRDisplay.prototype.depthFar = 10000.0; - } - - window.VRDisplay.prototype.getFrameData = function(frameData) { - return Util.frameDataFromPose(frameData, this.getPose(), this); - } - } -}; - -module.exports.WebVRPolyfill = WebVRPolyfill; -module.exports.InstallWebVRSpecShim = InstallWebVRSpecShim; - -},{"./base.js":2,"./cardboard-vr-display.js":5,"./display-wrappers.js":8,"./mouse-keyboard-vr-display.js":15,"./util.js":22}]},{},[13]); diff --git a/servo/tests/html/webvr/js/third-party/wglu/wglu-debug-geometry.js b/servo/tests/html/webvr/js/third-party/wglu/wglu-debug-geometry.js deleted file mode 100644 index 3f48e1aad78c..000000000000 --- a/servo/tests/html/webvr/js/third-party/wglu/wglu-debug-geometry.js +++ /dev/null @@ -1,270 +0,0 @@ -/* -Copyright (c) 2016, Brandon Jones. - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. -*/ - -var WGLUDebugGeometry = (function() { - - "use strict"; - - var debugGeomVS = [ - "uniform mat4 projectionMat;", - "uniform mat4 viewMat;", - "uniform mat4 modelMat;", - "attribute vec3 position;", - - "void main() {", - " gl_Position = projectionMat * viewMat * modelMat * vec4( position, 1.0 );", - "}", - ].join("\n"); - - var debugGeomFS = [ - "precision mediump float;", - "uniform vec4 color;", - - "void main() {", - " gl_FragColor = color;", - "}", - ].join("\n"); - - var DebugGeometry = function(gl) { - this.gl = gl; - - this.projMat = mat4.create(); - this.viewMat = mat4.create(); - this.modelMat = mat4.create(); - - this.program = new WGLUProgram(gl); - this.program.attachShaderSource(debugGeomVS, gl.VERTEX_SHADER); - this.program.attachShaderSource(debugGeomFS, gl.FRAGMENT_SHADER); - this.program.bindAttribLocation({ position: 0 }); - this.program.link(); - - var verts = []; - var indices = []; - - // - // Cube Geometry - // - this.cubeIndexOffset = indices.length; - - var size = 0.5; - // Bottom - var idx = verts.length / 3.0; - indices.push(idx, idx+1, idx+2); - indices.push(idx, idx+2, idx+3); - - verts.push(-size, -size, -size); - verts.push(+size, -size, -size); - verts.push(+size, -size, +size); - verts.push(-size, -size, +size); - - // Top - idx = verts.length / 3.0; - indices.push(idx, idx+2, idx+1); - indices.push(idx, idx+3, idx+2); - - verts.push(-size, +size, -size); - verts.push(+size, +size, -size); - verts.push(+size, +size, +size); - verts.push(-size, +size, +size); - - // Left - idx = verts.length / 3.0; - indices.push(idx, idx+2, idx+1); - indices.push(idx, idx+3, idx+2); - - verts.push(-size, -size, -size); - verts.push(-size, +size, -size); - verts.push(-size, +size, +size); - verts.push(-size, -size, +size); - - // Right - idx = verts.length / 3.0; - indices.push(idx, idx+1, idx+2); - indices.push(idx, idx+2, idx+3); - - verts.push(+size, -size, -size); - verts.push(+size, +size, -size); - verts.push(+size, +size, +size); - verts.push(+size, -size, +size); - - // Back - idx = verts.length / 3.0; - indices.push(idx, idx+2, idx+1); - indices.push(idx, idx+3, idx+2); - - verts.push(-size, -size, -size); - verts.push(+size, -size, -size); - verts.push(+size, +size, -size); - verts.push(-size, +size, -size); - - // Front - idx = verts.length / 3.0; - indices.push(idx, idx+1, idx+2); - indices.push(idx, idx+2, idx+3); - - verts.push(-size, -size, +size); - verts.push(+size, -size, +size); - verts.push(+size, +size, +size); - verts.push(-size, +size, +size); - - this.cubeIndexCount = indices.length - this.cubeIndexOffset; - - // - // Cone Geometry - // - this.coneIndexOffset = indices.length; - - var size = 0.5; - var conePointVertex = verts.length / 3.0; - var coneBaseVertex = conePointVertex+1; - var coneSegments = 16; - - // Point - verts.push(0, size, 0); - - // Base Vertices - for (var i = 0; i < coneSegments; ++i) { - if (i > 0) { - idx = verts.length / 3.0; - indices.push(idx-1, conePointVertex, idx); - } - - var rad = ((Math.PI * 2) / coneSegments) * i; - verts.push(Math.sin(rad) * (size / 2.0), -size, Math.cos(rad) * (size / 2.0)); - } - - // Last triangle to fill the gap - indices.push(idx, conePointVertex, coneBaseVertex); - - // Base triangles - for (var i = 2; i < coneSegments; ++i) { - indices.push(coneBaseVertex, coneBaseVertex+(i-1), coneBaseVertex+i); - } - - this.coneIndexCount = indices.length - this.coneIndexOffset; - - // - // Rect geometry - // - this.rectIndexOffset = indices.length; - - idx = verts.length / 3.0; - indices.push(idx, idx+1, idx+2, idx+3, idx); - - verts.push(0, 0, 0); - verts.push(1, 0, 0); - verts.push(1, 1, 0); - verts.push(0, 1, 0); - - this.rectIndexCount = indices.length - this.rectIndexOffset; - - this.vertBuffer = gl.createBuffer(); - gl.bindBuffer(gl.ARRAY_BUFFER, this.vertBuffer); - gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(verts), gl.STATIC_DRAW); - - this.indexBuffer = gl.createBuffer(); - gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, this.indexBuffer); - gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, new Uint16Array(indices), gl.STATIC_DRAW); - }; - - DebugGeometry.prototype.bind = function(projectionMat, viewMat) { - var gl = this.gl; - var program = this.program; - - program.use(); - - gl.uniformMatrix4fv(program.uniform.projectionMat, false, projectionMat); - gl.uniformMatrix4fv(program.uniform.viewMat, false, viewMat); - - gl.bindBuffer(gl.ARRAY_BUFFER, this.vertBuffer); - gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, this.indexBuffer); - - gl.enableVertexAttribArray(program.attrib.position); - - gl.vertexAttribPointer(program.attrib.position, 3, gl.FLOAT, false, 12, 0); - }; - - DebugGeometry.prototype.bindOrtho = function() { - mat4.ortho(this.projMat, 0, this.gl.canvas.width, this.gl.canvas.height, 0, 0.1, 1024); - mat4.identity(this.viewMat); - this.bind(this.projMat, this.viewMat); - }; - - DebugGeometry.prototype._bindUniforms = function(orientation, position, scale, color) { - if (!position) { position = [0, 0, 0]; } - if (!orientation) { orientation = [0, 0, 0, 1]; } - if (!scale) { scale = [1, 1, 1]; } - if (!color) { color = [1, 0, 0, 1]; } - - mat4.fromRotationTranslationScale(this.modelMat, orientation, position, scale); - this.gl.uniformMatrix4fv(this.program.uniform.modelMat, false, this.modelMat); - this.gl.uniform4fv(this.program.uniform.color, color); - }; - - DebugGeometry.prototype.drawCube = function(orientation, position, size, color) { - var gl = this.gl; - - if (!size) { size = 1; } - this._bindUniforms(orientation, position, [size, size, size], color); - gl.drawElements(gl.TRIANGLES, this.cubeIndexCount, gl.UNSIGNED_SHORT, this.cubeIndexOffset * 2.0); - }; - - DebugGeometry.prototype.drawBox = function(orientation, position, scale, color) { - var gl = this.gl; - - this._bindUniforms(orientation, position, scale, color); - gl.drawElements(gl.TRIANGLES, this.cubeIndexCount, gl.UNSIGNED_SHORT, this.cubeIndexOffset * 2.0); - }; - - DebugGeometry.prototype.drawBoxWithMatrix = function(mat, color) { - var gl = this.gl; - - gl.uniformMatrix4fv(this.program.uniform.modelMat, false, mat); - gl.uniform4fv(this.program.uniform.color, color); - gl.drawElements(gl.TRIANGLES, this.cubeIndexCount, gl.UNSIGNED_SHORT, this.cubeIndexOffset * 2.0); - }; - - DebugGeometry.prototype.drawRect = function(x, y, width, height, color) { - var gl = this.gl; - - this._bindUniforms(null, [x, y, -1], [width, height, 1], color); - gl.drawElements(gl.LINE_STRIP, this.rectIndexCount, gl.UNSIGNED_SHORT, this.rectIndexOffset * 2.0); - }; - - DebugGeometry.prototype.drawCone = function(orientation, position, size, color) { - var gl = this.gl; - - if (!size) { size = 1; } - this._bindUniforms(orientation, position, [size, size, size], color); - gl.drawElements(gl.TRIANGLES, this.coneIndexCount, gl.UNSIGNED_SHORT, this.coneIndexOffset * 2.0); - }; - - DebugGeometry.prototype.drawConeWithMatrix = function(mat, color) { - var gl = this.gl; - - gl.uniformMatrix4fv(this.program.uniform.modelMat, false, mat); - gl.uniform4fv(this.program.uniform.color, color); - gl.drawElements(gl.TRIANGLES, this.coneIndexCount, gl.UNSIGNED_SHORT, this.coneIndexOffset * 2.0); - }; - - return DebugGeometry; -})(); diff --git a/servo/tests/html/webvr/js/third-party/wglu/wglu-preserve-state.js b/servo/tests/html/webvr/js/third-party/wglu/wglu-preserve-state.js deleted file mode 100644 index 16e1b6049ec1..000000000000 --- a/servo/tests/html/webvr/js/third-party/wglu/wglu-preserve-state.js +++ /dev/null @@ -1,162 +0,0 @@ -/* -Copyright (c) 2016, Brandon Jones. - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. -*/ - -/* -Caches specified GL state, runs a callback, and restores the cached state when -done. - -Example usage: - -var savedState = [ - gl.ARRAY_BUFFER_BINDING, - - // TEXTURE_BINDING_2D or _CUBE_MAP must always be followed by the texure unit. - gl.TEXTURE_BINDING_2D, gl.TEXTURE0, - - gl.CLEAR_COLOR, -]; -// After this call the array buffer, texture unit 0, active texture, and clear -// color will be restored. The viewport will remain changed, however, because -// gl.VIEWPORT was not included in the savedState list. -WGLUPreserveGLState(gl, savedState, function(gl) { - gl.viewport(0, 0, gl.drawingBufferWidth, gl.drawingBufferHeight); - - gl.bindBuffer(gl.ARRAY_BUFFER, buffer); - gl.bufferData(gl.ARRAY_BUFFER, ....); - - gl.activeTexture(gl.TEXTURE0); - gl.bindTexture(gl.TEXTURE_2D, texture); - gl.texImage2D(gl.TEXTURE_2D, ...); - - gl.clearColor(1, 0, 0, 1); - gl.clear(gl.COLOR_BUFFER_BIT); -}); - -Note that this is not intended to be fast. Managing state in your own code to -avoid redundant state setting and querying will always be faster. This function -is most useful for cases where you may not have full control over the WebGL -calls being made, such as tooling or effect injectors. -*/ - -function WGLUPreserveGLState(gl, bindings, callback) { - if (!bindings) { - callback(gl); - return; - } - - var boundValues = []; - - var activeTexture = null; - for (var i = 0; i < bindings.length; ++i) { - var binding = bindings[i]; - switch (binding) { - case gl.TEXTURE_BINDING_2D: - case gl.TEXTURE_BINDING_CUBE_MAP: - var textureUnit = bindings[++i]; - if (textureUnit < gl.TEXTURE0 || textureUnit > gl.TEXTURE31) { - console.error("TEXTURE_BINDING_2D or TEXTURE_BINDING_CUBE_MAP must be followed by a valid texture unit"); - boundValues.push(null, null); - break; - } - if (!activeTexture) { - activeTexture = gl.getParameter(gl.ACTIVE_TEXTURE); - } - gl.activeTexture(textureUnit); - boundValues.push(gl.getParameter(binding), null); - break; - case gl.ACTIVE_TEXTURE: - activeTexture = gl.getParameter(gl.ACTIVE_TEXTURE); - boundValues.push(null); - break; - default: - boundValues.push(gl.getParameter(binding)); - break; - } - } - - callback(gl); - - for (var i = 0; i < bindings.length; ++i) { - var binding = bindings[i]; - var boundValue = boundValues[i]; - switch (binding) { - case gl.ACTIVE_TEXTURE: - break; // Ignore this binding, since we special-case it to happen last. - case gl.ARRAY_BUFFER_BINDING: - gl.bindBuffer(gl.ARRAY_BUFFER, boundValue); - break; - case gl.COLOR_CLEAR_VALUE: - gl.clearColor(boundValue[0], boundValue[1], boundValue[2], boundValue[3]); - break; - case gl.COLOR_WRITEMASK: - gl.colorMask(boundValue[0], boundValue[1], boundValue[2], boundValue[3]); - break; - case gl.CURRENT_PROGRAM: - gl.useProgram(boundValue); - break; - case gl.ELEMENT_ARRAY_BUFFER_BINDING: - gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, boundValue); - break; - case gl.FRAMEBUFFER_BINDING: - gl.bindFramebuffer(gl.FRAMEBUFFER, boundValue); - break; - case gl.RENDERBUFFER_BINDING: - gl.bindRenderbuffer(gl.RENDERBUFFER, boundValue); - break; - case gl.TEXTURE_BINDING_2D: - var textureUnit = bindings[++i]; - if (textureUnit < gl.TEXTURE0 || textureUnit > gl.TEXTURE31) - break; - gl.activeTexture(textureUnit); - gl.bindTexture(gl.TEXTURE_2D, boundValue); - break; - case gl.TEXTURE_BINDING_CUBE_MAP: - var textureUnit = bindings[++i]; - if (textureUnit < gl.TEXTURE0 || textureUnit > gl.TEXTURE31) - break; - gl.activeTexture(textureUnit); - gl.bindTexture(gl.TEXTURE_CUBE_MAP, boundValue); - break; - case gl.VIEWPORT: - gl.viewport(boundValue[0], boundValue[1], boundValue[2], boundValue[3]); - break; - case gl.BLEND: - case gl.CULL_FACE: - case gl.DEPTH_TEST: - case gl.SCISSOR_TEST: - case gl.STENCIL_TEST: - if (boundValue) { - gl.enable(binding); - } else { - gl.disable(binding); - } - break; - default: - console.log("No GL restore behavior for 0x" + binding.toString(16)); - break; - } - - if (activeTexture) { - gl.activeTexture(activeTexture); - } - } -} diff --git a/servo/tests/html/webvr/js/third-party/wglu/wglu-program.js b/servo/tests/html/webvr/js/third-party/wglu/wglu-program.js deleted file mode 100644 index 911182edb8f4..000000000000 --- a/servo/tests/html/webvr/js/third-party/wglu/wglu-program.js +++ /dev/null @@ -1,179 +0,0 @@ -/* -Copyright (c) 2015, Brandon Jones. - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. -*/ - -/* -Utility class to make loading shader programs easier. Does all the error -checking you typically want, automatically queries uniform and attribute -locations, and attempts to take advantage of some browser's ability to link -asynchronously by not querying any information from the program until it's -first use. -*/ -var WGLUProgram = (function() { - - "use strict"; - - // Attempts to allow the browser to asynchronously compile and link - var Program = function(gl) { - this.gl = gl; - this.program = gl.createProgram(); - this.attrib = null; - this.uniform = null; - - this._firstUse = true; - this._vertexShader = null; - this._fragmentShader = null; - } - - Program.prototype.attachShaderSource = function(source, type) { - var gl = this.gl; - var shader; - - switch (type) { - case gl.VERTEX_SHADER: - this._vertexShader = gl.createShader(type); - shader = this._vertexShader; - break; - case gl.FRAGMENT_SHADER: - this._fragmentShader = gl.createShader(type); - shader = this._fragmentShader; - break; - default: - console.Error("Invalid Shader Type:", type); - return; - } - - gl.attachShader(this.program, shader); - gl.shaderSource(shader, source); - gl.compileShader(shader); - } - - Program.prototype.attachShaderSourceFromXHR = function(url, type) { - var self = this; - return new Promise(function(resolve, reject) { - var xhr = new XMLHttpRequest(); - xhr.addEventListener("load", function (ev) { - if (xhr.status == 200) { - self.attachShaderSource(xhr.response, type); - resolve(); - } else { - reject(xhr.statusText); - } - }, false); - xhr.open("GET", url, true); - xhr.send(null); - }); - } - - Program.prototype.attachShaderSourceFromTag = function(tagId, type) { - var shaderTag = document.getElementById(tagId); - if (!shaderTag) { - console.error("Shader source tag not found:", tagId); - return; - } - - if (!type) { - if (shaderTag.type == "x-shader/x-vertex") { - type = this.gl.VERTEX_SHADER; - } else if (shaderTag.type == "x-shader/x-fragment") { - type = this.gl.FRAGMENT_SHADER; - } else { - console.error("Invalid Shader Type:", shaderTag.type); - return; - } - } - - var src = ""; - var k = shaderTag.firstChild; - while (k) { - if (k.nodeType == 3) { - src += k.textContent; - } - k = k.nextSibling; - } - this.attachShaderSource(src, type); - } - - Program.prototype.bindAttribLocation = function(attribLocationMap) { - var gl = this.gl; - - if (attribLocationMap) { - this.attrib = {}; - for (var attribName in attribLocationMap) { - gl.bindAttribLocation(this.program, attribLocationMap[attribName], attribName); - this.attrib[attribName] = attribLocationMap[attribName]; - } - } - } - - Program.prototype.transformFeedbackVaryings = function(varyings, type) { - gl.transformFeedbackVaryings(this.program, varyings, type); - } - - Program.prototype.link = function() { - this.gl.linkProgram(this.program); - } - - Program.prototype.use = function() { - var gl = this.gl; - - // If this is the first time the program has been used do all the error checking and - // attrib/uniform querying needed. - if (this._firstUse) { - if (!gl.getProgramParameter(this.program, gl.LINK_STATUS)) { - if (this._vertexShader && !gl.getShaderParameter(this._vertexShader, gl.COMPILE_STATUS)) { - console.error("Vertex shader compile error:", gl.getShaderInfoLog(this._vertexShader)); - } else if (this._fragmentShader && !gl.getShaderParameter(this._fragmentShader, gl.COMPILE_STATUS)) { - console.error("Fragment shader compile error:", gl.getShaderInfoLog(this._fragmentShader)); - } else { - console.error("Program link error:", gl.getProgramInfoLog(this.program)); - } - gl.deleteProgram(this.program); - this.program = null; - } else { - if (!this.attrib) { - this.attrib = {}; - var attribCount = gl.getProgramParameter(this.program, gl.ACTIVE_ATTRIBUTES); - for (var i = 0; i < attribCount; i++) { - var attribInfo = gl.getActiveAttrib(this.program, i); - this.attrib[attribInfo.name] = gl.getAttribLocation(this.program, attribInfo.name); - } - } - - this.uniform = {}; - var uniformCount = gl.getProgramParameter(this.program, gl.ACTIVE_UNIFORMS); - var uniformName = ""; - for (var i = 0; i < uniformCount; i++) { - var uniformInfo = gl.getActiveUniform(this.program, i); - uniformName = uniformInfo.name.replace("[0]", ""); - this.uniform[uniformName] = gl.getUniformLocation(this.program, uniformName); - } - } - gl.deleteShader(this._vertexShader); - gl.deleteShader(this._fragmentShader); - this._firstUse = false; - } - - gl.useProgram(this.program); - } - - return Program; -})(); diff --git a/servo/tests/html/webvr/js/third-party/wglu/wglu-stats.js b/servo/tests/html/webvr/js/third-party/wglu/wglu-stats.js deleted file mode 100644 index 70aee00671b5..000000000000 --- a/servo/tests/html/webvr/js/third-party/wglu/wglu-stats.js +++ /dev/null @@ -1,649 +0,0 @@ -/* -Copyright (c) 2016, Brandon Jones. - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. -*/ - -/* -Heavily inspired by Mr. Doobs stats.js, this FPS counter is rendered completely -with WebGL, allowing it to be shown in cases where overlaid HTML elements aren't -usable (like WebVR), or if you want the FPS counter to be rendered as part of -your scene. - -See stats-test.html for basic usage. -*/ -var WGLUStats = (function() { - - "use strict"; - - //-------------------- - // glMatrix functions - //-------------------- - - // These functions have been copied here from glMatrix (glmatrix.net) to allow - // this file to run standalone. - - var mat4_identity = function(out) { - out[0] = 1; - out[1] = 0; - out[2] = 0; - out[3] = 0; - out[4] = 0; - out[5] = 1; - out[6] = 0; - out[7] = 0; - out[8] = 0; - out[9] = 0; - out[10] = 1; - out[11] = 0; - out[12] = 0; - out[13] = 0; - out[14] = 0; - out[15] = 1; - return out; - }; - - var mat4_multiply = function (out, a, b) { - var a00 = a[0], a01 = a[1], a02 = a[2], a03 = a[3], - a10 = a[4], a11 = a[5], a12 = a[6], a13 = a[7], - a20 = a[8], a21 = a[9], a22 = a[10], a23 = a[11], - a30 = a[12], a31 = a[13], a32 = a[14], a33 = a[15]; - - // Cache only the current line of the second matrix - var b0 = b[0], b1 = b[1], b2 = b[2], b3 = b[3]; - out[0] = b0*a00 + b1*a10 + b2*a20 + b3*a30; - out[1] = b0*a01 + b1*a11 + b2*a21 + b3*a31; - out[2] = b0*a02 + b1*a12 + b2*a22 + b3*a32; - out[3] = b0*a03 + b1*a13 + b2*a23 + b3*a33; - - b0 = b[4]; b1 = b[5]; b2 = b[6]; b3 = b[7]; - out[4] = b0*a00 + b1*a10 + b2*a20 + b3*a30; - out[5] = b0*a01 + b1*a11 + b2*a21 + b3*a31; - out[6] = b0*a02 + b1*a12 + b2*a22 + b3*a32; - out[7] = b0*a03 + b1*a13 + b2*a23 + b3*a33; - - b0 = b[8]; b1 = b[9]; b2 = b[10]; b3 = b[11]; - out[8] = b0*a00 + b1*a10 + b2*a20 + b3*a30; - out[9] = b0*a01 + b1*a11 + b2*a21 + b3*a31; - out[10] = b0*a02 + b1*a12 + b2*a22 + b3*a32; - out[11] = b0*a03 + b1*a13 + b2*a23 + b3*a33; - - b0 = b[12]; b1 = b[13]; b2 = b[14]; b3 = b[15]; - out[12] = b0*a00 + b1*a10 + b2*a20 + b3*a30; - out[13] = b0*a01 + b1*a11 + b2*a21 + b3*a31; - out[14] = b0*a02 + b1*a12 + b2*a22 + b3*a32; - out[15] = b0*a03 + b1*a13 + b2*a23 + b3*a33; - return out; - }; - - var mat4_fromTranslation = function(out, v) { - out[0] = 1; - out[1] = 0; - out[2] = 0; - out[3] = 0; - out[4] = 0; - out[5] = 1; - out[6] = 0; - out[7] = 0; - out[8] = 0; - out[9] = 0; - out[10] = 1; - out[11] = 0; - out[12] = v[0]; - out[13] = v[1]; - out[14] = v[2]; - out[15] = 1; - return out; - }; - - var mat4_ortho = function (out, left, right, bottom, top, near, far) { - var lr = 1 / (left - right), - bt = 1 / (bottom - top), - nf = 1 / (near - far); - out[0] = -2 * lr; - out[1] = 0; - out[2] = 0; - out[3] = 0; - out[4] = 0; - out[5] = -2 * bt; - out[6] = 0; - out[7] = 0; - out[8] = 0; - out[9] = 0; - out[10] = 2 * nf; - out[11] = 0; - out[12] = (left + right) * lr; - out[13] = (top + bottom) * bt; - out[14] = (far + near) * nf; - out[15] = 1; - return out; - }; - - var mat4_translate = function (out, a, v) { - var x = v[0], y = v[1], z = v[2], - a00, a01, a02, a03, - a10, a11, a12, a13, - a20, a21, a22, a23; - - if (a === out) { - out[12] = a[0] * x + a[4] * y + a[8] * z + a[12]; - out[13] = a[1] * x + a[5] * y + a[9] * z + a[13]; - out[14] = a[2] * x + a[6] * y + a[10] * z + a[14]; - out[15] = a[3] * x + a[7] * y + a[11] * z + a[15]; - } else { - a00 = a[0]; a01 = a[1]; a02 = a[2]; a03 = a[3]; - a10 = a[4]; a11 = a[5]; a12 = a[6]; a13 = a[7]; - a20 = a[8]; a21 = a[9]; a22 = a[10]; a23 = a[11]; - - out[0] = a00; out[1] = a01; out[2] = a02; out[3] = a03; - out[4] = a10; out[5] = a11; out[6] = a12; out[7] = a13; - out[8] = a20; out[9] = a21; out[10] = a22; out[11] = a23; - - out[12] = a00 * x + a10 * y + a20 * z + a[12]; - out[13] = a01 * x + a11 * y + a21 * z + a[13]; - out[14] = a02 * x + a12 * y + a22 * z + a[14]; - out[15] = a03 * x + a13 * y + a23 * z + a[15]; - } - - return out; - }; - - var mat4_scale = function(out, a, v) { - var x = v[0], y = v[1], z = v[2]; - - out[0] = a[0] * x; - out[1] = a[1] * x; - out[2] = a[2] * x; - out[3] = a[3] * x; - out[4] = a[4] * y; - out[5] = a[5] * y; - out[6] = a[6] * y; - out[7] = a[7] * y; - out[8] = a[8] * z; - out[9] = a[9] * z; - out[10] = a[10] * z; - out[11] = a[11] * z; - out[12] = a[12]; - out[13] = a[13]; - out[14] = a[14]; - out[15] = a[15]; - return out; - }; - - //------------------- - // Utility functions - //------------------- - - function linkProgram(gl, vertexSource, fragmentSource, attribLocationMap) { - // No error checking for brevity. - var vertexShader = gl.createShader(gl.VERTEX_SHADER); - gl.shaderSource(vertexShader, vertexSource); - gl.compileShader(vertexShader); - - var fragmentShader = gl.createShader(gl.FRAGMENT_SHADER); - gl.shaderSource(fragmentShader, fragmentSource); - gl.compileShader(fragmentShader); - - var program = gl.createProgram(); - gl.attachShader(program, vertexShader); - gl.attachShader(program, fragmentShader); - - for (var attribName in attribLocationMap) - gl.bindAttribLocation(program, attribLocationMap[attribName], attribName); - - gl.linkProgram(program); - - gl.deleteShader(vertexShader); - gl.deleteShader(fragmentShader); - - return program; - } - - function getProgramUniforms(gl, program) { - var uniforms = {}; - var uniformCount = gl.getProgramParameter(program, gl.ACTIVE_UNIFORMS); - var uniformName = ""; - for (var i = 0; i < uniformCount; i++) { - var uniformInfo = gl.getActiveUniform(program, i); - uniformName = uniformInfo.name.replace("[0]", ""); - uniforms[uniformName] = gl.getUniformLocation(program, uniformName); - } - return uniforms; - } - - //---------------------------- - // Seven-segment text display - //---------------------------- - - var sevenSegmentVS = [ - "uniform mat4 projectionMat;", - "uniform mat4 modelViewMat;", - "attribute vec2 position;", - - "void main() {", - " gl_Position = projectionMat * modelViewMat * vec4( position, 0.0, 1.0 );", - "}", - ].join("\n"); - - var sevenSegmentFS = [ - "precision mediump float;", - "uniform vec4 color;", - - "void main() {", - " gl_FragColor = color;", - "}", - ].join("\n"); - - var SevenSegmentText = function (gl) { - this.gl = gl; - - this.attribs = { - position: 0, - color: 1 - }; - - this.program = linkProgram(gl, sevenSegmentVS, sevenSegmentFS, this.attribs); - this.uniforms = getProgramUniforms(gl, this.program); - - var verts = []; - var segmentIndices = {}; - var indices = []; - - var width = 0.5; - var thickness = 0.25; - this.kerning = 2.0; - - this.matrix = new Float32Array(16); - - function defineSegment(id, left, top, right, bottom) { - var idx = verts.length / 2; - verts.push( - left, top, - right, top, - right, bottom, - left, bottom); - - segmentIndices[id] = [ - idx, idx+2, idx+1, - idx, idx+3, idx+2]; - } - - var characters = {}; - this.characters = characters; - - function defineCharacter(c, segments) { - var character = { - character: c, - offset: indices.length * 2, - count: 0 - }; - - for (var i = 0; i < segments.length; ++i) { - var idx = segments[i]; - var segment = segmentIndices[idx]; - character.count += segment.length; - indices.push.apply(indices, segment); - } - - characters[c] = character; - } - - /* Segment layout is as follows: - - |-0-| - 3 4 - |-1-| - 5 6 - |-2-| - - */ - - defineSegment(0, -1, 1, width, 1-thickness); - defineSegment(1, -1, thickness*0.5, width, -thickness*0.5); - defineSegment(2, -1, -1+thickness, width, -1); - defineSegment(3, -1, 1, -1+thickness, -thickness*0.5); - defineSegment(4, width-thickness, 1, width, -thickness*0.5); - defineSegment(5, -1, thickness*0.5, -1+thickness, -1); - defineSegment(6, width-thickness, thickness*0.5, width, -1); - - - defineCharacter("0", [0, 2, 3, 4, 5, 6]); - defineCharacter("1", [4, 6]); - defineCharacter("2", [0, 1, 2, 4, 5]); - defineCharacter("3", [0, 1, 2, 4, 6]); - defineCharacter("4", [1, 3, 4, 6]); - defineCharacter("5", [0, 1, 2, 3, 6]); - defineCharacter("6", [0, 1, 2, 3, 5, 6]); - defineCharacter("7", [0, 4, 6]); - defineCharacter("8", [0, 1, 2, 3, 4, 5, 6]); - defineCharacter("9", [0, 1, 2, 3, 4, 6]); - defineCharacter("A", [0, 1, 3, 4, 5, 6]); - defineCharacter("B", [1, 2, 3, 5, 6]); - defineCharacter("C", [0, 2, 3, 5]); - defineCharacter("D", [1, 2, 4, 5, 6]); - defineCharacter("E", [0, 1, 2, 4, 6]); - defineCharacter("F", [0, 1, 3, 5]); - defineCharacter("P", [0, 1, 3, 4, 5]); - defineCharacter("-", [1]); - defineCharacter(" ", []); - defineCharacter("_", [2]); // Used for undefined characters - - this.vertBuffer = gl.createBuffer(); - gl.bindBuffer(gl.ARRAY_BUFFER, this.vertBuffer); - gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(verts), gl.DYNAMIC_DRAW); - - this.indexBuffer = gl.createBuffer(); - gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, this.indexBuffer); - gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, new Uint16Array(indices), gl.STATIC_DRAW); - }; - - SevenSegmentText.prototype.render = function(projectionMat, modelViewMat, text, r, g, b, a) { - var gl = this.gl; - - if (r == undefined || g == undefined || b == undefined) { - r = 0.0; - g = 1.0; - b = 0.0; - } - - if (a == undefined) - a = 1.0; - - gl.useProgram(this.program); - - gl.uniformMatrix4fv(this.uniforms.projectionMat, false, projectionMat); - gl.uniform4f(this.uniforms.color, r, g, b, a); - - gl.bindBuffer(gl.ARRAY_BUFFER, this.vertBuffer); - gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, this.indexBuffer); - - gl.enableVertexAttribArray(this.attribs.position); - gl.vertexAttribPointer(this.attribs.position, 2, gl.FLOAT, false, 8, 0); - - text = text.toUpperCase(); - - var offset = 0; - - for (var i = 0; i < text.length; ++i) { - var c; - if (text[i] in this.characters) { - c = this.characters[text[i]]; - } else { - c = this.characters["_"]; - } - - if (c.count != 0) { - mat4_fromTranslation(this.matrix, [offset, 0, 0]); - mat4_multiply(this.matrix, modelViewMat, this.matrix); - - gl.uniformMatrix4fv(this.uniforms.modelViewMat, false, this.matrix); - gl.drawElements(gl.TRIANGLES, c.count, gl.UNSIGNED_SHORT, c.offset); - - } - - offset += this.kerning; - } - } - - //----------- - // FPS Graph - //----------- - - var statsVS = [ - "uniform mat4 projectionMat;", - "uniform mat4 modelViewMat;", - "attribute vec3 position;", - "attribute vec3 color;", - "varying vec4 vColor;", - - "void main() {", - " vColor = vec4(color, 1.0);", - " gl_Position = projectionMat * modelViewMat * vec4( position, 1.0 );", - "}", - ].join("\n"); - - var statsFS = [ - "precision mediump float;", - "varying vec4 vColor;", - - "void main() {", - " gl_FragColor = vColor;", - "}", - ].join("\n"); - - var segments = 30; - var maxFPS = 90; - - function segmentToX(i) { - return ((0.9/segments) * i) - 0.45; - } - - function fpsToY(value) { - return (Math.min(value, maxFPS) * (0.7 / maxFPS)) - 0.45; - } - - function fpsToRGB(value) { - return { - r: Math.max(0.0, Math.min(1.0, 1.0 - (value/60))), - g: Math.max(0.0, Math.min(1.0, ((value-15)/(maxFPS-15)))), - b: Math.max(0.0, Math.min(1.0, ((value-15)/(maxFPS-15)))) - }; - } - - var now = /*( performance && performance.now ) ? performance.now.bind( performance ) :*/ Date.now; - - var Stats = function(gl) { - this.gl = gl; - - this.sevenSegmentText = new SevenSegmentText(gl); - - this.startTime = now(); - this.prevTime = this.startTime; - this.frames = 0; - this.fps = 0; - - this.orthoProjMatrix = new Float32Array(16); - this.orthoViewMatrix = new Float32Array(16); - this.modelViewMatrix = new Float32Array(16); - - // Hard coded because it doesn't change: - // Scale by 0.075 in X and Y - // Translate into upper left corner w/ z = 0.02 - this.textMatrix = new Float32Array([ - 0.075, 0, 0, 0, - 0, 0.075, 0, 0, - 0, 0, 1, 0, - -0.3625, 0.3625, 0.02, 1 - ]); - - this.lastSegment = 0; - - this.attribs = { - position: 0, - color: 1 - }; - - this.program = linkProgram(gl, statsVS, statsFS, this.attribs); - this.uniforms = getProgramUniforms(gl, this.program); - - var fpsVerts = []; - var fpsIndices = []; - - // Graph geometry - for (var i = 0; i < segments; ++i) { - // Bar top - fpsVerts.push(segmentToX(i), fpsToY(0), 0.02, 0.0, 1.0, 1.0); - fpsVerts.push(segmentToX(i+1), fpsToY(0), 0.02, 0.0, 1.0, 1.0); - - // Bar bottom - fpsVerts.push(segmentToX(i), fpsToY(0), 0.02, 0.0, 1.0, 1.0); - fpsVerts.push(segmentToX(i+1), fpsToY(0), 0.02, 0.0, 1.0, 1.0); - - var idx = i * 4; - fpsIndices.push(idx, idx+3, idx+1, - idx+3, idx, idx+2); - } - - function addBGSquare(left, bottom, right, top, z, r, g, b) { - var idx = fpsVerts.length / 6; - - fpsVerts.push(left, bottom, z, r, g, b); - fpsVerts.push(right, top, z, r, g, b); - fpsVerts.push(left, top, z, r, g, b); - fpsVerts.push(right, bottom, z, r, g, b); - - fpsIndices.push(idx, idx+1, idx+2, - idx, idx+3, idx+1); - }; - - // Panel Background - addBGSquare(-0.5, -0.5, 0.5, 0.5, 0.0, 0.0, 0.0, 0.125); - - // FPS Background - addBGSquare(-0.45, -0.45, 0.45, 0.25, 0.01, 0.0, 0.0, 0.4); - - // 30 FPS line - addBGSquare(-0.45, fpsToY(30), 0.45, fpsToY(32), 0.015, 0.5, 0.0, 0.5); - - // 60 FPS line - addBGSquare(-0.45, fpsToY(60), 0.45, fpsToY(62), 0.015, 0.2, 0.0, 0.75); - - this.fpsVertBuffer = gl.createBuffer(); - gl.bindBuffer(gl.ARRAY_BUFFER, this.fpsVertBuffer); - gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(fpsVerts), gl.DYNAMIC_DRAW); - - this.fpsIndexBuffer = gl.createBuffer(); - gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, this.fpsIndexBuffer); - gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, new Uint16Array(fpsIndices), gl.STATIC_DRAW); - - this.fpsIndexCount = fpsIndices.length; - }; - - Stats.prototype.begin = function() { - this.startTime = now(); - }; - - Stats.prototype.end = function() { - var time = now(); - - this.frames++; - - if (time > this.prevTime + 250) { - this.fps = Math.round((this.frames * 1000) / (time - this.prevTime)); - - this.updateGraph(this.fps); - - this.prevTime = time; - this.frames = 0; - } - }; - - Stats.prototype.updateGraph = function(value) { - var gl = this.gl; - - var color = fpsToRGB(value); - - gl.bindBuffer(gl.ARRAY_BUFFER, this.fpsVertBuffer); - - // Update the current segment with the new FPS value - var updateVerts = [ - segmentToX(this.lastSegment), fpsToY(value), 0.02, color.r, color.g, color.b, - segmentToX(this.lastSegment+1), fpsToY(value), 0.02, color.r, color.g, color.b, - segmentToX(this.lastSegment), fpsToY(0), 0.02, color.r, color.g, color.b, - segmentToX(this.lastSegment+1), fpsToY(0), 0.02, color.r, color.g, color.b, - ]; - - // Re-shape the next segment into the green "progress" line - color.r = 0.2; - color.g = 1.0; - color.b = 0.2; - - if (this.lastSegment == segments - 1) { - // If we're updating the last segment we need to do two bufferSubDatas - // to update the segment and turn the first segment into the progress line. - gl.bufferSubData(gl.ARRAY_BUFFER, this.lastSegment * 24 * 4, new Float32Array(updateVerts)); - updateVerts = [ - segmentToX(0), fpsToY(maxFPS), 0.02, color.r, color.g, color.b, - segmentToX(.25), fpsToY(maxFPS), 0.02, color.r, color.g, color.b, - segmentToX(0), fpsToY(0), 0.02, color.r, color.g, color.b, - segmentToX(.25), fpsToY(0), 0.02, color.r, color.g, color.b - ]; - gl.bufferSubData(gl.ARRAY_BUFFER, 0, new Float32Array(updateVerts)); - } else { - updateVerts.push( - segmentToX(this.lastSegment+1), fpsToY(maxFPS), 0.02, color.r, color.g, color.b, - segmentToX(this.lastSegment+1.25), fpsToY(maxFPS), 0.02, color.r, color.g, color.b, - segmentToX(this.lastSegment+1), fpsToY(0), 0.02, color.r, color.g, color.b, - segmentToX(this.lastSegment+1.25), fpsToY(0), 0.02, color.r, color.g, color.b - ); - gl.bufferSubData(gl.ARRAY_BUFFER, this.lastSegment * 24 * 4, new Float32Array(updateVerts)); - } - - this.lastSegment = (this.lastSegment+1) % segments; - }; - - Stats.prototype.render = function(projectionMat, modelViewMat) { - var gl = this.gl; - - // Render text first, minor win for early fragment discard - mat4_multiply(this.modelViewMatrix, modelViewMat, this.textMatrix); - this.sevenSegmentText.render(projectionMat, this.modelViewMatrix, this.fps + " FP5"); - - gl.useProgram(this.program); - - gl.uniformMatrix4fv(this.uniforms.projectionMat, false, projectionMat); - gl.uniformMatrix4fv(this.uniforms.modelViewMat, false, modelViewMat); - - gl.enableVertexAttribArray(this.attribs.position); - gl.enableVertexAttribArray(this.attribs.color); - - gl.bindBuffer(gl.ARRAY_BUFFER, this.fpsVertBuffer); - gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, this.fpsIndexBuffer); - - gl.vertexAttribPointer(this.attribs.position, 3, gl.FLOAT, false, 24, 0); - gl.vertexAttribPointer(this.attribs.color, 3, gl.FLOAT, false, 24, 12); - - // Draw the graph and background in a single call - gl.drawElements(gl.TRIANGLES, this.fpsIndexCount, gl.UNSIGNED_SHORT, 0); - } - - Stats.prototype.renderOrtho = function(x, y, width, height) { - var canvas = this.gl.canvas; - - if (x == undefined || y == undefined) { - x = 10 * window.devicePixelRatio; - y = 10 * window.devicePixelRatio; - } - if (width == undefined || height == undefined) { - width = 75 * window.devicePixelRatio; - height = 75 * window.devicePixelRatio; - } - - mat4_ortho(this.orthoProjMatrix, 0, canvas.width, 0, canvas.height, 0.1, 1024); - - mat4_identity(this.orthoViewMatrix); - mat4_translate(this.orthoViewMatrix, this.orthoViewMatrix, [x, canvas.height - height - y, -1]); - mat4_scale(this.orthoViewMatrix, this.orthoViewMatrix, [width, height, 1]); - mat4_translate(this.orthoViewMatrix, this.orthoViewMatrix, [0.5, 0.5, 0]); - - this.render(this.orthoProjMatrix, this.orthoViewMatrix); - } - - return Stats; -})(); diff --git a/servo/tests/html/webvr/js/third-party/wglu/wglu-texture.js b/servo/tests/html/webvr/js/third-party/wglu/wglu-texture.js deleted file mode 100644 index 6bfa368ab92c..000000000000 --- a/servo/tests/html/webvr/js/third-party/wglu/wglu-texture.js +++ /dev/null @@ -1,687 +0,0 @@ -/* -Copyright (c) 2015, Brandon Jones. - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. -*/ - -/* -Handles loading of textures of mutliple formats, tries to be efficent about it. - -Formats supported will vary by devices. Use the .supports() functions -to determine if a format is supported. Most of the time you can just call -loader.loadTexture("url"); and it will handle it based on the extension. -If the extension can't be relied on use the corresponding -.load("url") calls. -*/ -var WGLUTextureLoader = (function() { - - "use strict"; - - //============================// - // DXT constants and utilites // - //============================// - - // Utility functions - // Builds a numeric code for a given fourCC string - function fourCCToInt32(value) { - return value.charCodeAt(0) + - (value.charCodeAt(1) << 8) + - (value.charCodeAt(2) << 16) + - (value.charCodeAt(3) << 24); - } - - // Turns a fourCC numeric code into a string - function int32ToFourCC(value) { - return String.fromCharCode( - value & 0xff, - (value >> 8) & 0xff, - (value >> 16) & 0xff, - (value >> 24) & 0xff - ); - } - - // Calcualates the size of a compressed texture level in bytes - function textureLevelSize(format, width, height) { - switch (format) { - case COMPRESSED_RGB_S3TC_DXT1_EXT: - case COMPRESSED_RGB_ATC_WEBGL: - case COMPRESSED_RGB_ETC1_WEBGL: - return ((width + 3) >> 2) * ((height + 3) >> 2) * 8; - - case COMPRESSED_RGBA_S3TC_DXT3_EXT: - case COMPRESSED_RGBA_S3TC_DXT5_EXT: - case COMPRESSED_RGBA_ATC_EXPLICIT_ALPHA_WEBGL: - case COMPRESSED_RGBA_ATC_INTERPOLATED_ALPHA_WEBGL: - return ((width + 3) >> 2) * ((height + 3) >> 2) * 16; - - case COMPRESSED_RGB_PVRTC_4BPPV1_IMG: - case COMPRESSED_RGBA_PVRTC_4BPPV1_IMG: - return Math.floor((Math.max(width, 8) * Math.max(height, 8) * 4 + 7) / 8); - - case COMPRESSED_RGB_PVRTC_2BPPV1_IMG: - case COMPRESSED_RGBA_PVRTC_2BPPV1_IMG: - return Math.floor((Math.max(width, 16) * Math.max(height, 8) * 2 + 7) / 8); - - default: - return 0; - } - } - - // DXT formats, from: - // http://www.khronos.org/registry/webgl/extensions/WEBGL_compressed_texture_s3tc/ - var COMPRESSED_RGB_S3TC_DXT1_EXT = 0x83F0; - var COMPRESSED_RGBA_S3TC_DXT1_EXT = 0x83F1; - var COMPRESSED_RGBA_S3TC_DXT3_EXT = 0x83F2; - var COMPRESSED_RGBA_S3TC_DXT5_EXT = 0x83F3; - - // ATC formats, from: - // http://www.khronos.org/registry/webgl/extensions/WEBGL_compressed_texture_atc/ - var COMPRESSED_RGB_ATC_WEBGL = 0x8C92; - var COMPRESSED_RGBA_ATC_EXPLICIT_ALPHA_WEBGL = 0x8C93; - var COMPRESSED_RGBA_ATC_INTERPOLATED_ALPHA_WEBGL = 0x87EE; - - // DXT values and structures referenced from: - // http://msdn.microsoft.com/en-us/library/bb943991.aspx/ - var DDS_MAGIC = 0x20534444; - var DDSD_MIPMAPCOUNT = 0x20000; - var DDPF_FOURCC = 0x4; - - var DDS_HEADER_LENGTH = 31; // The header length in 32 bit ints. - - // Offsets into the header array. - var DDS_HEADER_MAGIC = 0; - - var DDS_HEADER_SIZE = 1; - var DDS_HEADER_FLAGS = 2; - var DDS_HEADER_HEIGHT = 3; - var DDS_HEADER_WIDTH = 4; - - var DDS_HEADER_MIPMAPCOUNT = 7; - - var DDS_HEADER_PF_FLAGS = 20; - var DDS_HEADER_PF_FOURCC = 21; - - // FourCC format identifiers. - var FOURCC_DXT1 = fourCCToInt32("DXT1"); - var FOURCC_DXT3 = fourCCToInt32("DXT3"); - var FOURCC_DXT5 = fourCCToInt32("DXT5"); - - var FOURCC_ATC = fourCCToInt32("ATC "); - var FOURCC_ATCA = fourCCToInt32("ATCA"); - var FOURCC_ATCI = fourCCToInt32("ATCI"); - - //==================// - // Crunch constants // - //==================// - - // Taken from crnlib.h - var CRN_FORMAT = { - cCRNFmtInvalid: -1, - - cCRNFmtDXT1: 0, - // cCRNFmtDXT3 is not currently supported when writing to CRN - only DDS. - cCRNFmtDXT3: 1, - cCRNFmtDXT5: 2 - - // Crunch supports more formats than this, but we can't use them here. - }; - - // Mapping of Crunch formats to DXT formats. - var DXT_FORMAT_MAP = {}; - DXT_FORMAT_MAP[CRN_FORMAT.cCRNFmtDXT1] = COMPRESSED_RGB_S3TC_DXT1_EXT; - DXT_FORMAT_MAP[CRN_FORMAT.cCRNFmtDXT3] = COMPRESSED_RGBA_S3TC_DXT3_EXT; - DXT_FORMAT_MAP[CRN_FORMAT.cCRNFmtDXT5] = COMPRESSED_RGBA_S3TC_DXT5_EXT; - - //===============// - // PVR constants // - //===============// - - // PVR formats, from: - // http://www.khronos.org/registry/webgl/extensions/WEBGL_compressed_texture_pvrtc/ - var COMPRESSED_RGB_PVRTC_4BPPV1_IMG = 0x8C00; - var COMPRESSED_RGB_PVRTC_2BPPV1_IMG = 0x8C01; - var COMPRESSED_RGBA_PVRTC_4BPPV1_IMG = 0x8C02; - var COMPRESSED_RGBA_PVRTC_2BPPV1_IMG = 0x8C03; - - // ETC1 format, from: - // http://www.khronos.org/registry/webgl/extensions/WEBGL_compressed_texture_etc1/ - var COMPRESSED_RGB_ETC1_WEBGL = 0x8D64; - - var PVR_FORMAT_2BPP_RGB = 0; - var PVR_FORMAT_2BPP_RGBA = 1; - var PVR_FORMAT_4BPP_RGB = 2; - var PVR_FORMAT_4BPP_RGBA = 3; - var PVR_FORMAT_ETC1 = 6; - var PVR_FORMAT_DXT1 = 7; - var PVR_FORMAT_DXT3 = 9; - var PVR_FORMAT_DXT5 = 5; - - var PVR_HEADER_LENGTH = 13; // The header length in 32 bit ints. - var PVR_MAGIC = 0x03525650; //0x50565203; - - // Offsets into the header array. - var PVR_HEADER_MAGIC = 0; - var PVR_HEADER_FORMAT = 2; - var PVR_HEADER_HEIGHT = 6; - var PVR_HEADER_WIDTH = 7; - var PVR_HEADER_MIPMAPCOUNT = 11; - var PVR_HEADER_METADATA = 12; - - //============// - // Misc Utils // - //============// - - // When an error occurs set the texture to a 1x1 black pixel - // This prevents WebGL errors from attempting to use unrenderable textures - // and clears out stale data if we're re-using a texture. - function clearOnError(gl, error, texture, callback) { - if (console) { - console.error(error); - } - gl.bindTexture(gl.TEXTURE_2D, texture); - gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGB, 1, 1, 0, gl.RGB, gl.UNSIGNED_BYTE, new Uint8Array([0, 0, 0])); - gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST); - gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST); - - // Notify the user that an error occurred and the texture is ready. - if (callback) { callback(texture, error, null); } - } - - function isPowerOfTwo(n) { - return (n & (n - 1)) === 0; - } - - function getExtension(gl, name) { - var vendorPrefixes = ["", "WEBKIT_", "MOZ_"]; - var ext = null; - for (var i in vendorPrefixes) { - ext = gl.getExtension(vendorPrefixes[i] + name); - if (ext) { break; } - } - return ext; - } - - //==================// - // DDS File Reading // - //==================// - - // Parse a DDS file and provide information about the raw DXT data it contains to the given callback. - function parseDDS(arrayBuffer, callback, errorCallback) { - // Callbacks must be provided. - if (!callback || !errorCallback) { return; } - - // Get a view of the arrayBuffer that represents the DDS header. - var header = new Int32Array(arrayBuffer, 0, DDS_HEADER_LENGTH); - - // Do some sanity checks to make sure this is a valid DDS file. - if(header[DDS_HEADER_MAGIC] != DDS_MAGIC) { - errorCallback("Invalid magic number in DDS header"); - return 0; - } - - if(!header[DDS_HEADER_PF_FLAGS] & DDPF_FOURCC) { - errorCallback("Unsupported format, must contain a FourCC code"); - return 0; - } - - // Determine what type of compressed data the file contains. - var fourCC = header[DDS_HEADER_PF_FOURCC]; - var internalFormat; - switch(fourCC) { - case FOURCC_DXT1: - internalFormat = COMPRESSED_RGB_S3TC_DXT1_EXT; - break; - - case FOURCC_DXT3: - internalFormat = COMPRESSED_RGBA_S3TC_DXT3_EXT; - break; - - case FOURCC_DXT5: - internalFormat = COMPRESSED_RGBA_S3TC_DXT5_EXT; - break; - - case FOURCC_ATC: - internalFormat = COMPRESSED_RGB_ATC_WEBGL; - break; - - case FOURCC_ATCA: - internalFormat = COMPRESSED_RGBA_ATC_EXPLICIT_ALPHA_WEBGL; - break; - - case FOURCC_ATCI: - internalFormat = COMPRESSED_RGBA_ATC_INTERPOLATED_ALPHA_WEBGL; - break; - - - default: - errorCallback("Unsupported FourCC code: " + int32ToFourCC(fourCC)); - return; - } - - // Determine how many mipmap levels the file contains. - var levels = 1; - if(header[DDS_HEADER_FLAGS] & DDSD_MIPMAPCOUNT) { - levels = Math.max(1, header[DDS_HEADER_MIPMAPCOUNT]); - } - - // Gather other basic metrics and a view of the raw the DXT data. - var width = header[DDS_HEADER_WIDTH]; - var height = header[DDS_HEADER_HEIGHT]; - var dataOffset = header[DDS_HEADER_SIZE] + 4; - var dxtData = new Uint8Array(arrayBuffer, dataOffset); - - // Pass the DXT information to the callback for uploading. - callback(dxtData, width, height, levels, internalFormat); - } - - //==================// - // PVR File Reading // - //==================// - - // Parse a PVR file and provide information about the raw texture data it contains to the given callback. - function parsePVR(arrayBuffer, callback, errorCallback) { - // Callbacks must be provided. - if (!callback || !errorCallback) { return; } - - // Get a view of the arrayBuffer that represents the DDS header. - var header = new Int32Array(arrayBuffer, 0, PVR_HEADER_LENGTH); - - // Do some sanity checks to make sure this is a valid DDS file. - if(header[PVR_HEADER_MAGIC] != PVR_MAGIC) { - errorCallback("Invalid magic number in PVR header"); - return 0; - } - - // Determine what type of compressed data the file contains. - var format = header[PVR_HEADER_FORMAT]; - var internalFormat; - switch(format) { - case PVR_FORMAT_2BPP_RGB: - internalFormat = COMPRESSED_RGB_PVRTC_2BPPV1_IMG; - break; - - case PVR_FORMAT_2BPP_RGBA: - internalFormat = COMPRESSED_RGBA_PVRTC_2BPPV1_IMG; - break; - - case PVR_FORMAT_4BPP_RGB: - internalFormat = COMPRESSED_RGB_PVRTC_4BPPV1_IMG; - break; - - case PVR_FORMAT_4BPP_RGBA: - internalFormat = COMPRESSED_RGBA_PVRTC_4BPPV1_IMG; - break; - - case PVR_FORMAT_ETC1: - internalFormat = COMPRESSED_RGB_ETC1_WEBGL; - break; - - case PVR_FORMAT_DXT1: - internalFormat = COMPRESSED_RGB_S3TC_DXT1_EXT; - break; - - case PVR_FORMAT_DXT3: - internalFormat = COMPRESSED_RGBA_S3TC_DXT3_EXT; - break; - - case PVR_FORMAT_DXT5: - internalFormat = COMPRESSED_RGBA_S3TC_DXT5_EXT; - break; - - default: - errorCallback("Unsupported PVR format: " + format); - return; - } - - // Gather other basic metrics and a view of the raw the DXT data. - var width = header[PVR_HEADER_WIDTH]; - var height = header[PVR_HEADER_HEIGHT]; - var levels = header[PVR_HEADER_MIPMAPCOUNT]; - var dataOffset = header[PVR_HEADER_METADATA] + 52; - var pvrtcData = new Uint8Array(arrayBuffer, dataOffset); - - // Pass the PVRTC information to the callback for uploading. - callback(pvrtcData, width, height, levels, internalFormat); - } - - //=============// - // IMG loading // - //=============// - - /* - This function provides a method for loading webgl textures using a pool of - image elements, which has very low memory overhead. For more details see: - http://blog.tojicode.com/2012/03/javascript-memory-optimization-and.html - */ - var loadImgTexture = (function createTextureLoader() { - var MAX_CACHE_IMAGES = 16; - - var textureImageCache = new Array(MAX_CACHE_IMAGES); - var cacheTop = 0; - var remainingCacheImages = MAX_CACHE_IMAGES; - var pendingTextureRequests = []; - - var TextureImageLoader = function(loadedCallback) { - var self = this; - var blackPixel = new Uint8Array([0, 0, 0]); - - this.gl = null; - this.texture = null; - this.callback = null; - - this.image = new Image(); - this.image.crossOrigin = 'anonymous'; - this.image.addEventListener('load', function() { - var gl = self.gl; - gl.bindTexture(gl.TEXTURE_2D, self.texture); - - var startTime = Date.now(); - gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, self.image); - - if (isPowerOfTwo(self.image.width) && isPowerOfTwo(self.image.height)) { - gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR); - gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR_MIPMAP_NEAREST); - gl.generateMipmap(gl.TEXTURE_2D); - } else { - gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR); - gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR); - } - var uploadTime = Date.now() - startTime; - - if(self.callback) { - var stats = { - width: self.image.width, - height: self.image.height, - internalFormat: gl.RGBA, - levelZeroSize: self.image.width * self.image.height * 4, - uploadTime: uploadTime - }; - self.callback(self.texture, null, stats); - } - loadedCallback(self); - }, false); - this.image.addEventListener('error', function(ev) { - clearOnError(self.gl, 'Image could not be loaded: ' + self.image.src, self.texture, self.callback); - loadedCallback(self); - }, false); - }; - - TextureImageLoader.prototype.loadTexture = function(gl, src, texture, callback) { - this.gl = gl; - this.texture = texture; - this.callback = callback; - this.image.src = src; - }; - - var PendingTextureRequest = function(gl, src, texture, callback) { - this.gl = gl; - this.src = src; - this.texture = texture; - this.callback = callback; - }; - - function releaseTextureImageLoader(til) { - var req; - if(pendingTextureRequests.length) { - req = pendingTextureRequests.shift(); - til.loadTexture(req.gl, req.src, req.texture, req.callback); - } else { - textureImageCache[cacheTop++] = til; - } - } - - return function(gl, src, texture, callback) { - var til; - - if(cacheTop) { - til = textureImageCache[--cacheTop]; - til.loadTexture(gl, src, texture, callback); - } else if (remainingCacheImages) { - til = new TextureImageLoader(releaseTextureImageLoader); - til.loadTexture(gl, src, texture, callback); - --remainingCacheImages; - } else { - pendingTextureRequests.push(new PendingTextureRequest(gl, src, texture, callback)); - } - - return texture; - }; - })(); - - //=====================// - // TextureLoader Class // - //=====================// - - // This class is our public interface. - var TextureLoader = function(gl) { - this.gl = gl; - - // Load the compression format extensions, if available - this.dxtExt = getExtension(gl, "WEBGL_compressed_texture_s3tc"); - this.pvrtcExt = getExtension(gl, "WEBGL_compressed_texture_pvrtc"); - this.atcExt = getExtension(gl, "WEBGL_compressed_texture_atc"); - this.etc1Ext = getExtension(gl, "WEBGL_compressed_texture_etc1"); - - // Returns whether or not the compressed format is supported by the WebGL implementation - TextureLoader.prototype._formatSupported = function(format) { - switch (format) { - case COMPRESSED_RGB_S3TC_DXT1_EXT: - case COMPRESSED_RGBA_S3TC_DXT3_EXT: - case COMPRESSED_RGBA_S3TC_DXT5_EXT: - return !!this.dxtExt; - - case COMPRESSED_RGB_PVRTC_4BPPV1_IMG: - case COMPRESSED_RGBA_PVRTC_4BPPV1_IMG: - case COMPRESSED_RGB_PVRTC_2BPPV1_IMG: - case COMPRESSED_RGBA_PVRTC_2BPPV1_IMG: - return !!this.pvrtcExt; - - case COMPRESSED_RGB_ATC_WEBGL: - case COMPRESSED_RGBA_ATC_EXPLICIT_ALPHA_WEBGL: - case COMPRESSED_RGBA_ATC_INTERPOLATED_ALPHA_WEBGL: - return !!this.atcExt; - - case COMPRESSED_RGB_ETC1_WEBGL: - return !!this.etc1Ext; - - default: - return false; - } - } - - // Uploads compressed texture data to the GPU. - TextureLoader.prototype._uploadCompressedData = function(data, width, height, levels, internalFormat, texture, callback) { - var gl = this.gl; - gl.bindTexture(gl.TEXTURE_2D, texture); - - var offset = 0; - - var stats = { - width: width, - height: height, - internalFormat: internalFormat, - levelZeroSize: textureLevelSize(internalFormat, width, height), - uploadTime: 0 - }; - - var startTime = Date.now(); - // Loop through each mip level of compressed texture data provided and upload it to the given texture. - for (var i = 0; i < levels; ++i) { - // Determine how big this level of compressed texture data is in bytes. - var levelSize = textureLevelSize(internalFormat, width, height); - // Get a view of the bytes for this level of DXT data. - var dxtLevel = new Uint8Array(data.buffer, data.byteOffset + offset, levelSize); - // Upload! - gl.compressedTexImage2D(gl.TEXTURE_2D, i, internalFormat, width, height, 0, dxtLevel); - // The next mip level will be half the height and width of this one. - width = width >> 1; - height = height >> 1; - // Advance the offset into the compressed texture data past the current mip level's data. - offset += levelSize; - } - stats.uploadTime = Date.now() - startTime; - - // We can't use gl.generateMipmaps with compressed textures, so only use - // mipmapped filtering if the compressed texture data contained mip levels. - if (levels > 1) { - gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR); - gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR_MIPMAP_NEAREST); - } else { - gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR); - gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR); - } - - // Notify the user that the texture is ready. - if (callback) { callback(texture, null, stats); } - } - - TextureLoader.prototype.supportsDXT = function() { - return !!this.dxtExt; - } - - TextureLoader.prototype.supportsPVRTC = function() { - return !!this.pvrtcExt; - } - - TextureLoader.prototype.supportsATC = function() { - return !!this.atcExt; - } - - TextureLoader.prototype.supportsETC1 = function() { - return !!this.etc1Ext; - } - - // Loads a image file into the given texture. - // Supports any format that can be loaded into an img tag - // If no texture is provided one is created and returned. - TextureLoader.prototype.loadIMG = function(src, texture, callback) { - if(!texture) { - texture = this.gl.createTexture(); - } - - loadImgTexture(gl, src, texture, callback); - - return texture; - } - - // Loads a DDS file into the given texture. - // If no texture is provided one is created and returned. - TextureLoader.prototype.loadDDS = function(src, texture, callback) { - var self = this; - if (!texture) { - texture = this.gl.createTexture(); - } - - // Load the file via XHR. - var xhr = new XMLHttpRequest(); - xhr.addEventListener('load', function (ev) { - if (xhr.status == 200) { - // If the file loaded successfully parse it. - parseDDS(xhr.response, function(dxtData, width, height, levels, internalFormat) { - if (!self._formatSupported(internalFormat)) { - clearOnError(self.gl, "Texture format not supported", texture, callback); - return; - } - // Upload the parsed DXT data to the texture. - self._uploadCompressedData(dxtData, width, height, levels, internalFormat, texture, callback); - }, function(error) { - clearOnError(self.gl, error, texture, callback); - }); - } else { - clearOnError(self.gl, xhr.statusText, texture, callback); - } - }, false); - xhr.open('GET', src, true); - xhr.responseType = 'arraybuffer'; - xhr.send(null); - - return texture; - } - - // Loads a PVR file into the given texture. - // If no texture is provided one is created and returned. - TextureLoader.prototype.loadPVR = function(src, texture, callback) { - var self = this; - if(!texture) { - texture = this.gl.createTexture(); - } - - // Load the file via XHR. - var xhr = new XMLHttpRequest(); - xhr.addEventListener('load', function (ev) { - if (xhr.status == 200) { - // If the file loaded successfully parse it. - parsePVR(xhr.response, function(dxtData, width, height, levels, internalFormat) { - if (!self._formatSupported(internalFormat)) { - clearOnError(self.gl, "Texture format not supported", texture, callback); - return; - } - // Upload the parsed PVR data to the texture. - self._uploadCompressedData(dxtData, width, height, levels, internalFormat, texture, callback); - }, function(error) { - clearOnError(self.gl, error, texture, callback); - }); - } else { - clearOnError(self.gl, xhr.statusText, texture, callback); - } - }, false); - xhr.open('GET', src, true); - xhr.responseType = 'arraybuffer'; - xhr.send(null); - - return texture; - } - - // Loads a texture from a file. Guesses the type based on extension. - // If no texture is provided one is created and returned. - TextureLoader.prototype.loadTexture = function(src, texture, callback) { - // Shamelessly lifted from StackOverflow :) - // http://stackoverflow.com/questions/680929 - var re = /(?:\.([^.]+))?$/; - var ext = re.exec(src)[1] || ''; - ext = ext.toLowerCase(); - - switch(ext) { - case 'dds': - return this.loadDDS(src, texture, callback); - case 'pvr': - return this.loadPVR(src, texture, callback); - default: - return this.loadIMG(src, texture, callback); - } - } - - // Sets a texture to a solid RGBA color - // If no texture is provided one is created and returned. - TextureLoader.prototype.makeSolidColor = function(r, g, b, a, texture) { - var gl = this.gl; - var data = new Uint8Array([r, g, b, a]); - if(!texture) { - texture = gl.createTexture(); - } - gl.bindTexture(gl.TEXTURE_2D, texture); - gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 1, 1, 0, gl.RGBA, gl.UNSIGNED_BYTE, data); - gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST); - gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST); - return texture; - } - } - - return TextureLoader; -})(); diff --git a/servo/tests/html/webvr/js/third-party/wglu/wglu-url.js b/servo/tests/html/webvr/js/third-party/wglu/wglu-url.js deleted file mode 100644 index 43be65831bda..000000000000 --- a/servo/tests/html/webvr/js/third-party/wglu/wglu-url.js +++ /dev/null @@ -1,94 +0,0 @@ -/* -Copyright (c) 2015, Brandon Jones. - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. -*/ - -/* -Provides a simple way to get values from the query string if they're present -and use a default value if not. Not strictly a "WebGL" utility, but I use it -frequently enough for debugging that I wanted to include it here. - -Example: -For the URL http://example.com/index.html?particleCount=1000 - -WGLUUrl.getInt("particleCount", 100); // URL overrides, returns 1000 -WGLUUrl.getInt("particleSize", 10); // Not in URL, returns default of 10 -*/ -var WGLUUrl = (function() { - - "use strict"; - - var urlArgs = null; - - function ensureArgsCached() { - if (!urlArgs) { - urlArgs = {}; - var query = window.location.search.substring(1); - var vars = query.split("&"); - for (var i = 0; i < vars.length; i++) { - var pair = vars[i].split("="); - urlArgs[pair[0].toLowerCase()] = unescape(pair[1]); - } - } - } - - function getString(name, defaultValue) { - ensureArgsCached(); - var lcaseName = name.toLowerCase(); - if (lcaseName in urlArgs) { - return urlArgs[lcaseName]; - } - return defaultValue; - } - - function getInt(name, defaultValue) { - ensureArgsCached(); - var lcaseName = name.toLowerCase(); - if (lcaseName in urlArgs) { - return parseInt(urlArgs[lcaseName], 10); - } - return defaultValue; - } - - function getFloat(name, defaultValue) { - ensureArgsCached(); - var lcaseName = name.toLowerCase(); - if (lcaseName in urlArgs) { - return parseFloat(urlArgs[lcaseName]); - } - return defaultValue; - } - - function getBool(name, defaultValue) { - ensureArgsCached(); - var lcaseName = name.toLowerCase(); - if (lcaseName in urlArgs) { - return parseInt(urlArgs[lcaseName], 10) != 0; - } - return defaultValue; - } - - return { - getString: getString, - getInt: getInt, - getFloat: getFloat, - getBool: getBool - }; -})(); diff --git a/servo/tests/html/webvr/js/vr-audio-panner.js b/servo/tests/html/webvr/js/vr-audio-panner.js deleted file mode 100644 index 292d1cc366a8..000000000000 --- a/servo/tests/html/webvr/js/vr-audio-panner.js +++ /dev/null @@ -1,284 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -(function (VRAudioPanner) { - - 'use strict'; - - // Default settings for panning. Cone parameters are experimentally - // determined. - var _PANNING_MODEL = 'HRTF'; - var _DISTANCE_MODEL = 'inverse'; - var _CONE_INNER_ANGLE = 60; - var _CONE_OUTER_ANGLE = 120; - var _CONE_OUTER_GAIN = 0.25; - - // Super-simple web audio version detection. - var _LEGACY_WEBAUDIO = window.hasOwnProperty('webkitAudioContext') && !window.hasOwnProperty('AudioContext'); - if (_LEGACY_WEBAUDIO) - console.log('[VRAudioPanner] outdated version of Web Audio API detected.'); - - // Master audio context. - var _context = _LEGACY_WEBAUDIO ? new webkitAudioContext() : new AudioContext(); - - - /** - * A buffer source player with HRTF panning for testing purpose. - * @param {Object} options Default options. - * @param {Number} options.gain Sound object gain. (0.0~1.0) - * @param {Number} options.buffer AudioBuffer to play. - * @param {Number} options.detune Detune parameter. (cent) - * @param {Array} options.position x, y, z position in a array. - */ - function TestSource (options) { - - this._src = _context.createBufferSource(); - this._out = _context.createGain(); - this._panner = _context.createPanner(); - this._analyser = _context.createAnalyser(); - - this._src.connect(this._out); - this._out.connect(this._analyser); - this._analyser.connect(this._panner); - this._panner.connect(_context.destination); - - this._src.buffer = options.buffer; - this._src.loop = true; - this._out.gain.value = options.gain; - - this._analyser.fftSize = 1024; - this._analyser.smoothingTimeConstant = 0.85; - this._lastRMSdB = 0.0; - - this._panner.panningModel = _PANNING_MODEL; - this._panner.distanceModel = _DISTANCE_MODEL; - this._panner.coneInnerAngle = _CONE_INNER_ANGLE; - this._panner.coneOuterAngle = _CONE_OUTER_ANGLE; - this._panner.coneOuterGain = _CONE_OUTER_GAIN; - - this._position = [0, 0, 0]; - this._orientation = [1, 0, 0]; - - this._analyserBuffer = new Uint8Array(this._analyser.fftSize); - - if (!_LEGACY_WEBAUDIO) { - this._src.detune.value = (options.detune || 0); - this._analyserBuffer = new Float32Array(this._analyser.fftSize); - } - - this.setPosition(options.position); - this.setOrientation(options.orientation); - - }; - - TestSource.prototype.start = function () { - this._src.start(0); - }; - - TestSource.prototype.stop = function () { - this._src.stop(0); - }; - - TestSource.prototype.getPosition = function () { - return this._position; - }; - - TestSource.prototype.setPosition = function (position) { - if (position) { - this._position[0] = position[0]; - this._position[1] = position[1]; - this._position[2] = position[2]; - } - - this._panner.setPosition.apply(this._panner, this._position); - }; - - TestSource.prototype.getOrientation = function () { - return this._orientation; - }; - - TestSource.prototype.setOrientation = function (orientation) { - if (orientation) { - this._orientation[0] = orientation[0]; - this._orientation[1] = orientation[1]; - this._orientation[2] = orientation[2]; - } - - this._panner.setOrientation.apply(this._panner, this._orientation); - }; - - TestSource.prototype.getCubeScale = function () { - // Safari does not support getFloatTimeDomainData(), so fallback to the - // naive spectral energy sum. This is relative expensive. - if (_LEGACY_WEBAUDIO) { - this._analyser.getByteFrequencyData(this._analyserBuffer); - - for (var k = 0, total = 0; k < this._analyserBuffer.length; ++k) - total += this._analyserBuffer[k]; - total /= this._analyserBuffer.length; - - return (total / 256.0) * 1.5; - } - - this._analyser.getFloatTimeDomainData(this._analyserBuffer); - for (var i = 0, sum = 0; i < this._analyserBuffer.length; ++i) - sum += this._analyserBuffer[i] * this._analyserBuffer[i]; - - // Calculate RMS and convert it to DB for perceptual loudness. - var rms = Math.sqrt(sum / this._analyserBuffer.length); - var db = 30 + 10 / Math.LN10 * Math.log(rms <= 0 ? 0.0001 : rms); - - // Moving average with the alpha of 0.525. Experimentally determined. - this._lastRMSdB += 0.525 * ((db < 0 ? 0 : db) - this._lastRMSdB); - - // Scaling by 1/30 is also experimentally determined. - return this._lastRMSdB / 30.0; - }; - - - // Internal helper: load a file into a buffer. (github.com/hoch/spiral) - function _loadAudioFile(context, fileInfo, done) { - var xhr = new XMLHttpRequest(); - xhr.open('GET', fileInfo.url); - xhr.responseType = 'arraybuffer'; - - xhr.onload = function () { - if (xhr.status === 200) { - context.decodeAudioData(xhr.response, - function (buffer) { - console.log('[VRAudioPanner] File loaded: ' + fileInfo.url); - done(fileInfo.name, buffer); - }, - function (message) { - console.log('[VRAudioPanner] Decoding failure: ' + fileInfo.url + ' (' + message + ')'); - done(fileInfo.name, null); - }); - } else { - console.log('[VRAudioPanner] XHR Error: ' + fileInfo.url + ' (' + xhr.statusText + ')'); - done(fileInfo.name, null); - } - }; - - xhr.onerror = function (event) { - console.log('[VRAudioPanner] XHR Network failure: ' + fileInfo.url); - done(fileInfo.name, null); - }; - - xhr.send(); - } - - - /** - * A wrapper/container class for multiple file loaders. - * @param {Object} context AudioContext - * @param {Object} audioFileData Audio file info in the format of {name, url} - * @param {Function} resolve Resolution handler for promise. - * @param {Function} reject Rejection handler for promise. - * @param {Function} progress Progress event handler. - */ - function AudioBufferManager(context, audioFileData, resolve, reject, progress) { - this._context = context; - this._resolve = resolve; - this._reject = reject; - this._progress = progress; - - this._buffers = new Map(); - this._loadingTasks = {}; - - // Iterating file loading. - for (var i = 0; i < audioFileData.length; i++) { - var fileInfo = audioFileData[i]; - - // Check for duplicates filename and quit if it happens. - if (this._loadingTasks.hasOwnProperty(fileInfo.name)) { - console.log('[VRAudioPanner] Duplicated filename in AudioBufferManager: ' + fileInfo.name); - return; - } - - // Mark it as pending (0) - this._loadingTasks[fileInfo.name] = 0; - _loadAudioFile(this._context, fileInfo, this._done.bind(this)); - } - } - - AudioBufferManager.prototype._done = function (filename, buffer) { - // Label the loading task. - this._loadingTasks[filename] = buffer !== null ? 'loaded' : 'failed'; - - // A failed task will be a null buffer. - this._buffers.set(filename, buffer); - - this._updateProgress(filename); - }; - - AudioBufferManager.prototype._updateProgress = function (filename) { - var numberOfFinishedTasks = 0, numberOfFailedTask = 0; - var numberOfTasks = 0; - - for (var task in this._loadingTasks) { - numberOfTasks++; - if (this._loadingTasks[task] === 'loaded') - numberOfFinishedTasks++; - else if (this._loadingTasks[task] === 'failed') - numberOfFailedTask++; - } - - if (typeof this._progress === 'function') - this._progress(filename, numberOfFinishedTasks, numberOfTasks); - - if (numberOfFinishedTasks === numberOfTasks) - this._resolve(this._buffers); - - if (numberOfFinishedTasks + numberOfFailedTask === numberOfTasks) - this._reject(this._buffers); - }; - - /** - * Returns true if the web audio implementation is outdated. - * @return {Boolean} - */ - VRAudioPanner.isWebAudioOutdated = function () { - return _LEGACY_WEBAUDIO; - } - - /** - * Static method for updating listener's position. - * @param {Array} position Listener position in x, y, z. - */ - VRAudioPanner.setListenerPosition = function (position) { - _context.listener.setPosition.apply(_context.listener, position); - }; - - /** - * Static method for updating listener's orientation. - * @param {Array} orientation Listener orientation in x, y, z. - * @param {Array} orientation Listener's up vector in x, y, z. - */ - VRAudioPanner.setListenerOrientation = function (orientation, upvector) { - _context.listener.setOrientation( - orientation[0], orientation[1], orientation[2], - upvector[0], upvector[1], upvector[2]); - }; - - /** - * Load an audio file asynchronously. - * @param {Array} dataModel Audio file info in the format of {name, url} - * @param {Function} onprogress Callback function for reporting the progress. - * @return {Promise} Promise. - */ - VRAudioPanner.loadAudioFiles = function (dataModel, onprogress) { - return new Promise(function (resolve, reject) { - new AudioBufferManager(_context, dataModel, resolve, reject, onprogress); - }); - }; - - /** - * Create a source player. See TestSource class for parameter description. - * @return {TestSource} - */ - VRAudioPanner.createTestSource = function (options) { - return new TestSource(options); - }; - -})(VRAudioPanner = {}); diff --git a/servo/tests/html/webvr/js/vr-cube-island.js b/servo/tests/html/webvr/js/vr-cube-island.js deleted file mode 100644 index e21a10e11bd2..000000000000 --- a/servo/tests/html/webvr/js/vr-cube-island.js +++ /dev/null @@ -1,210 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -/* global mat4, WGLUProgram */ - -/* -Like CubeSea, but designed around a users physical space. One central platform -that maps to the users play area and several floating cubes that sit just -those boundries (just to add visual interest) -*/ -window.VRCubeIsland = (function () { - "use strict"; - - var cubeIslandVS = [ - "uniform mat4 projectionMat;", - "uniform mat4 modelViewMat;", - "attribute vec3 position;", - "attribute vec2 texCoord;", - "varying vec2 vTexCoord;", - - "void main() {", - " vTexCoord = texCoord;", - " gl_Position = projectionMat * modelViewMat * vec4( position, 1.0 );", - "}", - ].join("\n"); - - var cubeIslandFS = [ - "precision mediump float;", - "uniform sampler2D diffuse;", - "varying vec2 vTexCoord;", - - "void main() {", - " gl_FragColor = texture2D(diffuse, vTexCoord);", - "}", - ].join("\n"); - - var CubeIsland = function (gl, texture, width, depth) { - this.gl = gl; - - this.statsMat = mat4.create(); - - this.texture = texture; - - this.program = new WGLUProgram(gl); - this.program.attachShaderSource(cubeIslandVS, gl.VERTEX_SHADER); - this.program.attachShaderSource(cubeIslandFS, gl.FRAGMENT_SHADER); - this.program.bindAttribLocation({ - position: 0, - texCoord: 1 - }); - this.program.link(); - - this.vertBuffer = gl.createBuffer(); - this.indexBuffer = gl.createBuffer(); - - this.resize(width, depth); - }; - - CubeIsland.prototype.resize = function (width, depth) { - var gl = this.gl; - - this.width = width; - this.depth = depth; - - var cubeVerts = []; - var cubeIndices = []; - - // Build a single box. - function appendBox (left, bottom, back, right, top, front) { - // Bottom - var idx = cubeVerts.length / 5.0; - cubeIndices.push(idx, idx + 1, idx + 2); - cubeIndices.push(idx, idx + 2, idx + 3); - - cubeVerts.push(left, bottom, back, 0.0, 1.0); - cubeVerts.push(right, bottom, back, 1.0, 1.0); - cubeVerts.push(right, bottom, front, 1.0, 0.0); - cubeVerts.push(left, bottom, front, 0.0, 0.0); - - // Top - idx = cubeVerts.length / 5.0; - cubeIndices.push(idx, idx + 2, idx + 1); - cubeIndices.push(idx, idx + 3, idx + 2); - - cubeVerts.push(left, top, back, 0.0, 0.0); - cubeVerts.push(right, top, back, 1.0, 0.0); - cubeVerts.push(right, top, front, 1.0, 1.0); - cubeVerts.push(left, top, front, 0.0, 1.0); - - // Left - idx = cubeVerts.length / 5.0; - cubeIndices.push(idx, idx + 2, idx + 1); - cubeIndices.push(idx, idx + 3, idx + 2); - - cubeVerts.push(left, bottom, back, 0.0, 1.0); - cubeVerts.push(left, top, back, 0.0, 0.0); - cubeVerts.push(left, top, front, 1.0, 0.0); - cubeVerts.push(left, bottom, front, 1.0, 1.0); - - // Right - idx = cubeVerts.length / 5.0; - cubeIndices.push(idx, idx + 1, idx + 2); - cubeIndices.push(idx, idx + 2, idx + 3); - - cubeVerts.push(right, bottom, back, 1.0, 1.0); - cubeVerts.push(right, top, back, 1.0, 0.0); - cubeVerts.push(right, top, front, 0.0, 0.0); - cubeVerts.push(right, bottom, front, 0.0, 1.0); - - // Back - idx = cubeVerts.length / 5.0; - cubeIndices.push(idx, idx + 2, idx + 1); - cubeIndices.push(idx, idx + 3, idx + 2); - - cubeVerts.push(left, bottom, back, 1.0, 1.0); - cubeVerts.push(right, bottom, back, 0.0, 1.0); - cubeVerts.push(right, top, back, 0.0, 0.0); - cubeVerts.push(left, top, back, 1.0, 0.0); - - // Front - idx = cubeVerts.length / 5.0; - cubeIndices.push(idx, idx + 1, idx + 2); - cubeIndices.push(idx, idx + 2, idx + 3); - - cubeVerts.push(left, bottom, front, 0.0, 1.0); - cubeVerts.push(right, bottom, front, 1.0, 1.0); - cubeVerts.push(right, top, front, 1.0, 0.0); - cubeVerts.push(left, top, front, 0.0, 0.0); - } - - // Appends a cube with the given centerpoint and size. - function appendCube (x, y, z, size) { - var halfSize = size * 0.5; - appendBox(x - halfSize, y - halfSize, z - halfSize, - x + halfSize, y + halfSize, z + halfSize); - } - - // Main "island", covers where the user can safely stand. Top of the cube - // (the ground the user stands on) should be at Y=0 to align with users - // floor. X=0 and Z=0 should be at the center of the users play space. - appendBox(-width * 0.5, -width, -depth * 0.5, width * 0.5, 0, depth * 0.5); - - // A sprinkling of other cubes to make things more visually interesting. - appendCube(1.1, 0.3, (-depth * 0.5) - 0.8, 0.5); - appendCube(-0.5, 1.0, (-depth * 0.5) - 0.9, 0.75); - appendCube(0.6, 1.5, (-depth * 0.5) - 0.6, 0.4); - appendCube(-1.0, 0.5, (-depth * 0.5) - 0.5, 0.2); - - appendCube((-width * 0.5) - 0.8, 0.3, -1.1, 0.5); - appendCube((-width * 0.5) - 0.9, 1.0, 0.5, 0.75); - appendCube((-width * 0.5) - 0.6, 1.5, -0.6, 0.4); - appendCube((-width * 0.5) - 0.5, 0.5, 1.0, 0.2); - - appendCube((width * 0.5) + 0.8, 0.3, 1.1, 0.5); - appendCube((width * 0.5) + 0.9, 1.0, -0.5, 0.75); - appendCube((width * 0.5) + 0.6, 1.5, 0.6, 0.4); - appendCube((width * 0.5) + 0.5, 0.5, -1.0, 0.2); - - appendCube(1.1, 1.4, (depth * 0.5) + 0.8, 0.5); - appendCube(-0.5, 1.0, (depth * 0.5) + 0.9, 0.75); - appendCube(0.6, 0.4, (depth * 0.5) + 0.6, 0.4); - - - gl.bindBuffer(gl.ARRAY_BUFFER, this.vertBuffer); - gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(cubeVerts), gl.STATIC_DRAW); - - gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, this.indexBuffer); - gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, new Uint16Array(cubeIndices), gl.STATIC_DRAW); - - this.indexCount = cubeIndices.length; - }; - - CubeIsland.prototype.render = function (projectionMat, modelViewMat, stats) { - var gl = this.gl; - var program = this.program; - - program.use(); - - gl.uniformMatrix4fv(program.uniform.projectionMat, false, projectionMat); - gl.uniformMatrix4fv(program.uniform.modelViewMat, false, modelViewMat); - - gl.bindBuffer(gl.ARRAY_BUFFER, this.vertBuffer); - gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, this.indexBuffer); - - gl.enableVertexAttribArray(program.attrib.position); - gl.enableVertexAttribArray(program.attrib.texCoord); - - gl.vertexAttribPointer(program.attrib.position, 3, gl.FLOAT, false, 20, 0); - gl.vertexAttribPointer(program.attrib.texCoord, 2, gl.FLOAT, false, 20, 12); - - gl.activeTexture(gl.TEXTURE0); - gl.uniform1i(this.program.uniform.diffuse, 0); - gl.bindTexture(gl.TEXTURE_2D, this.texture); - - gl.drawElements(gl.TRIANGLES, this.indexCount, gl.UNSIGNED_SHORT, 0); - - if (stats) { - // To ensure that the FPS counter is visible in VR mode we have to - // render it as part of the scene. - mat4.fromTranslation(this.statsMat, [0, 1.5, -this.depth * 0.5]); - mat4.scale(this.statsMat, this.statsMat, [0.5, 0.5, 0.5]); - mat4.rotateX(this.statsMat, this.statsMat, -0.75); - mat4.multiply(this.statsMat, modelViewMat, this.statsMat); - stats.render(projectionMat, this.statsMat); - } - }; - - return CubeIsland; -})(); diff --git a/servo/tests/html/webvr/js/vr-cube-sea.js b/servo/tests/html/webvr/js/vr-cube-sea.js deleted file mode 100644 index 5002e1816396..000000000000 --- a/servo/tests/html/webvr/js/vr-cube-sea.js +++ /dev/null @@ -1,188 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -/* global mat4, WGLUProgram */ - -window.VRCubeSea = (function () { - "use strict"; - - var cubeSeaVS = [ - "uniform mat4 projectionMat;", - "uniform mat4 modelViewMat;", - "attribute vec3 position;", - "attribute vec2 texCoord;", - "varying vec2 vTexCoord;", - - "void main() {", - " vTexCoord = texCoord;", - " gl_Position = projectionMat * modelViewMat * vec4( position, 1.0 );", - "}", - ].join("\n"); - - var cubeSeaFS = [ - "precision mediump float;", - "uniform sampler2D diffuse;", - "varying vec2 vTexCoord;", - - "void main() {", - " gl_FragColor = texture2D(diffuse, vTexCoord);", - "}", - ].join("\n"); - - var CubeSea = function (gl, texture) { - this.gl = gl; - - this.statsMat = mat4.create(); - - this.texture = texture; - - this.program = new WGLUProgram(gl); - this.program.attachShaderSource(cubeSeaVS, gl.VERTEX_SHADER); - this.program.attachShaderSource(cubeSeaFS, gl.FRAGMENT_SHADER); - this.program.bindAttribLocation({ - position: 0, - texCoord: 1 - }); - this.program.link(); - - var cubeVerts = []; - var cubeIndices = []; - - // Build a single cube. - function appendCube (x, y, z) { - if (!x && !y && !z) { - // Don't create a cube in the center. - return; - } - - var size = 0.2; - // Bottom - var idx = cubeVerts.length / 5.0; - cubeIndices.push(idx, idx + 1, idx + 2); - cubeIndices.push(idx, idx + 2, idx + 3); - - cubeVerts.push(x - size, y - size, z - size, 0.0, 1.0); - cubeVerts.push(x + size, y - size, z - size, 1.0, 1.0); - cubeVerts.push(x + size, y - size, z + size, 1.0, 0.0); - cubeVerts.push(x - size, y - size, z + size, 0.0, 0.0); - - // Top - idx = cubeVerts.length / 5.0; - cubeIndices.push(idx, idx + 2, idx + 1); - cubeIndices.push(idx, idx + 3, idx + 2); - - cubeVerts.push(x - size, y + size, z - size, 0.0, 0.0); - cubeVerts.push(x + size, y + size, z - size, 1.0, 0.0); - cubeVerts.push(x + size, y + size, z + size, 1.0, 1.0); - cubeVerts.push(x - size, y + size, z + size, 0.0, 1.0); - - // Left - idx = cubeVerts.length / 5.0; - cubeIndices.push(idx, idx + 2, idx + 1); - cubeIndices.push(idx, idx + 3, idx + 2); - - cubeVerts.push(x - size, y - size, z - size, 0.0, 1.0); - cubeVerts.push(x - size, y + size, z - size, 0.0, 0.0); - cubeVerts.push(x - size, y + size, z + size, 1.0, 0.0); - cubeVerts.push(x - size, y - size, z + size, 1.0, 1.0); - - // Right - idx = cubeVerts.length / 5.0; - cubeIndices.push(idx, idx + 1, idx + 2); - cubeIndices.push(idx, idx + 2, idx + 3); - - cubeVerts.push(x + size, y - size, z - size, 1.0, 1.0); - cubeVerts.push(x + size, y + size, z - size, 1.0, 0.0); - cubeVerts.push(x + size, y + size, z + size, 0.0, 0.0); - cubeVerts.push(x + size, y - size, z + size, 0.0, 1.0); - - // Back - idx = cubeVerts.length / 5.0; - cubeIndices.push(idx, idx + 2, idx + 1); - cubeIndices.push(idx, idx + 3, idx + 2); - - cubeVerts.push(x - size, y - size, z - size, 1.0, 1.0); - cubeVerts.push(x + size, y - size, z - size, 0.0, 1.0); - cubeVerts.push(x + size, y + size, z - size, 0.0, 0.0); - cubeVerts.push(x - size, y + size, z - size, 1.0, 0.0); - - // Front - idx = cubeVerts.length / 5.0; - cubeIndices.push(idx, idx + 1, idx + 2); - cubeIndices.push(idx, idx + 2, idx + 3); - - cubeVerts.push(x - size, y - size, z + size, 0.0, 1.0); - cubeVerts.push(x + size, y - size, z + size, 1.0, 1.0); - cubeVerts.push(x + size, y + size, z + size, 1.0, 0.0); - cubeVerts.push(x - size, y + size, z + size, 0.0, 0.0); - } - - var gridSize = 10; - - // Build the cube sea - for (var x = 0; x < gridSize; ++x) { - for (var y = 0; y < gridSize; ++y) { - for (var z = 0; z < gridSize; ++z) { - appendCube(x - (gridSize / 2), y - (gridSize / 2), z - (gridSize / 2)); - } - } - } - - this.vertBuffer = gl.createBuffer(); - gl.bindBuffer(gl.ARRAY_BUFFER, this.vertBuffer); - gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(cubeVerts), gl.STATIC_DRAW); - - this.indexBuffer = gl.createBuffer(); - gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, this.indexBuffer); - gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, new Uint16Array(cubeIndices), gl.STATIC_DRAW); - - this.indexCount = cubeIndices.length; - }; - - var mortimer = mat4.create(); - - var a = [0.9868122935295105, -0.03754837438464165, -0.15745431184768677, 0, 0.011360996402800083, 0.9863911271095276, -0.1640235036611557, 0, 0.16147033870220184, 0.16007155179977417, 0.9738093614578247, 0, 0.192538782954216, 0.024526841938495636, -0.001076754298992455, 1.0000001192092896]; - for (var i = 0; i < 16; ++i) { - mortimer[i] = a[i]; - } - - CubeSea.prototype.render = function (projectionMat, modelViewMat, stats) { - var gl = this.gl; - var program = this.program; - - //mat4.invert(mortimer, modelViewMat); - - program.use(); - - gl.uniformMatrix4fv(program.uniform.projectionMat, false, projectionMat); - gl.uniformMatrix4fv(program.uniform.modelViewMat, false, modelViewMat); - - gl.bindBuffer(gl.ARRAY_BUFFER, this.vertBuffer); - gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, this.indexBuffer); - - gl.enableVertexAttribArray(program.attrib.position); - gl.enableVertexAttribArray(program.attrib.texCoord); - - gl.vertexAttribPointer(program.attrib.position, 3, gl.FLOAT, false, 20, 0); - gl.vertexAttribPointer(program.attrib.texCoord, 2, gl.FLOAT, false, 20, 12); - - gl.activeTexture(gl.TEXTURE0); - gl.uniform1i(this.program.uniform.diffuse, 0); - gl.bindTexture(gl.TEXTURE_2D, this.texture); - - gl.drawElements(gl.TRIANGLES, this.indexCount, gl.UNSIGNED_SHORT, 0); - - if (stats) { - // To ensure that the FPS counter is visible in VR mode we have to - // render it as part of the scene. - mat4.fromTranslation(this.statsMat, [0, -0.3, -0.5]); - mat4.scale(this.statsMat, this.statsMat, [0.3, 0.3, 0.3]); - mat4.rotateX(this.statsMat, this.statsMat, -0.75); - mat4.multiply(this.statsMat, modelViewMat, this.statsMat); - stats.render(projectionMat, this.statsMat); - } - }; - - return CubeSea; -})(); diff --git a/servo/tests/html/webvr/js/vr-panorama.js b/servo/tests/html/webvr/js/vr-panorama.js deleted file mode 100644 index 8eac81e9f05e..000000000000 --- a/servo/tests/html/webvr/js/vr-panorama.js +++ /dev/null @@ -1,219 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -/* global mat4, WGLUProgram */ - -window.VRPanorama = (function () { - "use strict"; - - var panoVS = [ - "uniform mat4 projectionMat;", - "uniform mat4 modelViewMat;", - "attribute vec3 position;", - "attribute vec2 texCoord;", - "varying vec2 vTexCoord;", - - "void main() {", - " vTexCoord = texCoord;", - " gl_Position = projectionMat * modelViewMat * vec4( position, 1.0 );", - "}", - ].join("\n"); - - var panoFS = [ - "precision mediump float;", - "uniform sampler2D diffuse;", - "varying vec2 vTexCoord;", - - "void main() {", - " gl_FragColor = texture2D(diffuse, vTexCoord);", - "}", - ].join("\n"); - - var Panorama = function (gl) { - this.gl = gl; - - this.texture = gl.createTexture(); - - this.program = new WGLUProgram(gl); - this.program.attachShaderSource(panoVS, gl.VERTEX_SHADER); - this.program.attachShaderSource(panoFS, gl.FRAGMENT_SHADER); - this.program.bindAttribLocation({ - position: 0, - texCoord: 1 - }); - this.program.link(); - - var panoVerts = []; - var panoIndices = []; - - var radius = 2; // 2 meter radius sphere - var latSegments = 40; - var lonSegments = 40; - - // Create the vertices - for (var i=0; i <= latSegments; ++i) { - var theta = i * Math.PI / latSegments; - var sinTheta = Math.sin(theta); - var cosTheta = Math.cos(theta); - - for (var j=0; j <= lonSegments; ++j) { - var phi = j * 2 * Math.PI / lonSegments; - var sinPhi = Math.sin(phi); - var cosPhi = Math.cos(phi); - - var x = sinPhi * sinTheta; - var y = cosTheta; - var z = -cosPhi * sinTheta; - var u = (j / lonSegments); - var v = (i / latSegments); - - panoVerts.push(x * radius, y * radius, z * radius, u, v); - } - } - - // Create the indices - for (var i = 0; i < latSegments; ++i) { - var offset0 = i * (lonSegments+1); - var offset1 = (i+1) * (lonSegments+1); - for (var j = 0; j < lonSegments; ++j) { - var index0 = offset0+j; - var index1 = offset1+j; - panoIndices.push( - index0, index1, index0+1, - index1, index1+1, index0+1 - ); - } - } - - this.vertBuffer = gl.createBuffer(); - gl.bindBuffer(gl.ARRAY_BUFFER, this.vertBuffer); - gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(panoVerts), gl.STATIC_DRAW); - - this.indexBuffer = gl.createBuffer(); - gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, this.indexBuffer); - gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, new Uint16Array(panoIndices), gl.STATIC_DRAW); - - this.indexCount = panoIndices.length; - - this.imgElement = null; - this.videoElement = null; - }; - - Panorama.prototype.setImage = function (url) { - var gl = this.gl; - var self = this; - - return new Promise(function(resolve, reject) { - var img = new Image(); - img.addEventListener('load', function() { - self.imgElement = img; - self.videoElement = null; - - gl.bindTexture(gl.TEXTURE_2D, self.texture); - gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGB, gl.RGB, gl.UNSIGNED_BYTE, img); - - gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR); - gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR); - gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE); - gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE); - - resolve(self.imgElement); - }); - img.addEventListener('error', function(ev) { - console.error(ev.message); - reject(ev.message); - }, false); - img.crossOrigin = 'anonymous'; - img.src = url; - }); - }; - - Panorama.prototype.setVideo = function (url) { - var gl = this.gl; - var self = this; - - return new Promise(function(resolve, reject) { - var video = document.createElement('video'); - video.addEventListener('canplay', function() { - // Added "click to play" UI? - }); - - video.addEventListener('playing', function() { - self.videoElement = video; - self.imgElement = null; - - gl.bindTexture(gl.TEXTURE_2D, self.texture); - gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGB, gl.RGB, gl.UNSIGNED_BYTE, self.videoElement); - - gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR); - gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR); - gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE); - gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE); - - resolve(self.videoElement); - }); - - video.addEventListener('error', function(ev) { - console.error(video.error); - reject(video.error); - }, false); - - video.loop = true; - video.autoplay = true; - video.crossOrigin = 'anonymous'; - video.setAttribute('webkit-playsinline', ''); - video.src = url; - }); - }; - - Panorama.prototype.play = function() { - if (this.videoElement) - this.videoElement.play(); - }; - - Panorama.prototype.pause = function() { - if (this.videoElement) - this.videoElement.pause(); - }; - - Panorama.prototype.isPaused = function() { - if (this.videoElement) - return this.videoElement.paused; - return false; - }; - - Panorama.prototype.render = function (projectionMat, modelViewMat) { - var gl = this.gl; - var program = this.program; - - if (!this.imgElement && !this.videoElement) - return; - - program.use(); - - gl.uniformMatrix4fv(program.uniform.projectionMat, false, projectionMat); - gl.uniformMatrix4fv(program.uniform.modelViewMat, false, modelViewMat); - - gl.bindBuffer(gl.ARRAY_BUFFER, this.vertBuffer); - gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, this.indexBuffer); - - gl.enableVertexAttribArray(program.attrib.position); - gl.enableVertexAttribArray(program.attrib.texCoord); - - gl.vertexAttribPointer(program.attrib.position, 3, gl.FLOAT, false, 20, 0); - gl.vertexAttribPointer(program.attrib.texCoord, 2, gl.FLOAT, false, 20, 12); - - gl.activeTexture(gl.TEXTURE0); - gl.uniform1i(this.program.uniform.diffuse, 0); - gl.bindTexture(gl.TEXTURE_2D, this.texture); - - if (this.videoElement && !this.videoElement.paused) { - gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGB, gl.RGB, gl.UNSIGNED_BYTE, this.videoElement); - } - - gl.drawElements(gl.TRIANGLES, this.indexCount, gl.UNSIGNED_SHORT, 0); - }; - - return Panorama; -})(); diff --git a/servo/tests/html/webvr/js/vr-samples-util.js b/servo/tests/html/webvr/js/vr-samples-util.js deleted file mode 100644 index 20553bdf8702..000000000000 --- a/servo/tests/html/webvr/js/vr-samples-util.js +++ /dev/null @@ -1,181 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -window.VRSamplesUtil = (function () { - - "use strict"; - - // Lifted from the WebVR Polyfill - function isMobile () { - return /Android/i.test(navigator.userAgent) || - /iPhone|iPad|iPod/i.test(navigator.userAgent); - } - - function getMessageContainer () { - var messageContainer = document.getElementById("vr-sample-message-container"); - if (!messageContainer) { - messageContainer = document.createElement("div"); - messageContainer.id = "vr-sample-message-container"; - messageContainer.style.fontFamily = "sans-serif"; - messageContainer.style.position = "absolute"; - messageContainer.style.zIndex = "999"; - messageContainer.style.left = "0"; - messageContainer.style.top = "0"; - messageContainer.style.right = "0"; - messageContainer.style.margin = "0"; - messageContainer.style.padding = "0"; - messageContainer.align = "center"; - document.body.appendChild(messageContainer); - } - return messageContainer; - } - - function addMessageElement (message, backgroundColor) { - var messageElement = document.createElement("div"); - messageElement.classList.add = "vr-sample-message"; - messageElement.style.color = "#FFF"; - messageElement.style.backgroundColor = backgroundColor; - messageElement.style.borderRadius = "3px"; - messageElement.style.position = "relative"; - messageElement.style.display = "inline-block"; - messageElement.style.margin = "0.5em"; - messageElement.style.padding = "0.75em"; - - messageElement.innerHTML = message; - - getMessageContainer().appendChild(messageElement); - - return messageElement; - } - - // Makes the given element fade out and remove itself from the DOM after the - // given timeout. - function makeToast (element, timeout) { - element.style.transition = "opacity 0.5s ease-in-out"; - element.style.opacity = "1"; - setTimeout(function () { - element.style.opacity = "0"; - setTimeout(function () { - if (element.parentElement) - element.parentElement.removeChild(element); - }, 500); - }, timeout); - } - - function addError (message, timeout) { - var element = addMessageElement("ERROR: " + message, "#D33"); - - if (timeout) { - makeToast(element, timeout); - } - - return element; - } - - function addInfo (message, timeout) { - var element = addMessageElement(message, "#22A"); - - if (timeout) { - makeToast(element, timeout); - } - - return element; - } - - function getButtonContainer () { - var buttonContainer = document.getElementById("vr-sample-button-container"); - if (!buttonContainer) { - buttonContainer = document.createElement("div"); - buttonContainer.id = "vr-sample-button-container"; - buttonContainer.style.fontFamily = "sans-serif"; - buttonContainer.style.position = "absolute"; - buttonContainer.style.zIndex = "999"; - buttonContainer.style.left = "0"; - buttonContainer.style.bottom = "0"; - buttonContainer.style.right = "0"; - buttonContainer.style.margin = "0"; - buttonContainer.style.padding = "0"; - buttonContainer.align = "right"; - document.body.appendChild(buttonContainer); - } - return buttonContainer; - } - - function addButtonElement (message, key, icon) { - var buttonElement = document.createElement("div"); - buttonElement.classList.add = "vr-sample-button"; - buttonElement.style.color = "#FFF"; - buttonElement.style.fontWeight = "bold"; - buttonElement.style.backgroundColor = "#888"; - buttonElement.style.borderRadius = "5px"; - buttonElement.style.border = "3px solid #555"; - buttonElement.style.position = "relative"; - buttonElement.style.display = "inline-block"; - buttonElement.style.margin = "0.5em"; - buttonElement.style.padding = "0.75em"; - buttonElement.style.cursor = "pointer"; - buttonElement.align = "center"; - - if (icon) { - buttonElement.innerHTML = "
" + message; - } else { - buttonElement.innerHTML = message; - } - - if (key) { - var keyElement = document.createElement("span"); - keyElement.classList.add = "vr-sample-button-accelerator"; - keyElement.style.fontSize = "0.75em"; - keyElement.style.fontStyle = "italic"; - keyElement.innerHTML = " (" + key + ")"; - - buttonElement.appendChild(keyElement); - } - - getButtonContainer().appendChild(buttonElement); - - return buttonElement; - } - - function addButton (message, key, icon, callback) { - var keyListener = null; - if (key) { - var keyCode = key.charCodeAt(0); - keyListener = function (event) { - if (event.keyCode === keyCode) { - callback(event); - } - }; - document.addEventListener("keydown", keyListener, false); - } - var element = addButtonElement(message, key, icon); - element.addEventListener("click", function (event) { - callback(event); - event.preventDefault(); - }, false); - - return { - element: element, - keyListener: keyListener - }; - } - - function removeButton (button) { - if (!button) - return; - if (button.element.parentElement) - button.element.parentElement.removeChild(button.element); - if (button.keyListener) - document.removeEventListener("keydown", button.keyListener, false); - } - - return { - isMobile: isMobile, - addError: addError, - addInfo: addInfo, - addButton: addButton, - removeButton: removeButton, - makeToast: makeToast - }; -})(); diff --git a/servo/tests/html/webvr/media/icons/cardboard64.png b/servo/tests/html/webvr/media/icons/cardboard64.png deleted file mode 100644 index 9457f7d53ed0..000000000000 Binary files a/servo/tests/html/webvr/media/icons/cardboard64.png and /dev/null differ diff --git a/servo/tests/html/webvr/media/textures/cube-sea.png b/servo/tests/html/webvr/media/textures/cube-sea.png deleted file mode 100644 index 356bc3369d31..000000000000 Binary files a/servo/tests/html/webvr/media/textures/cube-sea.png and /dev/null differ diff --git a/servo/tests/html/webvr/room-scale.html b/servo/tests/html/webvr/room-scale.html deleted file mode 100644 index fcd35de041c2..000000000000 --- a/servo/tests/html/webvr/room-scale.html +++ /dev/null @@ -1,312 +0,0 @@ - - - - - - - - - - 05 - Room Scale - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/servo/tests/html/webvr/simple-mirroring.html b/servo/tests/html/webvr/simple-mirroring.html deleted file mode 100644 index 6578ae49ea4a..000000000000 --- a/servo/tests/html/webvr/simple-mirroring.html +++ /dev/null @@ -1,262 +0,0 @@ - - - - - - - - - - 04 - Simple Mirroring - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/servo/tests/html/webvr/vr-controllers.html b/servo/tests/html/webvr/vr-controllers.html deleted file mode 100644 index 797b4198fdc9..000000000000 --- a/servo/tests/html/webvr/vr-controllers.html +++ /dev/null @@ -1,419 +0,0 @@ - - - - - - - - - - - - - XX - VR Controllers - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/servo/tests/html/webvr/vr-presentation.html b/servo/tests/html/webvr/vr-presentation.html deleted file mode 100644 index 98adc9dd1957..000000000000 --- a/servo/tests/html/webvr/vr-presentation.html +++ /dev/null @@ -1,307 +0,0 @@ - - - - - - - - - - 03 - VR Presentation - - - - - - - - - - - - - - - - - - - - - - - -
Put on your headset now
- - - diff --git a/servo/tests/html/work.js b/servo/tests/html/work.js deleted file mode 100644 index 8fef1f11654d..000000000000 --- a/servo/tests/html/work.js +++ /dev/null @@ -1,4 +0,0 @@ -console.log("reached inside work.js file"); -setInterval(function() { - console.log('hi'); -}, 500); diff --git a/servo/tests/html/worker/worker_post_block.js b/servo/tests/html/worker/worker_post_block.js deleted file mode 100644 index a9837b71afdf..000000000000 --- a/servo/tests/html/worker/worker_post_block.js +++ /dev/null @@ -1,9 +0,0 @@ -var prev = Date.now() -for (var i=0; true; i++) { - - if (i % 100000000 == 0) { - var now = Date.now(); - postMessage(now - prev); - prev = now; - } -} diff --git a/servo/tests/html/worker/worker_post_interval.js b/servo/tests/html/worker/worker_post_interval.js deleted file mode 100644 index ce1126136fa1..000000000000 --- a/servo/tests/html/worker/worker_post_interval.js +++ /dev/null @@ -1,6 +0,0 @@ -var prev = Date.now() -setInterval(function () { - var now = Date.now(); - postMessage(now - prev); - prev = now; -}, 500); diff --git a/servo/tests/html/worker/worker_terminate.html b/servo/tests/html/worker/worker_terminate.html deleted file mode 100644 index d6c40a5c69d2..000000000000 --- a/servo/tests/html/worker/worker_terminate.html +++ /dev/null @@ -1,48 +0,0 @@ - - - - - Worker Test - - - - - - - diff --git a/servo/tests/jquery/.gitignore b/servo/tests/jquery/.gitignore deleted file mode 100644 index fc1787458a2a..000000000000 --- a/servo/tests/jquery/.gitignore +++ /dev/null @@ -1 +0,0 @@ -jquery/ diff --git a/servo/tests/jquery/expected_selector.txt b/servo/tests/jquery/expected_selector.txt deleted file mode 100644 index 434a4d80ea47..000000000000 --- a/servo/tests/jquery/expected_selector.txt +++ /dev/null @@ -1,14 +0,0 @@ -[jQuery test] [15/0/15] jQuery.uniqueSort -[jQuery test] [0/1/1] Iframe dispatch should not affect jQuery (#13936) -[jQuery test] [4/0/4] class - jQuery only -[jQuery test] [0/2/2] attributes - jQuery.attr -[jQuery test] [5/0/5] name -[jQuery test] [4/0/4] selectors with comma -[jQuery test] [16/0/16] jQuery.contains -[jQuery test] [27/0/27] child and adjacent -[jQuery test] [7/0/7] element - jQuery only -[jQuery test] [0/2/2] Sizzle cache collides with multiple Sizzles on a page -[jQuery test] [1/0/1] disconnected nodes -[jQuery test] [54/0/54] attributes -[jQuery test] [3/0/3] disconnected nodes - jQuery only -[jQuery test] [26/0/26] id diff --git a/servo/tests/jquery/run_jquery.py b/servo/tests/jquery/run_jquery.py deleted file mode 100755 index d3a3d3e97b8c..000000000000 --- a/servo/tests/jquery/run_jquery.py +++ /dev/null @@ -1,268 +0,0 @@ -#!/usr/bin/env python - -# This Source Code Form is subject to the terms of the Mozilla Public -# License, v. 2.0. If a copy of the MPL was not distributed with this -# file, You can obtain one at http://mozilla.org/MPL/2.0/. - -import os -import re -import subprocess -import sys -import BaseHTTPServer -import SimpleHTTPServer -import SocketServer -import threading -import urlparse - -# List of jQuery modules that will be tested. -# TODO(gw): Disabled most of them as something has been -# introduced very recently that causes the resource task -# to panic - and hard fail doesn't exit the servo -# process when this happens. -# See https://github.com/servo/servo/issues/6210 and -# https://github.com/servo/servo/issues/6211 -JQUERY_MODULES = [ - # "ajax", # panics - # "attributes", - # "callbacks", - # "core", # mozjs crash - # "css", - # "data", - # "deferred", - # "dimensions", - # "effects", - # "event", # panics - # "manipulation", # mozjs crash - # "offset", - # "queue", - "selector", - # "serialize", - # "support", - # "traversing", - # "wrap" -] - -# Port to run the HTTP server on for jQuery. -TEST_SERVER_PORT = 8192 - -# A regex for matching console.log output lines from the test runner. -REGEX_PATTERN = "^\[jQuery test\] \[([0-9]+)/([0-9]+)/([0-9]+)] (.*)" - - -# The result of a single test group. -class TestResult: - def __init__(self, success, fail, total, text): - self.success = int(success) - self.fail = int(fail) - self.total = int(total) - self.text = text - - def __key(self): - return (self.success, self.fail, self.total, self.text) - - def __eq__(self, other): - return self.__key() == other.__key() - - def __ne__(self, other): - return self.__key() != other.__key() - - def __hash__(self): - return hash(self.__key()) - - def __repr__(self): - return "ok={0} fail={1} total={2}".format(self.success, self.fail, self.total) - - -# Parse a line, producing a TestResult. -# Throws if unable to parse. -def parse_line_to_result(line): - match = re.match(REGEX_PATTERN, line) - success, fail, total, name = match.groups() - return name, TestResult(success, fail, total, line) - - -# Parse an entire buffer of lines to a dictionary -# of test results, keyed by the test name. -def parse_string_to_results(buffer): - test_results = {} - lines = buffer.splitlines() - for line in lines: - name, test_result = parse_line_to_result(line) - test_results[name] = test_result - return test_results - - -# Run servo and print / parse the results for a specific jQuery test module. -def run_servo(servo_exe, module): - url = "http://localhost:{0}/jquery/test/?module={1}".format(TEST_SERVER_PORT, module) - args = [servo_exe, url, "-z", "-f"] - proc = subprocess.Popen(args, stdout=subprocess.PIPE) - while True: - line = proc.stdout.readline() - if len(line) == 0: - break - line = line.rstrip() - try: - name, test_result = parse_line_to_result(line) - yield name, test_result - except AttributeError: - pass - - -# Build the filename for an expected results file. -def module_filename(module): - return 'expected_{0}.txt'.format(module) - - -# Read an existing set of expected results to compare against. -def read_existing_results(module): - with open(module_filename(module), 'r') as file: - buffer = file.read() - return parse_string_to_results(buffer) - - -# Write a set of results to file -def write_results(module, results): - with open(module_filename(module), 'w') as file: - for result in test_results.itervalues(): - file.write(result.text + '\n') - - -# Print usage if command line args are incorrect -def print_usage(): - print("USAGE: {0} test|update servo_binary jquery_base_dir".format(sys.argv[0])) - - -# Run a simple HTTP server to serve up the jQuery test suite -def run_http_server(): - class ThreadingSimpleServer(SocketServer.ThreadingMixIn, - BaseHTTPServer.HTTPServer): - allow_reuse_address = True - - class RequestHandler(SimpleHTTPServer.SimpleHTTPRequestHandler): - # TODO(gw): HACK copy the fixed version from python - # main repo - due to https://bugs.python.org/issue23112 - def send_head(self): - path = self.translate_path(self.path) - f = None - if os.path.isdir(path): - parts = urlparse.urlsplit(self.path) - if not parts.path.endswith('/'): - # redirect browser - doing basically what apache does - self.send_response(301) - new_parts = (parts[0], parts[1], parts[2] + '/', - parts[3], parts[4]) - new_url = urlparse.urlunsplit(new_parts) - self.send_header("Location", new_url) - self.end_headers() - return None - for index in "index.html", "index.htm": - index = os.path.join(path, index) - if os.path.exists(index): - path = index - break - else: - return self.list_directory(path) - ctype = self.guess_type(path) - try: - # Always read in binary mode. Opening files in text mode may cause - # newline translations, making the actual size of the content - # transmitted *less* than the content-length! - f = open(path, 'rb') - except IOError: - self.send_error(404, "File not found") - return None - try: - self.send_response(200) - self.send_header("Content-type", ctype) - fs = os.fstat(f.fileno()) - self.send_header("Content-Length", str(fs[6])) - self.send_header("Last-Modified", self.date_time_string(fs.st_mtime)) - self.end_headers() - return f - except: - f.close() - raise - - def log_message(self, format, *args): - return - - server = ThreadingSimpleServer(('', TEST_SERVER_PORT), RequestHandler) - while True: - sys.stdout.flush() - server.handle_request() - -if __name__ == '__main__': - if len(sys.argv) == 4: - cmd = sys.argv[1] - servo_exe = sys.argv[2] - base_dir = sys.argv[3] - os.chdir(base_dir) - - # Ensure servo binary can be found - if not os.path.isfile(servo_exe): - print("Unable to find {0}. This script expects an existing build of Servo.".format(servo_exe)) - sys.exit(1) - - # Start the test server - httpd_thread = threading.Thread(target=run_http_server) - httpd_thread.setDaemon(True) - httpd_thread.start() - - if cmd == "test": - print("Testing jQuery on Servo!") - test_count = 0 - unexpected_count = 0 - - individual_success = 0 - individual_total = 0 - - # Test each module separately - for module in JQUERY_MODULES: - print("\t{0}".format(module)) - - prev_test_results = read_existing_results(module) - for name, current_result in run_servo(servo_exe, module): - test_count += 1 - individual_success += current_result.success - individual_total += current_result.total - - # If this test was in the previous results, compare them. - if name in prev_test_results: - prev_result = prev_test_results[name] - if prev_result == current_result: - print("\t\tOK: {0}".format(name)) - else: - unexpected_count += 1 - print("\t\tFAIL: {0}: WAS {1} NOW {2}".format(name, prev_result, current_result)) - del prev_test_results[name] - else: - # There was a new test that wasn't expected - unexpected_count += 1 - print("\t\tNEW: {0}".format(current_result.text)) - - # Check what's left over, these are tests that were expected but didn't run this time. - for name in prev_test_results: - test_count += 1 - unexpected_count += 1 - print("\t\tMISSING: {0}".format(prev_test_results[name].text)) - - print("\tRan {0} test groups. {1} unexpected results.".format(test_count, unexpected_count)) - print("\t{0} tests succeeded of {1} ({2:.2f}%)".format(individual_success, - individual_total, - 100.0 * individual_success / individual_total)) - if unexpected_count > 0: - sys.exit(1) - elif cmd == "update": - print("Updating jQuery expected results") - for module in JQUERY_MODULES: - print("\t{0}".format(module)) - test_results = {} - for name, test_result in run_servo(servo_exe, module): - print("\t\t{0} {1}".format(name, test_result)) - test_results[name] = test_result - write_results(module, test_results) - else: - print_usage() - else: - print_usage() diff --git a/servo/tests/power/PowerMeasure.py b/servo/tests/power/PowerMeasure.py deleted file mode 100755 index 2eefb0097631..000000000000 --- a/servo/tests/power/PowerMeasure.py +++ /dev/null @@ -1,184 +0,0 @@ -#!/usr/bin/env python - -# This Source Code Form is subject to the terms of the Mozilla Public -# License, v. 2.0. If a copy of the MPL was not distributed with this -# file, You can obtain one at http://mozilla.org/MPL/2.0/. - - -# ---------Power measurement ------------------------------# -# This script will run the servo with the given benchmark and -# get the power usage using Powermetrics. Results will be put -# in sperate files with that name. -# Do not forget to run the script in servo/tests/power folder -# --------------------------------------------------------# - -from __future__ import print_function, unicode_literals - -import os -from os import path -import time -import argparse - -# ------------------------PowerCollector----------------------------# -# Collecting all the power data and put them into files - - -TOP_DIR = path.join("..", "..") - - -def PowerCollector(OutputDir, Benchmarks, LayoutThreads, Renderer): - print("Running the power collector") - power_dir = path.join(OutputDir, "power") - time_dir = path.join(OutputDir, "time") - etc_dir = path.join(OutputDir, "etc") - for d in [power_dir, time_dir, etc_dir]: - os.mkdir(d) - SleepTime = 20 - GuardTime = 0.5 - powerTiming = 1 - ExperimentNum = 21 - for ExpNum in range(1, ExperimentNum): - for layoutT in range(1, LayoutThreads + 1): - print(" layoutT=%d ExpNum=%d" % (layoutT, ExpNum)) - PowerFiles = path.join( - power_dir, "power-Layout%d-set%d.csv" % (layoutT, ExpNum)) - TimeFiles = path.join( - time_dir, "time-Layout%d-set%d.csv" % (layoutT, ExpNum)) - ServoCmd = "(time ../../target/release/servo -x -y %d %s %s) 2> %s" % \ - (layoutT, Renderer, Benchmarks, TimeFiles) - Metrics = path.join( - etc_dir, "metrics-Layout%d-set%d-css.csv" % (layoutT, ExpNum)) - cmd = "(sudo powermetrics -i %d | " \ - "grep \"energy\\|elapsed\\|servo\" > %s &_) 2> %s" % \ - (powerTiming, PowerFiles, Metrics) - time.sleep(SleepTime) - os.system(cmd) - time.sleep(GuardTime) - os.system(ServoCmd) - time.sleep(GuardTime) - os.system('sudo pkill -9 powermetrics') - time.sleep(SleepTime) - -# -------------------PowerParser ---------------------------------# -# Parsing collected power by PowerCollector fucntion - - -def PowerParser(OutputDir, LayoutThreads): - print("Running the PowerParser") - ExperimentNum = 21 - ResultTable = OutputDir + "ResultTable.csv" - ResultFile = open(ResultTable, "w") - ResultFile.write("LayoutThreads, MeanPower, MaxPower , MinPower, MeanTime , MaxTime, " - "MinTime \n") - - for layoutT in range(1, LayoutThreads + 1): - MaxTime = 0 - MinTime = 1000000 - MaxPower = 0 - MinPower = 1000000 - TotalPower = 0 - TotalTime = 0 - TimeGen = 0 - PowerGen = 0 - for ExpNum in range(1, ExperimentNum): - print(" layoutT=%d ExpNum=%d" % (layoutT, ExpNum)) - Files = path.join( - OutputDir, "power", "power-Layout%d-set%d.csv" % - (layoutT, ExpNum)) - NewFile = path.join(OutputDir, "power", "Servo-Layout%d-set%d.csv" % - (layoutT, ExpNum)) - File = open(Files, 'r') - PowerFile = open(NewFile, 'w') - TimeFiles = path.join(OutputDir, "time", "time-Layout%d-set%d.csv" % - (layoutT, ExpNum)) - # ----Putting the power the power and its time into a table---- # - - for line in File: - words = line.split() - if words[0] == "***": - insertingWord = words[10][1:-2] + " " - elif words[0] == "Intel": - insertingWord += words[7][:-1] - insertingWord += "\n" - PowerFile.write(insertingWord) - File.close() - PowerFile.close() - - # ---------------geting the total power of experiments-------- # - - TempFile = open(NewFile, 'r') - Power = 0 - for line in TempFile: - words2 = line.split() - Power += float(words2[0]) * float(words2[1]) - TotalPower = float(Power / 1000.0) - if TotalPower > MaxPower: - MaxPower = TotalPower - if TotalPower < MinPower: - MinPower = TotalPower - - # -------------getting the total time of execution---------- # - - TempFile2 = open(TimeFiles, "r") - for line in TempFile2: - words3 = line.split() - if line != "\n" and words3[0] == "real": - TotalTime = (float(words3[1][0]) * 60) + \ - float(words3[1][2:-1]) - if TotalTime > MaxTime: - MaxTime = TotalTime - if TotalTime < MinTime: - MinTime = TotalTime - TimeGen = TimeGen + TotalTime - PowerGen = PowerGen + TotalPower - - TotalPower = PowerGen / float(ExperimentNum - 1) - TotalTime = TimeGen / float(ExperimentNum - 1) - ResultFile.write(str(layoutT) + " , " + str(TotalPower) + " , " + - str(MaxPower) + " , " + str(MinPower) + " , " + - str(TotalTime) + " , " + str(MaxTime) + " , " + - str(MinTime) + "\n") - ResultFile.close() - Opener = ResultFile = open(ResultTable, "r") - for line in Opener: - print(line) - - print("Also you can find all the numbers for Power " - "and Performance in : ", ResultTable) - - -# ----------------------------------------------------# -def main(): - LayoutThreads = 8 # Maximum number of threads considered for Layout - Benchmarks = path.join(TOP_DIR, "tests", "html", "perf-rainbow.html") - OutputDir = "Experiments" - os.mkdir(OutputDir) - Renderer = "" - - # Parsing the input of the script - parser = argparse.ArgumentParser(description="Measuring \ - power and performance of your Servo runs") - parser.add_argument("-b", "--benchmark", help="Gets the \ - benchmark, for example \"-B perf-rainbow.html\"") - parser.add_argument("-c", "--CPU", help="Rendering with \ - CPU instead of GPU, for example -C") - parser.add_argument("-l", "--LayoutThreads", help="Specify \ - the maximum number of threads for layout, for example \" -L 5\"") - parser.add_argument("-o", "--Output", help="Specify \ - the output directory") - - args = parser.parse_args() - if args.benchmark: - Benchmarks = args.benchmark - if args.CPU: - Renderer = "-c" - if args.LayoutThreads: - LayoutThreads = int(args.LayoutThreads) - if args.Output: - OutputDir = args.Output - - PowerCollector(OutputDir, Benchmarks, LayoutThreads, Renderer) - PowerParser(OutputDir, LayoutThreads) - -if __name__ == "__main__": - main() diff --git a/servo/tests/power/README.md b/servo/tests/power/README.md deleted file mode 100644 index 9077205dbf6f..000000000000 --- a/servo/tests/power/README.md +++ /dev/null @@ -1,24 +0,0 @@ -The power and performance measurement for Servo parallel browser - -This script uses PowerMetrics to measure power usage of Servo on OS X - -## Running - -``` sh -cd servo/tests/power -sudo python PowerMeasure.py -``` -You can define the maximum number of threads in layout level, rendering by cpu, benchmarks and output directory with these command line arguments: - -- `-b BENCHMARK, --benchmark BENCHMARK` sets the benchmark, for example '-B "perf-rainbow.html"' -- `-c CPU, --CPU CPU` renders with CPU instead of GPU -- `-l LAYOUTTHREADS, --LayoutThreads LAYOUTTHREADS` sets the maximum number of threads for layout, for example " -L 5" -- `-o OUTPUT, --Output OUTPUT` specifyes the output directory - -## Example - -This command will measure power and performance for 1 to 5 threads in layout with CPU rendering when we are running the about-mozilla.html benchmark - -``` sh -sudo python PowerMeasure.py -L 5 -c cpu -b "/Desktop/servo/src/test/html/about-mozilla.html" -o /Desktop/Results/ -``` diff --git a/servo/tests/unit/deny_public_fields/Cargo.toml b/servo/tests/unit/deny_public_fields/Cargo.toml deleted file mode 100644 index 679069d2c1ba..000000000000 --- a/servo/tests/unit/deny_public_fields/Cargo.toml +++ /dev/null @@ -1,12 +0,0 @@ -[package] -name = "deny_public_fields_tests" -version = "0.0.1" -authors = ["The Servo Project Developers"] -license = "MPL-2.0" - -[lib] -path = "lib.rs" -test = false - -[dependencies] -deny_public_fields = {path = "../../../components/deny_public_fields"} diff --git a/servo/tests/unit/deny_public_fields/lib.rs b/servo/tests/unit/deny_public_fields/lib.rs deleted file mode 100644 index 1fcb1314cf3c..000000000000 --- a/servo/tests/unit/deny_public_fields/lib.rs +++ /dev/null @@ -1,33 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -/** -```compile_fail -#[macro_use] extern crate deny_public_fields; - -#[derive(DenyPublicFields)] -struct Foo { - pub v1: i32, - v2: i32 -} - -fn main() {} -``` -*/ -pub fn deny_public_fields_failing() {} - -/** -``` -#[macro_use] extern crate deny_public_fields; - -#[derive(DenyPublicFields)] -struct Foo { - v1: i32, - v2: i32 -} - -fn main() {} -``` -*/ -pub fn deny_public_fields_ok() {} diff --git a/servo/tests/unit/metrics/Cargo.toml b/servo/tests/unit/metrics/Cargo.toml deleted file mode 100644 index 7ab518b8bea9..000000000000 --- a/servo/tests/unit/metrics/Cargo.toml +++ /dev/null @@ -1,22 +0,0 @@ -[package] -name = "metrics_tests" -version = "0.0.1" -authors = ["The Servo Project Developers"] -license = "MPL-2.0" - -[lib] -name = "metrics_tests" -path = "lib.rs" -doctest = false - -[dependencies] -gfx = {path = "../../../components/gfx"} -gfx_traits = {path = "../../../components/gfx_traits"} -ipc-channel = "0.10" -metrics = {path = "../../../components/metrics"} -msg = {path = "../../../components/msg"} -net_traits = {path = "../../../components/net_traits"} -profile_traits = {path = "../../../components/profile_traits"} -servo_url = {path = "../../../components/url"} -time = "0.1.12" -webrender_api = {git = "https://github.com/servo/webrender"} diff --git a/servo/tests/unit/metrics/interactive_time.rs b/servo/tests/unit/metrics/interactive_time.rs deleted file mode 100644 index c8999df4b3b2..000000000000 --- a/servo/tests/unit/metrics/interactive_time.rs +++ /dev/null @@ -1,116 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -use ipc_channel::ipc; -use metrics::{InteractiveMetrics, InteractiveFlag}; -use metrics::{ProfilerMetadataFactory, ProgressiveWebMetric}; -use profile_traits::time::{ProfilerChan, TimerMetadata}; -use servo_url::ServoUrl; -use time; - -struct DummyProfilerMetadataFactory {} -impl ProfilerMetadataFactory for DummyProfilerMetadataFactory { - fn new_metadata(&self) -> Option { - None - } -} - - -fn test_interactive() -> InteractiveMetrics { - let (sender, _) = ipc::channel().unwrap(); - let profiler_chan = ProfilerChan(sender); - let mut interactive = InteractiveMetrics::new( - profiler_chan, - ServoUrl::parse("about:blank").unwrap(), - ); - - assert_eq!((&interactive).get_navigation_start(), None); - assert_eq!(interactive.get_tti(), None); - - interactive.set_navigation_start(time::precise_time_ns()); - - interactive -} - -#[test] -fn test_set_dcl() { - let profiler_metadata_factory = DummyProfilerMetadataFactory {}; - - let interactive = test_interactive(); - interactive.maybe_set_tti(&profiler_metadata_factory, InteractiveFlag::DOMContentLoaded); - let dcl = interactive.get_dom_content_loaded(); - assert!(dcl.is_some()); - - //try to overwrite - interactive.maybe_set_tti(&profiler_metadata_factory, InteractiveFlag::DOMContentLoaded); - assert_eq!(interactive.get_dom_content_loaded(), dcl); - assert_eq!(interactive.get_tti(), None); -} - -#[test] -fn test_set_mta() { - let profiler_metadata_factory = DummyProfilerMetadataFactory {}; - - let interactive = test_interactive(); - let t = time::precise_time_ns(); - interactive.maybe_set_tti( - &profiler_metadata_factory, - InteractiveFlag::TimeToInteractive(t), - ); - let mta = interactive.get_main_thread_available(); - assert!(mta.is_some()); - assert_eq!(mta, Some(t)); - - //try to overwrite - interactive.maybe_set_tti( - &profiler_metadata_factory, - InteractiveFlag::TimeToInteractive(time::precise_time_ns()), - ); - assert_eq!(interactive.get_main_thread_available(), mta); - assert_eq!(interactive.get_tti(), None); -} - -#[test] -fn test_set_tti_dcl() { - let profiler_metadata_factory = DummyProfilerMetadataFactory {}; - - let interactive = test_interactive(); - let t = time::precise_time_ns(); - interactive.maybe_set_tti( - &profiler_metadata_factory, - InteractiveFlag::TimeToInteractive(t), - ); - let mta = interactive.get_main_thread_available(); - assert!(mta.is_some()); - - interactive.maybe_set_tti(&profiler_metadata_factory, InteractiveFlag::DOMContentLoaded); - let dcl = interactive.get_dom_content_loaded(); - assert!(dcl.is_some()); - - let interactive_time = dcl.unwrap() - (&interactive).get_navigation_start().unwrap(); - assert_eq!(interactive.get_tti(), Some(interactive_time)); -} - -#[test] -fn test_set_tti_mta() { - let profiler_metadata_factory = DummyProfilerMetadataFactory {}; - - let interactive = test_interactive(); - interactive.maybe_set_tti(&profiler_metadata_factory, InteractiveFlag::DOMContentLoaded); - let dcl = interactive.get_dom_content_loaded(); - assert!(dcl.is_some()); - - let t = time::precise_time_ns(); - interactive.maybe_set_tti( - &profiler_metadata_factory, - InteractiveFlag::TimeToInteractive(t), - ); - let mta = interactive.get_main_thread_available(); - assert!(mta.is_some()); - - let interactive_time = mta.unwrap() - (&interactive).get_navigation_start().unwrap(); - assert_eq!(interactive.get_tti(), Some(interactive_time)); -} - -// TODO InteractiveWindow tests diff --git a/servo/tests/unit/metrics/lib.rs b/servo/tests/unit/metrics/lib.rs deleted file mode 100644 index e66c14ef1d8c..000000000000 --- a/servo/tests/unit/metrics/lib.rs +++ /dev/null @@ -1,19 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -#![cfg(test)] - -extern crate gfx; -extern crate gfx_traits; -extern crate ipc_channel; -extern crate metrics; -extern crate msg; -extern crate net_traits; -extern crate profile_traits; -extern crate servo_url; -extern crate time; -extern crate webrender_api; - -mod interactive_time; -mod paint_time; diff --git a/servo/tests/unit/metrics/paint_time.rs b/servo/tests/unit/metrics/paint_time.rs deleted file mode 100644 index 79a40799dd95..000000000000 --- a/servo/tests/unit/metrics/paint_time.rs +++ /dev/null @@ -1,149 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -use gfx::display_list::{BaseDisplayItem, WebRenderImageInfo}; -use gfx::display_list::{DisplayItem, DisplayList, ImageDisplayItem}; -use gfx_traits::Epoch; -use ipc_channel::ipc; -use metrics::{PaintTimeMetrics, ProfilerMetadataFactory, ProgressiveWebMetric}; -use msg::constellation_msg::TEST_PIPELINE_ID; -use net_traits::image::base::PixelFormat; -use profile_traits::time::{ProfilerChan, TimerMetadata}; -use servo_url::ServoUrl; -use time; -use webrender_api::{ImageRendering, LayoutSize}; - -struct DummyProfilerMetadataFactory {} -impl ProfilerMetadataFactory for DummyProfilerMetadataFactory { - fn new_metadata(&self) -> Option { - None - } -} - -#[test] -fn test_paint_metrics_construction() { - let (sender, _) = ipc::channel().unwrap(); - let profiler_chan = ProfilerChan(sender); - let (layout_sender, _) = ipc::channel().unwrap(); - let (script_sender, _) = ipc::channel().unwrap(); - let paint_time_metrics = PaintTimeMetrics::new( - TEST_PIPELINE_ID, - profiler_chan, - layout_sender, - script_sender, - ServoUrl::parse("about:blank").unwrap(), - ); - assert_eq!( - (&paint_time_metrics).get_navigation_start(), - None, - "navigation start is None" - ); - assert_eq!( - paint_time_metrics.get_first_paint(), - None, - "first paint is None" - ); - assert_eq!( - paint_time_metrics.get_first_contentful_paint(), - None, - "first contentful paint is None" - ); -} - -fn test_common(display_list: &DisplayList, epoch: Epoch) -> PaintTimeMetrics { - let (sender, _) = ipc::channel().unwrap(); - let profiler_chan = ProfilerChan(sender); - let (layout_sender, _) = ipc::channel().unwrap(); - let (script_sender, _) = ipc::channel().unwrap(); - let mut paint_time_metrics = PaintTimeMetrics::new( - TEST_PIPELINE_ID, - profiler_chan, - layout_sender, - script_sender, - ServoUrl::parse("about:blank").unwrap(), - ); - let dummy_profiler_metadata_factory = DummyProfilerMetadataFactory {}; - - paint_time_metrics.maybe_observe_paint_time( - &dummy_profiler_metadata_factory, - epoch, - &*display_list, - ); - - // Should not set any metric until navigation start is set. - paint_time_metrics.maybe_set_metric(epoch, 0); - assert_eq!( - paint_time_metrics.get_first_paint(), - None, - "first paint is None" - ); - assert_eq!( - paint_time_metrics.get_first_contentful_paint(), - None, - "first contentful paint is None" - ); - - let navigation_start = time::precise_time_ns(); - paint_time_metrics.set_navigation_start(navigation_start); - assert_eq!( - (&paint_time_metrics).get_navigation_start().unwrap(), - navigation_start, - "navigation start is set" - ); - - paint_time_metrics -} - -#[test] -fn test_first_paint_setter() { - let empty_display_list = DisplayList { - list: Vec::new(), - clip_scroll_nodes: Vec::new(), - }; - let epoch = Epoch(0); - let paint_time_metrics = test_common(&empty_display_list, epoch); - let now = time::precise_time_ns(); - paint_time_metrics.maybe_set_metric(epoch, now); - assert!( - paint_time_metrics.get_first_paint().is_some(), - "first paint is set" - ); - assert_eq!( - paint_time_metrics.get_first_contentful_paint(), - None, - "first contentful paint is None" - ); -} - -#[test] -fn test_first_contentful_paint_setter() { - let image = DisplayItem::Image(Box::new(ImageDisplayItem { - base: BaseDisplayItem::empty(), - webrender_image: WebRenderImageInfo { - width: 1, - height: 1, - format: PixelFormat::RGB8, - key: None, - }, - stretch_size: LayoutSize::zero(), - tile_spacing: LayoutSize::zero(), - image_rendering: ImageRendering::Auto, - })); - let display_list = DisplayList { - list: vec![image], - clip_scroll_nodes: Vec::new(), - }; - let epoch = Epoch(0); - let paint_time_metrics = test_common(&display_list, epoch); - let now = time::precise_time_ns(); - paint_time_metrics.maybe_set_metric(epoch, now); - assert!( - paint_time_metrics.get_first_contentful_paint().is_some(), - "first contentful paint is set" - ); - assert!( - paint_time_metrics.get_first_paint().is_some(), - "first paint is set" - ); -} diff --git a/servo/tests/unit/profile/Cargo.toml b/servo/tests/unit/profile/Cargo.toml deleted file mode 100644 index d3feb4108847..000000000000 --- a/servo/tests/unit/profile/Cargo.toml +++ /dev/null @@ -1,20 +0,0 @@ -[package] -name = "profile_tests" -version = "0.0.1" -authors = ["The Servo Project Developers"] -license = "MPL-2.0" - -[lib] -name = "profile_tests" -path = "lib.rs" -doctest = false - -[dependencies] -ipc-channel = "0.10" -profile = {path = "../../../components/profile"} -profile_traits = {path = "../../../components/profile_traits"} - -# Work around https://github.com/alexcrichton/jemallocator/issues/19 -servo_allocator = {path = "../../../components/allocator"} -servo_config = {path = "../../../components/config"} - diff --git a/servo/tests/unit/profile/lib.rs b/servo/tests/unit/profile/lib.rs deleted file mode 100644 index a67e211ad7b6..000000000000 --- a/servo/tests/unit/profile/lib.rs +++ /dev/null @@ -1,13 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -#![cfg(test)] - -extern crate ipc_channel; -extern crate profile; -extern crate profile_traits; -extern crate servo_allocator; -extern crate servo_config; - -mod time; diff --git a/servo/tests/unit/profile/time.rs b/servo/tests/unit/profile/time.rs deleted file mode 100644 index 19d3a19ee5d1..000000000000 --- a/servo/tests/unit/profile/time.rs +++ /dev/null @@ -1,81 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -use ipc_channel::ipc; -use profile::time; -use profile_traits::ipc as ProfiledIpc; -use profile_traits::time::{ProfilerCategory, ProfilerData, ProfilerMsg}; -use servo_config::opts::OutputOptions; -use std::thread; -use std::time::Duration; - -#[test] -fn time_profiler_smoke_test() { - let chan = time::Profiler::create(&None, None); - assert!(true, "Can create the profiler thread"); - - let (ipcchan, _ipcport) = ipc::channel().unwrap(); - chan.send(ProfilerMsg::Exit(ipcchan)); - assert!(true, "Can tell the profiler thread to exit"); -} - -#[test] -fn time_profiler_stats_test() { - let even_data = vec![1.234, 3.24567, 3.54578, 5.0, 5.324, 7.345, - 9.2345, 10.2342345, 13.2599, 15.0]; - let (even_mean, even_median, even_min, even_max) = time::Profiler::get_statistics(&even_data); - - assert_eq!(7.34230845, even_mean); - assert_eq!(7.345, even_median); - assert_eq!(1.234, even_min); - assert_eq!(15.0, even_max); - - let odd_data = vec![1.234, 3.24567, 3.54578, 5.0, 5.324, 7.345, - 9.2345, 10.2342345, 13.2599]; - let (odd_mean, odd_median, odd_min, odd_max) = time::Profiler::get_statistics(&odd_data); - - assert_eq!(6.491453833333334, odd_mean); - assert_eq!(5.324, odd_median); - assert_eq!(1.234, odd_min); - assert_eq!(13.2599, odd_max); -} - -#[test] -fn channel_profiler_test() { - let chan = time::Profiler::create(&Some(OutputOptions::Stdout(5.0)), None); - let (profiled_sender, profiled_receiver) = ProfiledIpc::channel(chan.clone()).unwrap(); - thread::spawn(move || { - thread::sleep(Duration::from_secs(2)); - profiled_sender.send(43).unwrap(); - }); - - let val_profile_receiver = profiled_receiver.recv().unwrap(); - assert_eq!(val_profile_receiver, 43); - - let (sender, receiver) = ipc::channel().unwrap(); - chan.send(ProfilerMsg::Get((ProfilerCategory::IpcReceiver, None), sender.clone())); - - match receiver.recv().unwrap() { - // asserts that the time spent in the sleeping thread is more than 1500 milliseconds - ProfilerData::Record(time_data) => assert!(time_data[0] > 1.5e3), - ProfilerData::NoRecords => assert!(false), - }; - -} - -#[cfg(debug_assertions)] -#[test] -#[should_panic] -fn time_profiler_unsorted_stats_test() { - let unsorted_data = vec![5.0, 7.5, 1.0, 8.9]; - time::Profiler::get_statistics(&unsorted_data); -} - -#[cfg(debug_assertions)] -#[test] -#[should_panic] -fn time_profiler_data_len_zero() { - let zero_data = vec![]; - time::Profiler::get_statistics(&zero_data); -} diff --git a/servo/tests/unit/script/Cargo.toml b/servo/tests/unit/script/Cargo.toml deleted file mode 100644 index f6743a7dba6a..000000000000 --- a/servo/tests/unit/script/Cargo.toml +++ /dev/null @@ -1,16 +0,0 @@ -[package] -name = "script_tests" -version = "0.0.1" -authors = ["The Servo Project Developers"] -license = "MPL-2.0" - -[lib] -name = "script_tests" -path = "lib.rs" - -[dependencies] -euclid = "0.17" -msg = {path = "../../../components/msg"} -script = {path = "../../../components/script"} -servo_url = {path = "../../../components/url"} -style = {path = "../../../components/style"} diff --git a/servo/tests/unit/script/headers.rs b/servo/tests/unit/script/headers.rs deleted file mode 100644 index e990b706cdd3..000000000000 --- a/servo/tests/unit/script/headers.rs +++ /dev/null @@ -1,73 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -use script::test::{ByteString, normalize_value}; - -#[test] -fn test_normalize_empty_bytestring() { - // empty ByteString test - let empty_bytestring = ByteString::new(vec![]); - let actual = normalize_value(empty_bytestring); - let expected = ByteString::new(vec![]); - assert_eq!(actual, expected); -} - -#[test] -fn test_normalize_all_whitespace_bytestring() { - // All whitespace test. A horizontal tab, a line feed, a carriage return , and a space - let all_whitespace_bytestring = ByteString::new(vec![b'\t', b'\n', b'\r', b' ']); - let actual = normalize_value(all_whitespace_bytestring); - let expected = ByteString::new(vec![]); - assert_eq!(actual, expected); -} - -#[test] -fn test_normalize_non_empty_no_whitespace_bytestring() { - // Non-empty, no whitespace ByteString test - let no_whitespace_bytestring = ByteString::new(vec![b'S', b'!']); - let actual = normalize_value(no_whitespace_bytestring); - let expected = ByteString::new(vec![b'S', b'!']); - assert_eq!(actual, expected); -} - -#[test] -fn test_normalize_non_empty_leading_whitespace_bytestring() { - // Non-empty, leading whitespace, no trailing whitespace ByteString test - let leading_whitespace_bytestring = ByteString::new(vec![b'\t', b'\n', b' ', b'\r', b'S', b'!']); - let actual = normalize_value(leading_whitespace_bytestring); - let expected = ByteString::new(vec![b'S', b'!']); - assert_eq!(actual, expected); -} - -#[test] -fn test_normalize_non_empty_no_leading_whitespace_trailing_whitespace_bytestring() { - // Non-empty, no leading whitespace, but with trailing whitespace ByteString test - let trailing_whitespace_bytestring = ByteString::new(vec![b'S', b'!', b'\t', b'\n', b' ', b'\r']); - let actual = normalize_value(trailing_whitespace_bytestring); - let expected = ByteString::new(vec![b'S', b'!']); - assert_eq!(actual, expected); -} - -#[test] -fn test_normalize_non_empty_leading_and_trailing_whitespace_bytestring() { - // Non-empty, leading whitespace, and trailing whitespace ByteString test - let whitespace_sandwich_bytestring = - ByteString::new(vec![b'\t', b'\n', b' ', b'\r', b'S', b'!', b'\t', b'\n', b' ', b'\r']); - let actual = normalize_value(whitespace_sandwich_bytestring); - let expected = ByteString::new(vec![b'S', b'!']); - assert_eq!(actual, expected); -} - -#[test] -fn test_normalize_non_empty_leading_trailing_and_internal_whitespace_bytestring() { - // Non-empty, leading whitespace, trailing whitespace, - // and internal whitespace ByteString test - let whitespace_bigmac_bytestring = - ByteString::new(vec![b'\t', b'\n', b' ', b'\r', b'S', - b'\t', b'\n', b' ', b'\r', b'!', - b'\t', b'\n', b' ', b'\r']); - let actual = normalize_value(whitespace_bigmac_bytestring); - let expected = ByteString::new(vec![b'S', b'\t', b'\n', b' ', b'\r', b'!']); - assert_eq!(actual, expected); -} diff --git a/servo/tests/unit/script/htmlareaelement.rs b/servo/tests/unit/script/htmlareaelement.rs deleted file mode 100644 index c2a98fd86817..000000000000 --- a/servo/tests/unit/script/htmlareaelement.rs +++ /dev/null @@ -1,122 +0,0 @@ -// Copyright 2013 The Servo Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -use euclid::Point2D; -use script::test::area::{Area, Shape}; - -#[test] -fn garbage_input() { - assert!(Area::parse(";.,()8.2", Shape::Circle).is_none()) -} - -#[test] -fn no_case_matching_input() { - assert!(Area::parse("8.2, 10.2", Shape::Circle).is_none()) -} - -#[test] -fn delimiter_input() { - assert!(Area::parse(";, ;,", Shape::Circle).is_none()) -} - -// Area::Circle tests -#[test] -fn valid_circle_inputs() { - assert_eq!(Area::parse("10.2, 3.4, 5.2", Shape::Circle), - Some(Area::Circle { left: 10.2, top: 3.4, radius: 5.2 })); -} - -#[test] -fn valid_negative_circle_inputs() { - assert_eq!(Area::parse("-10.2, -3.4, 5.2", Shape::Circle), - Some(Area::Circle { left: -10.2, top: -3.4, radius: 5.2 })); -} - -#[test] -fn invalid_negative_circle_radius() { - assert!(Area::parse("-10.2, -3.4, -5.2", Shape::Circle).is_none()); -} - -// Area::Rectangle tests -#[test] -fn rectangle_valid_input() { - assert_eq!(Area::parse("5.2, 1.1, 10.2, 3.4", Shape::Rectangle), - Some(Area::Rectangle { top_left: (5.2, 1.1), - bottom_right: (10.2, 3.4) })); -} - -#[test] -fn rectangle_valid_negative_input() { - assert_eq!(Area::parse("-10.2, -3.4, -5.2, -1.1", Shape::Rectangle), - Some(Area::Rectangle { top_left: (-10.2, -3.4), - bottom_right: (-5.2, -1.1) })); -} - -#[test] -fn rectangle_invalid_input() { - assert_eq!(Area::parse("5.2, 4.3, 10.2, 1.1.2", Shape::Rectangle), - Some(Area::Rectangle { top_left: (5.2, 0.0), - bottom_right: (10.2, 4.3) })); -} - -#[test] -fn rectangle_unordered_input() { - assert_eq!(Area::parse("5.2, 1.1, 10.2, 4.3", Shape::Rectangle), - Some(Area::Rectangle { top_left: (5.2, 1.1), - bottom_right: (10.2, 4.3) })); -} - -// Area::Polygon tests -#[test] -fn polygon_six_points_valid_input() { - assert_eq!(Area::parse("1.1, 1.1, 6.1, 1.1, 3.1, 3.1", Shape::Polygon), - Some(Area::Polygon { points: vec![1.1, 1.1, 6.1, 1.1, 3.1, 3.1] })); -} - -#[test] -fn polygon_six_points_valid_negative_input() { - assert_eq!(Area::parse("1.1, -1.1, 6.1, -1.1, 3.1, -3.1", Shape::Polygon), - Some(Area::Polygon { points: vec![1.1, -1.1, 6.1, -1.1, 3.1, -3.1] })); -} - -#[test] -fn polygon_six_points_invalid_input() { - assert_eq!(Area::parse(";1.1, 1.1,'; 6.1,(*^() 1.1, 3.1, 3.1, 100.1 %$,;", Shape::Polygon), - Some(Area::Polygon { points: vec![1.1, 1.1, 6.1, 1.1, 3.1, 3.1] })); -} - -#[test] -fn polygon_eight_points_invalid_input() { - assert_eq!(Area::parse("1.1, -1.1, 6.1, -1.1, 1.1, -3.1, 6.1, -3.1.2, 12.1", Shape::Polygon), - Some(Area::Polygon { points: vec![1.1, -1.1, 6.1, -1.1, 1.1, -3.1, 6.1, 0.0] })); -} - -#[test] -fn test_hit_test_circle() { - let circ1 = Area::Circle { left: 20.0, top: 10.0, radius: 5.0 }; - assert!(!circ1.hit_test(&Point2D::new(10.0, 20.0))); - let circ2 = Area::Circle { left: 10.0, top: 10.0, radius: 5.0 }; - assert!(circ2.hit_test(&Point2D::new(10.0, 12.0))); -} - -#[test] -fn test_hit_test_rectangle() { - let rect1 = Area::Rectangle { top_left: (1.0, 7.0), bottom_right: (15.0, 10.0) }; - assert!(!rect1.hit_test(&Point2D::new(10.0, 5.0))); - let rect2 = Area::Rectangle { top_left: (8.0, 10.0), bottom_right: (20.0, 12.0) }; - assert!(rect2.hit_test(&Point2D::new(10.0, 12.0))); -} - -#[test] -fn test_hit_test_polygon() { - let poly1 = Area::Polygon { points: vec![1.0, 2.0, 3.0, 4.0, 5.0, 6.0] }; - assert!(!poly1.hit_test(&Point2D::new(10.0, 5.0))); - let poly2 = Area::Polygon { points: vec![7.0, 7.5, 8.2, 9.0, 11.0, 12.0] }; - assert!(!poly2.hit_test(&Point2D::new(10.0, 5.0))); -} diff --git a/servo/tests/unit/script/htmlimageelement.rs b/servo/tests/unit/script/htmlimageelement.rs deleted file mode 100644 index 6d62f25a500b..000000000000 --- a/servo/tests/unit/script/htmlimageelement.rs +++ /dev/null @@ -1,181 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -use script::test::DOMString; -use script::test::sizes::{parse_a_sizes_attribute, Size}; -use script::test::srcset::{Descriptor, ImageSource, parse_a_srcset_attribute}; -use style::media_queries::{MediaQuery, MediaQueryType}; -use style::media_queries::Expression; -use style::servo::media_queries::{ExpressionKind, Range}; -use style::values::specified::{Length, NoCalcLength, AbsoluteLength, ViewportPercentageLength}; - -pub fn test_length_for_no_default_provided(len: f32) -> Length { - let length = Length::NoCalc(NoCalcLength::ViewportPercentage(ViewportPercentageLength::Vw(len))); - return length; -} - -#[test] -fn no_default_provided() { - let mut a = vec![]; - let length = test_length_for_no_default_provided(100f32); - let size = Size { query: None, length: length }; - a.push(size); - assert_eq!(parse_a_sizes_attribute(DOMString::new(), None), a); -} - -pub fn test_length_for_default_provided(len: f32) -> Length { - let length = Length::NoCalc(NoCalcLength::Absolute(AbsoluteLength::Px(len))); - return length; -} - -#[test] -fn default_provided() { - let mut a = vec![]; - let length = test_length_for_default_provided(2f32); - let size = Size { query: None, length: length }; - a.push(size); - assert_eq!(parse_a_sizes_attribute(DOMString::new(), Some(2)), a); -} - -pub fn test_media_query(len: f32) -> MediaQuery { - let length = Length::NoCalc(NoCalcLength::Absolute(AbsoluteLength::Px(len))); - let expr = Expression(ExpressionKind::Width(Range::Max(length))); - let media_query = MediaQuery { - qualifier: None, - media_type: MediaQueryType::All, - expressions: vec![expr] - }; - media_query -} - -pub fn test_length(len: f32) -> Length { - let length = Length::NoCalc(NoCalcLength::Absolute(AbsoluteLength::Px(len))); - return length; -} - -#[test] -fn one_value() { - let mut a = vec![]; - let media_query = test_media_query(200f32); - let length = test_length(545f32); - let size = Size { query: Some(media_query), length: length }; - a.push(size); - assert_eq!(parse_a_sizes_attribute(DOMString::from("(max-width: 200px) 545px"), None), a); -} - -#[test] -fn more_then_one_value() { - let media_query = test_media_query(900f32); - let length = test_length(1000f32); - let size = Size { query: Some(media_query), length: length }; - let media_query1 = test_media_query(900f32); - let length1 = test_length(50f32); - let size1 = Size { query: Some(media_query1), length: length1 }; - let a = &[size, size1]; - assert_eq!(parse_a_sizes_attribute(DOMString::from("(max-width: 900px) 1000px, (max-width: 900px) 50px"), - None), a); -} - -#[test] -fn no_extra_whitespace() { - let mut a = vec![]; - let media_query = test_media_query(200f32); - let length = test_length(545f32); - let size = Size { query: Some(media_query), length: length }; - a.push(size); - assert_eq!(parse_a_sizes_attribute(DOMString::from("(max-width: 200px) 545px"), None), a); -} - -#[test] -fn extra_whitespace() { - let media_query = test_media_query(900f32); - let length = test_length(1000f32); - let size = Size { query: Some(media_query), length: length }; - let media_query1 = test_media_query(900f32); - let length1 = test_length(50f32); - let size1 = Size { query: Some(media_query1), length: length1 }; - let a = &[size, size1]; - assert_eq!(parse_a_sizes_attribute( - DOMString::from("(max-width: 900px) 1000px, (max-width: 900px) 50px"), - None), a); -} - -#[test] -fn no_value() { - let new_vec = Vec::new(); - assert_eq!(parse_a_srcset_attribute(" "), new_vec); -} - -#[test] -fn width_one_value() { - let first_descriptor = Descriptor { wid: Some(320), den: None }; - let first_imagesource = ImageSource { url: "small-image.jpg".to_string(), descriptor: first_descriptor }; - let sources = &[first_imagesource]; - assert_eq!(parse_a_srcset_attribute("small-image.jpg, 320w"), sources); -} - -#[test] -fn width_two_value() { - let first_descriptor = Descriptor { wid: Some(320), den: None }; - let first_imagesource = ImageSource { url: "small-image.jpg".to_string(), descriptor: first_descriptor }; - let second_descriptor = Descriptor { wid: Some(480), den: None }; - let second_imagesource = ImageSource { url: "medium-image.jpg".to_string(), descriptor: second_descriptor }; - let sources = &[first_imagesource, second_imagesource]; - assert_eq!(parse_a_srcset_attribute("small-image.jpg 320w, medium-image.jpg 480w"), sources); -} - -#[test] -fn width_three_value() { - let first_descriptor = Descriptor { wid: Some(320), den: None }; - let first_imagesource = ImageSource { url: "smallImage.jpg".to_string(), descriptor: first_descriptor }; - let second_descriptor = Descriptor { wid: Some(480), den: None }; - let second_imagesource = ImageSource { url: "mediumImage.jpg".to_string(), descriptor: second_descriptor }; - let third_descriptor = Descriptor { wid: Some(800), den: None }; - let third_imagesource = ImageSource { url: "largeImage.jpg".to_string(), descriptor: third_descriptor }; - let sources = &[first_imagesource, second_imagesource, third_imagesource]; - assert_eq!(parse_a_srcset_attribute("smallImage.jpg 320w, - mediumImage.jpg 480w, - largeImage.jpg 800w"), sources); -} - -#[test] -fn density_value() { - let first_descriptor = Descriptor { wid: None, den: Some(1.0) }; - let first_imagesource = ImageSource { url: "small-image.jpg".to_string(), descriptor: first_descriptor }; - let sources = &[first_imagesource]; - assert_eq!(parse_a_srcset_attribute("small-image.jpg 1x"), sources); -} - -#[test] -fn without_descriptor() { - let first_descriptor = Descriptor { wid: None, den: None }; - let first_imagesource = ImageSource { url: "small-image.jpg".to_string(), descriptor: first_descriptor }; - let sources = &[first_imagesource]; - assert_eq!(parse_a_srcset_attribute("small-image.jpg"), sources); -} - -//Does not parse an ImageSource when both width and density descriptor present -#[test] -fn two_descriptor() { - let empty_vec = Vec::new(); - assert_eq!(parse_a_srcset_attribute("small-image.jpg 320w 1.1x"), empty_vec); -} - -#[test] -fn decimal_descriptor() { - let first_descriptor = Descriptor { wid: None, den: Some(2.2) }; - let first_imagesource = ImageSource { url: "small-image.jpg".to_string(), descriptor: first_descriptor }; - let sources = &[first_imagesource]; - assert_eq!(parse_a_srcset_attribute("small-image.jpg 2.2x"), sources); -} - -#[test] -fn different_descriptor() { - let first_descriptor = Descriptor { wid: Some(320), den: None }; - let first_imagesource = ImageSource { url: "small-image.jpg".to_string(), descriptor: first_descriptor }; - let second_descriptor = Descriptor { wid: None, den: Some(2.2) }; - let second_imagesource = ImageSource { url: "medium-image.jpg".to_string(), descriptor: second_descriptor }; - let sources = &[first_imagesource, second_imagesource]; - assert_eq!(parse_a_srcset_attribute("small-image.jpg 320w, medium-image.jpg 2.2x"), sources); -} diff --git a/servo/tests/unit/script/lib.rs b/servo/tests/unit/script/lib.rs deleted file mode 100644 index 6d724db5358f..000000000000 --- a/servo/tests/unit/script/lib.rs +++ /dev/null @@ -1,29 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -#[cfg(test)] extern crate euclid; -#[cfg(test)] extern crate msg; -#[cfg(test)] extern crate script; -#[cfg(test)] extern crate servo_url; -#[cfg(test)] extern crate style; - -#[cfg(test)] mod origin; -#[cfg(all(test, target_pointer_width = "64"))] mod size_of; -#[cfg(test)] mod textinput; -#[cfg(test)] mod headers; -#[cfg(test)] mod htmlareaelement; -#[cfg(test)] mod htmlimageelement; - -/** -```compile_fail,E0277 -extern crate script; - -fn cloneable() {} - -fn main() { - cloneable::(); -} -``` -*/ -pub fn trustedpromise_does_not_impl_clone() {} diff --git a/servo/tests/unit/script/origin.rs b/servo/tests/unit/script/origin.rs deleted file mode 100644 index 526b12bf0f92..000000000000 --- a/servo/tests/unit/script/origin.rs +++ /dev/null @@ -1,63 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -use servo_url::{ImmutableOrigin, MutableOrigin, ServoUrl}; - -#[test] -fn same_origin() { - let a = MutableOrigin::new(ServoUrl::parse("http://example.com/a.html").unwrap().origin()); - let b = MutableOrigin::new(ServoUrl::parse("http://example.com/b.html").unwrap().origin()); - assert!(a.same_origin(&b)); - assert_eq!(a.is_tuple(), true); -} - -#[test] -fn identical_origin() { - let a = MutableOrigin::new(ServoUrl::parse("http://example.com/a.html").unwrap().origin()); - assert!(a.same_origin(&a)); -} - -#[test] -fn cross_origin() { - let a = MutableOrigin::new(ServoUrl::parse("http://example.com/a.html").unwrap().origin()); - let b = MutableOrigin::new(ServoUrl::parse("http://example.org/b.html").unwrap().origin()); - assert!(!a.same_origin(&b)); -} - -#[test] -fn clone_same_origin() { - let a = MutableOrigin::new(ServoUrl::parse("http://example.com/a.html").unwrap().origin()); - let b = MutableOrigin::new(ServoUrl::parse("http://example.com/b.html").unwrap().origin()); - let c = b.clone(); - assert!(a.same_origin(&c)); - assert!(b.same_origin(&b)); - assert!(c.same_origin(&b)); - assert_eq!(c.is_tuple(), true); -} - -#[test] -fn clone_cross_origin() { - let a = MutableOrigin::new(ServoUrl::parse("http://example.com/a.html").unwrap().origin()); - let b = MutableOrigin::new(ServoUrl::parse("http://example.org/b.html").unwrap().origin()); - let c = b.clone(); - assert!(!a.same_origin(&c)); - assert!(b.same_origin(&c)); - assert!(c.same_origin(&c)); -} - -#[test] -fn opaque() { - let a = MutableOrigin::new(ImmutableOrigin::new_opaque()); - let b = MutableOrigin::new(ImmutableOrigin::new_opaque()); - assert!(!a.same_origin(&b)); - assert_eq!(a.is_tuple(), false); -} - -#[test] -fn opaque_clone() { - let a = MutableOrigin::new(ImmutableOrigin::new_opaque()); - let b = a.clone(); - assert!(a.same_origin(&b)); - assert_eq!(a.is_tuple(), false); -} diff --git a/servo/tests/unit/script/size_of.rs b/servo/tests/unit/script/size_of.rs deleted file mode 100644 index 903ffc5ddc31..000000000000 --- a/servo/tests/unit/script/size_of.rs +++ /dev/null @@ -1,39 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -use script::test::size_of; - -// Macro so that we can stringify type names -// I'd really prefer the tests themselves to be run at plugin time, -// however rustc::middle doesn't have access to the full type data -macro_rules! sizeof_checker ( - ($testname: ident, $t: ident, $known_size: expr) => ( - #[test] - fn $testname() { - let new = size_of::$t(); - let old = $known_size; - if new < old { - panic!("Your changes have decreased the stack size of commonly used DOM struct {} from {} to {}. \ - Good work! Please update the size in tests/unit/script/size_of.rs.", - stringify!($t), old, new) - } else if new > old { - panic!("Your changes have increased the stack size of commonly used DOM struct {} from {} to {}. \ - These structs are present in large quantities in the DOM, and increasing the size \ - may dramatically affect our memory footprint. Please consider choosing a design which \ - avoids this increase. If you feel that the increase is necessary, \ - update to the new size in tests/unit/script/size_of.rs.", - stringify!($t), old, new) - } - }); -); - -// Update the sizes here -sizeof_checker!(size_event_target, EventTarget, 40); -sizeof_checker!(size_node, Node, 184); -sizeof_checker!(size_element, Element, 432); -sizeof_checker!(size_htmlelement, HTMLElement, 448); -sizeof_checker!(size_div, HTMLDivElement, 448); -sizeof_checker!(size_span, HTMLSpanElement, 448); -sizeof_checker!(size_text, Text, 216); -sizeof_checker!(size_characterdata, CharacterData, 216); diff --git a/servo/tests/unit/script/textinput.rs b/servo/tests/unit/script/textinput.rs deleted file mode 100644 index 3880d641d851..000000000000 --- a/servo/tests/unit/script/textinput.rs +++ /dev/null @@ -1,662 +0,0 @@ -// Copyright 2013 The Servo Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -use msg::constellation_msg::{Key, KeyModifiers}; -use script::clipboard_provider::DummyClipboardContext; -use script::test::DOMString; -use script::textinput::{TextInput, TextPoint, Selection, Lines, Direction, SelectionDirection}; - -fn text_input(lines: Lines, s: &str) -> TextInput { - TextInput::new(lines, - DOMString::from(s), - DummyClipboardContext::new(""), - None, - None, - SelectionDirection::None) -} - -#[test] -fn test_set_content_ignores_max_length() { - let mut textinput = TextInput::new( - Lines::Single, DOMString::from(""), DummyClipboardContext::new(""), Some(1), None, SelectionDirection::None - ); - - textinput.set_content(DOMString::from("mozilla rocks")); - assert_eq!(textinput.get_content(), DOMString::from("mozilla rocks")); -} - -#[test] -fn test_textinput_when_inserting_multiple_lines_over_a_selection_respects_max_length() { - let mut textinput = TextInput::new( - Lines::Multiple, - DOMString::from("hello\nworld"), - DummyClipboardContext::new(""), - Some(17), - None, - SelectionDirection::None, - ); - - textinput.adjust_horizontal(1, Selection::NotSelected); - textinput.adjust_horizontal(3, Selection::Selected); - textinput.adjust_vertical(1, Selection::Selected); - - // Selection is now "hello\n - // ------ - // world" - // ---- - - textinput.insert_string("cruel\nterrible\nbad".to_string()); - - assert_eq!(textinput.get_content(), "hcruel\nterrible\nd"); -} - -#[test] -fn test_textinput_when_inserting_multiple_lines_still_respects_max_length() { - let mut textinput = TextInput::new( - Lines::Multiple, - DOMString::from("hello\nworld"), - DummyClipboardContext::new(""), - Some(17), - None, - SelectionDirection::None - ); - - textinput.adjust_vertical(1, Selection::NotSelected); - textinput.insert_string("cruel\nterrible".to_string()); - - assert_eq!(textinput.get_content(), "hello\ncruel\nworld"); -} - -#[test] -fn test_textinput_when_content_is_already_longer_than_max_length_and_theres_no_selection_dont_insert_anything() { - let mut textinput = TextInput::new( - Lines::Single, - DOMString::from("abc"), - DummyClipboardContext::new(""), - Some(1), - None, - SelectionDirection::None, - ); - - textinput.insert_char('a'); - - assert_eq!(textinput.get_content(), "abc"); -} - -#[test] -fn test_multi_line_textinput_with_maxlength_doesnt_allow_appending_characters_when_input_spans_lines() { - let mut textinput = TextInput::new( - Lines::Multiple, - DOMString::from("abc\nd"), - DummyClipboardContext::new(""), - Some(5), - None, - SelectionDirection::None, - ); - - textinput.insert_char('a'); - - assert_eq!(textinput.get_content(), "abc\nd"); -} - -#[test] -fn test_single_line_textinput_with_max_length_doesnt_allow_appending_characters_when_replacing_a_selection() { - let mut textinput = TextInput::new( - Lines::Single, - DOMString::from("abcde"), - DummyClipboardContext::new(""), - Some(5), - None, - SelectionDirection::None, - ); - - textinput.adjust_horizontal(1, Selection::NotSelected); - textinput.adjust_horizontal(3, Selection::Selected); - - // Selection is now "abcde" - // --- - - textinput.replace_selection(DOMString::from("too long")); - - assert_eq!(textinput.get_content(), "atooe"); -} - -#[test] -fn test_single_line_textinput_with_max_length_multibyte() { - let mut textinput = TextInput::new( - Lines::Single, - DOMString::from(""), - DummyClipboardContext::new(""), - Some(2), - None, - SelectionDirection::None, - ); - - textinput.insert_char('á'); - assert_eq!(textinput.get_content(), "á"); - textinput.insert_char('é'); - assert_eq!(textinput.get_content(), "áé"); - textinput.insert_char('i'); - assert_eq!(textinput.get_content(), "áé"); -} - -#[test] -fn test_single_line_textinput_with_max_length_multi_code_unit() { - let mut textinput = TextInput::new( - Lines::Single, - DOMString::from(""), - DummyClipboardContext::new(""), - Some(3), - None, - SelectionDirection::None, - ); - - textinput.insert_char('\u{10437}'); - assert_eq!(textinput.get_content(), "\u{10437}"); - textinput.insert_char('\u{10437}'); - assert_eq!(textinput.get_content(), "\u{10437}"); - textinput.insert_char('x'); - assert_eq!(textinput.get_content(), "\u{10437}x"); - textinput.insert_char('x'); - assert_eq!(textinput.get_content(), "\u{10437}x"); -} - -#[test] -fn test_single_line_textinput_with_max_length_inside_char() { - let mut textinput = TextInput::new( - Lines::Single, - DOMString::from("\u{10437}"), - DummyClipboardContext::new(""), - Some(1), - None, - SelectionDirection::None, - ); - - textinput.insert_char('x'); - assert_eq!(textinput.get_content(), "\u{10437}"); -} - -#[test] -fn test_single_line_textinput_with_max_length_doesnt_allow_appending_characters_after_max_length_is_reached() { - let mut textinput = TextInput::new( - Lines::Single, - DOMString::from("a"), - DummyClipboardContext::new(""), - Some(1), - None, - SelectionDirection::None, - ); - - textinput.insert_char('b'); - assert_eq!(textinput.get_content(), "a"); -} - -#[test] -fn test_textinput_delete_char() { - let mut textinput = text_input(Lines::Single, "abcdefg"); - textinput.adjust_horizontal(2, Selection::NotSelected); - textinput.delete_char(Direction::Backward); - assert_eq!(textinput.get_content(), "acdefg"); - - textinput.delete_char(Direction::Forward); - assert_eq!(textinput.get_content(), "adefg"); - - textinput.adjust_horizontal(2, Selection::Selected); - textinput.delete_char(Direction::Forward); - assert_eq!(textinput.get_content(), "afg"); - - let mut textinput = text_input(Lines::Single, "a🌠b"); - // Same as "Right" key - textinput.adjust_horizontal_by_one(Direction::Forward, Selection::NotSelected); - textinput.delete_char(Direction::Forward); - // Not splitting surrogate pairs. - assert_eq!(textinput.get_content(), "ab"); - - let mut textinput = text_input(Lines::Single, "abcdefg"); - textinput.set_selection_range(2, 2, SelectionDirection::None); - textinput.delete_char(Direction::Backward); - assert_eq!(textinput.get_content(), "acdefg"); -} - -#[test] -fn test_textinput_insert_char() { - let mut textinput = text_input(Lines::Single, "abcdefg"); - textinput.adjust_horizontal(2, Selection::NotSelected); - textinput.insert_char('a'); - assert_eq!(textinput.get_content(), "abacdefg"); - - textinput.adjust_horizontal(2, Selection::Selected); - textinput.insert_char('b'); - assert_eq!(textinput.get_content(), "ababefg"); - - let mut textinput = text_input(Lines::Single, "a🌠c"); - // Same as "Right" key - textinput.adjust_horizontal_by_one(Direction::Forward, Selection::NotSelected); - textinput.adjust_horizontal_by_one(Direction::Forward, Selection::NotSelected); - textinput.insert_char('b'); - // Not splitting surrogate pairs. - assert_eq!(textinput.get_content(), "a🌠bc"); -} - -#[test] -fn test_textinput_get_sorted_selection() { - let mut textinput = text_input(Lines::Single, "abcdefg"); - textinput.adjust_horizontal(2, Selection::NotSelected); - textinput.adjust_horizontal(2, Selection::Selected); - let (start, end) = textinput.sorted_selection_bounds(); - assert_eq!(start.index, 2); - assert_eq!(end.index, 4); - - textinput.clear_selection(); - - textinput.adjust_horizontal(-2, Selection::Selected); - let (start, end) = textinput.sorted_selection_bounds(); - assert_eq!(start.index, 2); - assert_eq!(end.index, 4); -} - -#[test] -fn test_textinput_replace_selection() { - let mut textinput = text_input(Lines::Single, "abcdefg"); - textinput.adjust_horizontal(2, Selection::NotSelected); - textinput.adjust_horizontal(2, Selection::Selected); - - textinput.replace_selection(DOMString::from("xyz")); - assert_eq!(textinput.get_content(), "abxyzefg"); -} - -#[test] -fn test_textinput_replace_selection_multibyte_char() { - let mut textinput = text_input(Lines::Single, "é"); - textinput.adjust_horizontal_by_one(Direction::Forward, Selection::Selected); - - textinput.replace_selection(DOMString::from("e")); - assert_eq!(textinput.get_content(), "e"); -} - -#[test] -fn test_textinput_current_line_length() { - let mut textinput = text_input(Lines::Multiple, "abc\nde\nf"); - assert_eq!(textinput.current_line_length(), 3); - - textinput.adjust_vertical(1, Selection::NotSelected); - assert_eq!(textinput.current_line_length(), 2); - - textinput.adjust_vertical(1, Selection::NotSelected); - assert_eq!(textinput.current_line_length(), 1); -} - -#[test] -fn test_textinput_adjust_vertical() { - let mut textinput = text_input(Lines::Multiple, "abc\nde\nf"); - textinput.adjust_horizontal(3, Selection::NotSelected); - textinput.adjust_vertical(1, Selection::NotSelected); - assert_eq!(textinput.edit_point().line, 1); - assert_eq!(textinput.edit_point().index, 2); - - textinput.adjust_vertical(-1, Selection::NotSelected); - assert_eq!(textinput.edit_point().line, 0); - assert_eq!(textinput.edit_point().index, 2); - - textinput.adjust_vertical(2, Selection::NotSelected); - assert_eq!(textinput.edit_point().line, 2); - assert_eq!(textinput.edit_point().index, 1); -} - -#[test] -fn test_textinput_adjust_vertical_multibyte() { - let mut textinput = text_input(Lines::Multiple, "áé\nae"); - - textinput.adjust_horizontal_by_one(Direction::Forward, Selection::NotSelected); - assert_eq!(textinput.edit_point().line, 0); - assert_eq!(textinput.edit_point().index, 2); - - textinput.adjust_vertical(1, Selection::NotSelected); - assert_eq!(textinput.edit_point().line, 1); - assert_eq!(textinput.edit_point().index, 1); -} - -#[test] -fn test_textinput_adjust_horizontal() { - let mut textinput = text_input(Lines::Multiple, "abc\nde\nf"); - textinput.adjust_horizontal(4, Selection::NotSelected); - assert_eq!(textinput.edit_point().line, 1); - assert_eq!(textinput.edit_point().index, 0); - - textinput.adjust_horizontal(1, Selection::NotSelected); - assert_eq!(textinput.edit_point().line, 1); - assert_eq!(textinput.edit_point().index, 1); - - textinput.adjust_horizontal(2, Selection::NotSelected); - assert_eq!(textinput.edit_point().line, 2); - assert_eq!(textinput.edit_point().index, 0); - - textinput.adjust_horizontal(-1, Selection::NotSelected); - assert_eq!(textinput.edit_point().line, 1); - assert_eq!(textinput.edit_point().index, 2); -} - -#[test] -fn test_textinput_adjust_horizontal_by_word() { - // Test basic case of movement word by word based on UAX#29 rules - let mut textinput = text_input(Lines::Single, "abc def"); - textinput.adjust_horizontal_by_word(Direction::Forward, Selection::NotSelected); - textinput.adjust_horizontal_by_word(Direction::Forward, Selection::NotSelected); - assert_eq!(textinput.edit_point().line, 0); - assert_eq!(textinput.edit_point().index, 7); - textinput.adjust_horizontal_by_word(Direction::Backward, Selection::NotSelected); - assert_eq!(textinput.edit_point().line, 0); - assert_eq!(textinput.edit_point().index, 4); - textinput.adjust_horizontal_by_word(Direction::Backward, Selection::NotSelected); - assert_eq!(textinput.edit_point().line, 0); - assert_eq!(textinput.edit_point().index, 0); - - // Test new line case of movement word by word based on UAX#29 rules - let mut textinput_2 = text_input(Lines::Multiple, "abc\ndef"); - textinput_2.adjust_horizontal_by_word(Direction::Forward, Selection::NotSelected); - textinput_2.adjust_horizontal_by_word(Direction::Forward, Selection::NotSelected); - assert_eq!(textinput_2.edit_point().line, 1); - assert_eq!(textinput_2.edit_point().index, 3); - textinput_2.adjust_horizontal_by_word(Direction::Backward, Selection::NotSelected); - assert_eq!(textinput_2.edit_point().line, 1); - assert_eq!(textinput_2.edit_point().index, 0); - textinput_2.adjust_horizontal_by_word(Direction::Backward, Selection::NotSelected); - assert_eq!(textinput_2.edit_point().line, 0); - assert_eq!(textinput_2.edit_point().index, 0); - - // Test non-standard sized characters case of movement word by word based on UAX#29 rules - let mut textinput_3 = text_input(Lines::Single, "áéc d🌠bc"); - textinput_3.adjust_horizontal_by_word(Direction::Forward, Selection::NotSelected); - assert_eq!(textinput_3.edit_point().line, 0); - assert_eq!(textinput_3.edit_point().index, 5); - textinput_3.adjust_horizontal_by_word(Direction::Forward, Selection::NotSelected); - assert_eq!(textinput_3.edit_point().line, 0); - assert_eq!(textinput_3.edit_point().index, 7); - textinput_3.adjust_horizontal_by_word(Direction::Forward, Selection::NotSelected); - assert_eq!(textinput_3.edit_point().line, 0); - assert_eq!(textinput_3.edit_point().index, 13); - textinput_3.adjust_horizontal_by_word(Direction::Backward, Selection::NotSelected); - assert_eq!(textinput_3.edit_point().line, 0); - assert_eq!(textinput_3.edit_point().index, 11); - textinput_3.adjust_horizontal_by_word(Direction::Backward, Selection::NotSelected); - assert_eq!(textinput_3.edit_point().line, 0); - assert_eq!(textinput_3.edit_point().index, 6); -} - -#[test] -fn test_textinput_adjust_horizontal_to_line_end() { - // Test standard case of movement to end based on UAX#29 rules - let mut textinput = text_input(Lines::Single, "abc def"); - textinput.adjust_horizontal_to_line_end(Direction::Forward, Selection::NotSelected); - assert_eq!(textinput.edit_point().line, 0); - assert_eq!(textinput.edit_point().index, 7); - - // Test new line case of movement to end based on UAX#29 rules - let mut textinput_2 = text_input(Lines::Multiple, "abc\ndef"); - textinput_2.adjust_horizontal_to_line_end(Direction::Forward, Selection::NotSelected); - assert_eq!(textinput_2.edit_point().line, 0); - assert_eq!(textinput_2.edit_point().index, 3); - textinput_2.adjust_horizontal_to_line_end(Direction::Forward, Selection::NotSelected); - assert_eq!(textinput_2.edit_point().line, 0); - assert_eq!(textinput_2.edit_point().index, 3); - textinput_2.adjust_horizontal_to_line_end(Direction::Backward, Selection::NotSelected); - assert_eq!(textinput_2.edit_point().line, 0); - assert_eq!(textinput_2.edit_point().index, 0); - - // Test non-standard sized characters case of movement to end based on UAX#29 rules - let mut textinput_3 = text_input(Lines::Single, "áéc d🌠bc"); - textinput_3.adjust_horizontal_to_line_end(Direction::Forward, Selection::NotSelected); - assert_eq!(textinput_3.edit_point().line, 0); - assert_eq!(textinput_3.edit_point().index, 13); - textinput_3.adjust_horizontal_to_line_end(Direction::Backward, Selection::NotSelected); - assert_eq!(textinput_3.edit_point().line, 0); - assert_eq!(textinput_3.edit_point().index, 0); -} - -#[test] -#[cfg(target_os = "macos")] -fn test_navigation_keyboard_shortcuts() { - let mut textinput = text_input(Lines::Multiple, "hello áéc"); - - // Test that CMD + Right moves to the end of the current line. - textinput.handle_keydown_aux(None, Key::Right, KeyModifiers::SUPER); - assert_eq!(textinput.edit_point().index, 11); - // Test that CMD + Right moves to the beginning of the current line. - textinput.handle_keydown_aux(None, Key::Left, KeyModifiers::SUPER); - assert_eq!(textinput.edit_point().index, 0); - // Test that CTRL + ALT + E moves to the end of the current line also. - textinput.handle_keydown_aux(None, Key::E, KeyModifiers::CONTROL | KeyModifiers::ALT); - assert_eq!(textinput.edit_point().index, 11); - // Test that CTRL + ALT + A moves to the beginning of the current line also. - textinput.handle_keydown_aux(None, Key::A, KeyModifiers::CONTROL | KeyModifiers::ALT); - assert_eq!(textinput.edit_point().index, 0); - - // Test that ALT + Right moves to the end of the word. - textinput.handle_keydown_aux(None, Key::Right, KeyModifiers::ALT); - assert_eq!(textinput.edit_point().index, 5); - // Test that CTRL + ALT + F moves to the end of the word also. - textinput.handle_keydown_aux(None, Key::F, KeyModifiers::CONTROL | KeyModifiers::ALT); - assert_eq!(textinput.edit_point().index, 11); - // Test that ALT + Left moves to the end of the word. - textinput.handle_keydown_aux(None, Key::Left, KeyModifiers::ALT); - assert_eq!(textinput.edit_point().index, 6); - // Test that CTRL + ALT + B moves to the end of the word also. - textinput.handle_keydown_aux(None, Key::B, KeyModifiers::CONTROL | KeyModifiers::ALT); - assert_eq!(textinput.edit_point().index, 0); -} - -#[test] -fn test_textinput_handle_return() { - let mut single_line_textinput = text_input(Lines::Single, "abcdef"); - single_line_textinput.adjust_horizontal(3, Selection::NotSelected); - single_line_textinput.handle_return(); - assert_eq!(single_line_textinput.get_content(), "abcdef"); - - let mut multi_line_textinput = text_input(Lines::Multiple, "abcdef"); - multi_line_textinput.adjust_horizontal(3, Selection::NotSelected); - multi_line_textinput.handle_return(); - assert_eq!(multi_line_textinput.get_content(), "abc\ndef"); -} - -#[test] -fn test_textinput_select_all() { - let mut textinput = text_input(Lines::Multiple, "abc\nde\nf"); - assert_eq!(textinput.edit_point().line, 0); - assert_eq!(textinput.edit_point().index, 0); - - textinput.select_all(); - assert_eq!(textinput.edit_point().line, 2); - assert_eq!(textinput.edit_point().index, 1); -} - -#[test] -fn test_textinput_get_content() { - let single_line_textinput = text_input(Lines::Single, "abcdefg"); - assert_eq!(single_line_textinput.get_content(), "abcdefg"); - - let multi_line_textinput = text_input(Lines::Multiple, "abc\nde\nf"); - assert_eq!(multi_line_textinput.get_content(), "abc\nde\nf"); -} - -#[test] -fn test_textinput_set_content() { - let mut textinput = text_input(Lines::Multiple, "abc\nde\nf"); - assert_eq!(textinput.get_content(), "abc\nde\nf"); - - textinput.set_content(DOMString::from("abc\nf")); - assert_eq!(textinput.get_content(), "abc\nf"); - - assert_eq!(textinput.edit_point().line, 0); - assert_eq!(textinput.edit_point().index, 0); - - textinput.adjust_horizontal(3, Selection::Selected); - assert_eq!(textinput.edit_point().line, 0); - assert_eq!(textinput.edit_point().index, 3); - textinput.set_content(DOMString::from("de")); - assert_eq!(textinput.get_content(), "de"); - assert_eq!(textinput.edit_point().line, 0); - assert_eq!(textinput.edit_point().index, 2); -} - -#[test] -fn test_clipboard_paste() { - #[cfg(target_os = "macos")] - const MODIFIERS: KeyModifiers = KeyModifiers::SUPER; - #[cfg(not(target_os = "macos"))] - const MODIFIERS: KeyModifiers = KeyModifiers::CONTROL; - - let mut textinput = TextInput::new(Lines::Single, - DOMString::from("defg"), - DummyClipboardContext::new("abc"), - None, - None, - SelectionDirection::None); - assert_eq!(textinput.get_content(), "defg"); - assert_eq!(textinput.edit_point().index, 0); - textinput.handle_keydown_aux(Some('v'), Key::V, MODIFIERS); - assert_eq!(textinput.get_content(), "abcdefg"); -} - -#[test] -fn test_textinput_cursor_position_correct_after_clearing_selection() { - let mut textinput = text_input(Lines::Single, "abcdef"); - - // Single line - Forward - textinput.adjust_horizontal(3, Selection::Selected); - textinput.adjust_horizontal(1, Selection::NotSelected); - assert_eq!(textinput.edit_point().index, 3); - - textinput.adjust_horizontal(-3, Selection::NotSelected); - textinput.adjust_horizontal(3, Selection::Selected); - textinput.adjust_horizontal_by_one(Direction::Forward, Selection::NotSelected); - assert_eq!(textinput.edit_point().index, 3); - - // Single line - Backward - textinput.adjust_horizontal(-3, Selection::NotSelected); - textinput.adjust_horizontal(3, Selection::Selected); - textinput.adjust_horizontal(-1, Selection::NotSelected); - assert_eq!(textinput.edit_point().index, 0); - - textinput.adjust_horizontal(-3, Selection::NotSelected); - textinput.adjust_horizontal(3, Selection::Selected); - textinput.adjust_horizontal_by_one(Direction::Backward, Selection::NotSelected); - assert_eq!(textinput.edit_point().index, 0); - - - let mut textinput = text_input(Lines::Multiple, "abc\nde\nf"); - - // Multiline - Forward - textinput.adjust_horizontal(4, Selection::Selected); - textinput.adjust_horizontal(1, Selection::NotSelected); - assert_eq!(textinput.edit_point().index, 0); - assert_eq!(textinput.edit_point().line, 1); - - textinput.adjust_horizontal(-4, Selection::NotSelected); - textinput.adjust_horizontal(4, Selection::Selected); - textinput.adjust_horizontal_by_one(Direction::Forward, Selection::NotSelected); - assert_eq!(textinput.edit_point().index, 0); - assert_eq!(textinput.edit_point().line, 1); - - // Multiline - Backward - textinput.adjust_horizontal(-4, Selection::NotSelected); - textinput.adjust_horizontal(4, Selection::Selected); - textinput.adjust_horizontal(-1, Selection::NotSelected); - assert_eq!(textinput.edit_point().index, 0); - assert_eq!(textinput.edit_point().line, 0); - - textinput.adjust_horizontal(-4, Selection::NotSelected); - textinput.adjust_horizontal(4, Selection::Selected); - textinput.adjust_horizontal_by_one(Direction::Backward, Selection::NotSelected); - assert_eq!(textinput.edit_point().index, 0); - assert_eq!(textinput.edit_point().line, 0); -} - - -#[test] -fn test_textinput_set_selection_with_direction() { - let mut textinput = text_input(Lines::Single, "abcdef"); - textinput.set_selection_range(2, 6, SelectionDirection::Forward); - assert_eq!(textinput.edit_point().line, 0); - assert_eq!(textinput.edit_point().index, 6); - assert_eq!(textinput.selection_direction(), SelectionDirection::Forward); - - assert!(textinput.selection_origin().is_some()); - assert_eq!(textinput.selection_origin().unwrap().line, 0); - assert_eq!(textinput.selection_origin().unwrap().index, 2); - - textinput.set_selection_range(2, 6, SelectionDirection::Backward); - assert_eq!(textinput.edit_point().line, 0); - assert_eq!(textinput.edit_point().index, 2); - assert_eq!(textinput.selection_direction(), SelectionDirection::Backward); - - assert!(textinput.selection_origin().is_some()); - assert_eq!(textinput.selection_origin().unwrap().line, 0); - assert_eq!(textinput.selection_origin().unwrap().index, 6); - - textinput = text_input(Lines::Multiple, "\n\n"); - textinput.set_selection_range(0, 1, SelectionDirection::Forward); - assert_eq!(textinput.edit_point().line, 1); - assert_eq!(textinput.edit_point().index, 0); - assert_eq!(textinput.selection_direction(), SelectionDirection::Forward); - - assert!(textinput.selection_origin().is_some()); - assert_eq!(textinput.selection_origin().unwrap().line, 0); - assert_eq!(textinput.selection_origin().unwrap().index, 0); - - textinput = text_input(Lines::Multiple, "\n"); - textinput.set_selection_range(0, 1, SelectionDirection::Forward); - assert_eq!(textinput.edit_point().line, 1); - assert_eq!(textinput.edit_point().index, 0); - assert_eq!(textinput.selection_direction(), SelectionDirection::Forward); - - assert!(textinput.selection_origin().is_some()); - assert_eq!(textinput.selection_origin().unwrap().line, 0); - assert_eq!(textinput.selection_origin().unwrap().index, 0); - -} - -#[test] -fn test_textinput_unicode_handling() { - let mut textinput = text_input(Lines::Single, "éèùµ$£"); - assert_eq!(textinput.edit_point().index, 0); - textinput.set_edit_point_index(1); - assert_eq!(textinput.edit_point().index, 2); - textinput.set_edit_point_index(4); - assert_eq!(textinput.edit_point().index, 8); -} - -#[test] -fn test_selection_bounds() { - let mut textinput = text_input(Lines::Single, "abcdef"); - - assert_eq!(TextPoint { line: 0, index: 0 }, textinput.selection_origin_or_edit_point()); - assert_eq!(TextPoint { line: 0, index: 0 }, textinput.selection_start()); - assert_eq!(TextPoint { line: 0, index: 0 }, textinput.selection_end()); - - textinput.set_selection_range(2, 5, SelectionDirection::Forward); - assert_eq!(TextPoint { line: 0, index: 2 }, textinput.selection_origin_or_edit_point()); - assert_eq!(TextPoint { line: 0, index: 2 }, textinput.selection_start()); - assert_eq!(TextPoint { line: 0, index: 5 }, textinput.selection_end()); - assert_eq!(2, textinput.selection_start_offset()); - assert_eq!(5, textinput.selection_end_offset()); - - textinput.set_selection_range(3, 6, SelectionDirection::Backward); - assert_eq!(TextPoint { line: 0, index: 6 }, textinput.selection_origin_or_edit_point()); - assert_eq!(TextPoint { line: 0, index: 3 }, textinput.selection_start()); - assert_eq!(TextPoint { line: 0, index: 6 }, textinput.selection_end()); - assert_eq!(3, textinput.selection_start_offset()); - assert_eq!(6, textinput.selection_end_offset()); - - textinput = text_input(Lines::Multiple, "\n\n"); - textinput.set_selection_range(0, 1, SelectionDirection::Forward); - assert_eq!(TextPoint { line: 0, index: 0 }, textinput.selection_origin_or_edit_point()); - assert_eq!(TextPoint { line: 0, index: 0 }, textinput.selection_start()); - assert_eq!(TextPoint { line: 1, index: 0 }, textinput.selection_end()); - -} diff --git a/servo/tests/unit/script_plugins/Cargo.toml b/servo/tests/unit/script_plugins/Cargo.toml deleted file mode 100644 index 8a41b62aa8fc..000000000000 --- a/servo/tests/unit/script_plugins/Cargo.toml +++ /dev/null @@ -1,12 +0,0 @@ -[package] -name = "script_plugins_tests" -version = "0.0.1" -authors = ["The Servo Project Developers"] -license = "MPL-2.0" - -[lib] -path = "lib.rs" -test = false - -[dependencies] -script_plugins = {path = "../../../components/script_plugins"} diff --git a/servo/tests/unit/script_plugins/lib.rs b/servo/tests/unit/script_plugins/lib.rs deleted file mode 100644 index 35a1c0dff11f..000000000000 --- a/servo/tests/unit/script_plugins/lib.rs +++ /dev/null @@ -1,63 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -pub mod unrooted_must_root { - /** - ``` - #![feature(plugin)] - #![plugin(script_plugins)] - - #[must_root] struct Foo(i32); - #[must_root] struct Bar(Foo); - - fn foo1(_: &Foo) {} - fn foo2(_: &()) -> &Foo { unimplemented!() } - - fn main() {} - ``` - */ - pub fn ok() {} - - /** - ```compile_fail - #![feature(plugin)] - #![plugin(script_plugins)] - - #[must_root] struct Foo(i32); - struct Bar(Foo); - - fn main() {} - ``` - */ - pub fn struct_field() {} - - /** - ```compile_fail - #![feature(plugin)] - #![plugin(script_plugins)] - - #[must_root] struct Foo(i32); - - fn foo1(_: Foo) {} - - fn main() {} - ``` - */ - pub fn parameter() {} - - /** - ```compile_fail - #![feature(plugin)] - #![plugin(script_plugins)] - - #[must_root] struct Foo(i32); - - fn foo2() -> Foo { unimplemented!() } - - fn main() {} - ``` - */ - pub fn return_type() {} - -} diff --git a/taskcluster/ci/release-secondary-update-verify-config/kind.yml b/taskcluster/ci/release-secondary-update-verify-config/kind.yml index 049ce8acd312..e63f67d95b71 100644 --- a/taskcluster/ci/release-secondary-update-verify-config/kind.yml +++ b/taskcluster/ci/release-secondary-update-verify-config/kind.yml @@ -28,6 +28,7 @@ job-defaults: sparse-profile: mozharness extra: app-name: browser + branch-prefix: mozilla product: firefox archive-prefix: by-project: diff --git a/taskcluster/ci/release-update-verify-config/kind.yml b/taskcluster/ci/release-update-verify-config/kind.yml index 45d6dc0e71fe..0d7bed999ff9 100644 --- a/taskcluster/ci/release-update-verify-config/kind.yml +++ b/taskcluster/ci/release-update-verify-config/kind.yml @@ -27,6 +27,7 @@ job-defaults: sparse-profile: mozharness extra: app-name: browser + branch-prefix: mozilla archive-prefix: by-project: birch: "http://ftp.stage.mozaws.net/pub" diff --git a/taskcluster/ci/release-version-bump/kind.yml b/taskcluster/ci/release-version-bump/kind.yml index 566044996918..187a8ed418dc 100644 --- a/taskcluster/ci/release-version-bump/kind.yml +++ b/taskcluster/ci/release-version-bump/kind.yml @@ -16,7 +16,13 @@ job-defaults: description: Release Promotion version bump/tag run-on-projects: [] shipping-phase: ship - worker-type: scriptworker-prov-v1/treescript-v1 + worker-type: + by-project: + mozilla-(beta|release|esr.*): scriptworker-prov-v1/treescript-v1 + maple: scriptworker-prov-v1/treescript-v1 + birch: scriptworker-prov-v1/treescript-v1 + jamun: scriptworker-prov-v1/treescript-v1 + default: scriptworker-prov-v1/treescript-dev worker: implementation: treescript tag: true diff --git a/taskcluster/taskgraph/transforms/release_version_bump.py b/taskcluster/taskgraph/transforms/release_version_bump.py index f03d80a1eb24..e9d9684cdf0d 100644 --- a/taskcluster/taskgraph/transforms/release_version_bump.py +++ b/taskcluster/taskgraph/transforms/release_version_bump.py @@ -18,7 +18,8 @@ def handle_keyed_by(config, tasks): """Resolve fields that can be keyed by platform, etc.""" fields = [ 'worker.push', - 'worker.bump-files' + 'worker.bump-files', + 'worker-type', ] for task in tasks: for field in fields: diff --git a/taskcluster/taskgraph/transforms/task.py b/taskcluster/taskgraph/transforms/task.py index 48ec056ca03c..bf0c2c47ff50 100644 --- a/taskcluster/taskgraph/transforms/task.py +++ b/taskcluster/taskgraph/transforms/task.py @@ -31,6 +31,7 @@ from taskgraph.util.schema import ( from taskgraph.util.scriptworker import ( BALROG_ACTIONS, get_release_config, + add_scope_prefix, ) from voluptuous import Any, Required, Optional, Extra from taskgraph import GECKO, MAX_DEPENDENCIES @@ -547,6 +548,7 @@ task_description_schema = Schema({ Required('tag'): bool, Required('bump'): bool, Optional('bump-files'): [basestring], + Optional('repo-param-prefix'): basestring, Required('force-dry-run', default=True): bool, Required('push', default=False): bool }), @@ -597,7 +599,15 @@ TREEHERDER_ROUTE_ROOT = 'tc-treeherder' def get_branch_rev(config): - return config.params['{}head_rev'.format(config.graph_config['project-repo-param-prefix'])] + return config.params['{}head_rev'.format( + config.graph_config['project-repo-param-prefix'] + )] + + +def get_branch_repo(config): + return config.params['{}head_repository'.format( + config.graph_config['project-repo-param-prefix'], + )] COALESCE_KEY = '{project}.{job-identifier}' @@ -1129,10 +1139,10 @@ def build_treescript_payload(config, task, task_def): ] tag_info = { 'tags': tag_names, - 'revision': config.params['head_rev'] + 'revision': config.params['{}head_rev'.format(worker.get('repo-param-prefix', ''))], } task_def['payload']['tag_info'] = tag_info - task_def['scopes'].append('project:releng:treescript:action:tagging') + task_def['scopes'].append(add_scope_prefix(config, 'treescript:action:tagging')) if worker['bump']: if not worker['bump-files']: @@ -1142,10 +1152,10 @@ def build_treescript_payload(config, task, task_def): bump_info['next_version'] = release_config['next_version'] bump_info['files'] = worker['bump-files'] task_def['payload']['version_bump_info'] = bump_info - task_def['scopes'].append('project:releng:treescript:action:version_bump') + task_def['scopes'].append(add_scope_prefix(config, 'treescript:action:version_bump')) if worker['push']: - task_def['scopes'].append('project:releng:treescript:action:push') + task_def['scopes'].append(add_scope_prefix(config, 'treescript:action:push')) if worker.get('force-dry-run'): task_def['payload']['dry_run'] = True diff --git a/taskcluster/taskgraph/transforms/update_verify_config.py b/taskcluster/taskgraph/transforms/update_verify_config.py index cb7ce7240845..fe0a17fc8aae 100644 --- a/taskcluster/taskgraph/transforms/update_verify_config.py +++ b/taskcluster/taskgraph/transforms/update_verify_config.py @@ -12,6 +12,10 @@ import urlparse from taskgraph.transforms.base import TransformSequence from taskgraph.util.schema import resolve_keyed_by from taskgraph.util.scriptworker import get_release_config +from taskgraph.transforms.task import ( + get_branch_repo, + get_branch_rev, +) transforms = TransformSequence() @@ -62,16 +66,17 @@ def add_command(config, tasks): "--product", task["extra"]["product"], "--stage-product", task["shipping-product"], "--app-name", task["extra"]["app-name"], + "--branch-prefix", task["extra"]["branch-prefix"], "--platform", task["extra"]["platform"], "--to-version", release_config["version"], "--to-app-version", release_config["appVersion"], "--to-build-number", str(release_config["build_number"]), "--to-buildid", config.params["moz_build_date"], - "--to-revision", config.params["head_rev"], + "--to-revision", get_branch_rev(config), "--output-file", "update-verify.cfg", ] - repo_path = urlparse.urlsplit(config.params["head_repository"]).path.lstrip("/") + repo_path = urlparse.urlsplit(get_branch_repo(config)).path.lstrip("/") command.extend(["--repo-path", repo_path]) if release_config.get("partial_versions"): diff --git a/testing/marionette/element.js b/testing/marionette/element.js index 2949dca5d695..32e68df2729b 100644 --- a/testing/marionette/element.js +++ b/testing/marionette/element.js @@ -359,7 +359,7 @@ function find_(container, strategy, selector, searchFn, // DOMElement, which will refer to :root in case of a DOMDocument. case element.Strategy.Anon: case element.Strategy.AnonAttribute: - if (rootNode instanceof Ci.nsIDOMDocument) { + if (rootNode.nodeType == rootNode.DOCUMENT_NODE) { startNode = rootNode.documentElement; } break; diff --git a/testing/mozharness/scripts/release/update-verify-config-creator.py b/testing/mozharness/scripts/release/update-verify-config-creator.py index 0d277a4993a5..5a35f604f915 100644 --- a/testing/mozharness/scripts/release/update-verify-config-creator.py +++ b/testing/mozharness/scripts/release/update-verify-config-creator.py @@ -52,6 +52,10 @@ class UpdateVerifyConfigCreator(BaseScript): "dest": "app_name", "help": "App name being tested. Eg: browser", }], + [["--branch-prefix"], { + "dest": "branch_prefix", + "help": "Prefix of release branch names. Eg: mozilla, comm", + }], [["--channel"], { "dest": "channel", "help": "Channel to run update verify against", @@ -87,6 +91,7 @@ class UpdateVerifyConfigCreator(BaseScript): }], [["--partial-version"], { "dest": "partial_versions", + "default": [], "action": "append", "help": "A previous release version that is expected to receive a partial update. " "Eg: 59.0b4. May be specified multiple times." @@ -219,11 +224,11 @@ class UpdateVerifyConfigCreator(BaseScript): # at the time of writing. branch = None if release_info["category"] == "dev": - branch = "releases/mozilla-beta" + branch = "releases/{}-beta".format(self.config['branch_prefix']) elif release_info["category"] == "esr": - branch = "releases/mozilla-esr{}".format(version[:2]) + branch = "releases/{}-esr{}".format(self.config['branch_prefix'], version[:2]) elif release_info["category"] in ("major", "stability"): - branch = "releases/mozilla-release" + branch = "releases/{}-release".format(self.config['branch_prefix']) if not branch: raise Exception("Cannot determine branch, cannot continue!") diff --git a/testing/web-platform/meta/MANIFEST.json b/testing/web-platform/meta/MANIFEST.json index 2fa9c2a35fc0..d66a968ed309 100644 --- a/testing/web-platform/meta/MANIFEST.json +++ b/testing/web-platform/meta/MANIFEST.json @@ -327024,6 +327024,12 @@ {} ] ], + "css/cssom/at-namespace.html": [ + [ + "/css/cssom/at-namespace.html", + {} + ] + ], "css/cssom/computed-style-001.html": [ [ "/css/cssom/computed-style-001.html", @@ -546001,6 +546007,10 @@ "0a1cd8ed56ac3a5b1a9556835d94fb80325199bf", "testharness" ], + "css/cssom/at-namespace.html": [ + "96da2dd244e9e19ff8ca1ca81b06c3ebdcee8267", + "testharness" + ], "css/cssom/computed-style-001.html": [ "0331a648e6b0d56f0e7365f1ff7d991ea77ce3e4", "testharness" diff --git a/testing/web-platform/meta/service-workers/cache-storage/serviceworker/cache-put.https.html.ini b/testing/web-platform/meta/service-workers/cache-storage/serviceworker/cache-put.https.html.ini deleted file mode 100644 index 43583c6adf39..000000000000 --- a/testing/web-platform/meta/service-workers/cache-storage/serviceworker/cache-put.https.html.ini +++ /dev/null @@ -1,4 +0,0 @@ -[cache-put.https.html] - [Cache.put with 206 response] - expected: FAIL - diff --git a/testing/web-platform/meta/service-workers/cache-storage/window/cache-put.https.html.ini b/testing/web-platform/meta/service-workers/cache-storage/window/cache-put.https.html.ini deleted file mode 100644 index 43583c6adf39..000000000000 --- a/testing/web-platform/meta/service-workers/cache-storage/window/cache-put.https.html.ini +++ /dev/null @@ -1,4 +0,0 @@ -[cache-put.https.html] - [Cache.put with 206 response] - expected: FAIL - diff --git a/testing/web-platform/meta/service-workers/cache-storage/worker/cache-put.https.html.ini b/testing/web-platform/meta/service-workers/cache-storage/worker/cache-put.https.html.ini deleted file mode 100644 index 43583c6adf39..000000000000 --- a/testing/web-platform/meta/service-workers/cache-storage/worker/cache-put.https.html.ini +++ /dev/null @@ -1,4 +0,0 @@ -[cache-put.https.html] - [Cache.put with 206 response] - expected: FAIL - diff --git a/testing/web-platform/meta/webdriver/tests/new_session/create_alwaysMatch.py.ini b/testing/web-platform/meta/webdriver/tests/new_session/create_alwaysMatch.py.ini index 770708f931e4..8a8f63934dce 100644 --- a/testing/web-platform/meta/webdriver/tests/new_session/create_alwaysMatch.py.ini +++ b/testing/web-platform/meta/webdriver/tests/new_session/create_alwaysMatch.py.ini @@ -1,6 +1,4 @@ [create_alwaysMatch.py] - expected: - if webrender: TIMEOUT [test_valid[timeouts-value10\]] expected: FAIL diff --git a/testing/web-platform/meta/webdriver/tests/new_session/create_firstMatch.py.ini b/testing/web-platform/meta/webdriver/tests/new_session/create_firstMatch.py.ini index c45c61214330..afc8153db3f3 100644 --- a/testing/web-platform/meta/webdriver/tests/new_session/create_firstMatch.py.ini +++ b/testing/web-platform/meta/webdriver/tests/new_session/create_firstMatch.py.ini @@ -1,6 +1,4 @@ [create_firstMatch.py] - expected: - if webrender: TIMEOUT [test_valid[timeouts-value10\]] expected: FAIL diff --git a/testing/web-platform/tests/css/cssom/at-namespace.html b/testing/web-platform/tests/css/cssom/at-namespace.html new file mode 100644 index 000000000000..04a8a2289aa6 --- /dev/null +++ b/testing/web-platform/tests/css/cssom/at-namespace.html @@ -0,0 +1,29 @@ + +CSS Test: @namespace in CSSOM is not severely broken + + + + + + +
Should be green
+ + diff --git a/testing/web-platform/tests/css/cssom/insertRule-charset-no-index.html b/testing/web-platform/tests/css/cssom/insertRule-charset-no-index.html index b94dc11afae7..16f2358dc2d8 100644 --- a/testing/web-platform/tests/css/cssom/insertRule-charset-no-index.html +++ b/testing/web-platform/tests/css/cssom/insertRule-charset-no-index.html @@ -19,7 +19,7 @@ sheet.insertRule("p { color: green; }"); assert_equals(sheet.cssRules.length, 1); assert_equals(sheet.cssRules.item(0).cssText, "p { color: green; }"); - }, "inserRule with charset and omitted index argument"); + }, "insertRule with charset and omitted index argument"); test(function() { assert_equals(sheet.cssRules.length, 1); diff --git a/testing/web-platform/tests/css/cssom/insertRule-import-no-index.html b/testing/web-platform/tests/css/cssom/insertRule-import-no-index.html index c97d39494870..ad3622f86aaa 100644 --- a/testing/web-platform/tests/css/cssom/insertRule-import-no-index.html +++ b/testing/web-platform/tests/css/cssom/insertRule-import-no-index.html @@ -20,7 +20,7 @@ assert_equals(sheet.cssRules.length, 1); assert_throws("HierarchyRequestError", function() { sheet.insertRule("p { color: green; }"); }); assert_equals(sheet.cssRules.length, 1); - }, "inserRule with import and omitted index argument"); + }, "insertRule with import and omitted index argument"); test(function() { assert_equals(sheet.cssRules.length, 1); diff --git a/testing/web-platform/tests/css/cssom/insertRule-namespace-no-index.html b/testing/web-platform/tests/css/cssom/insertRule-namespace-no-index.html index 8a3315d86061..c1628eed85f9 100644 --- a/testing/web-platform/tests/css/cssom/insertRule-namespace-no-index.html +++ b/testing/web-platform/tests/css/cssom/insertRule-namespace-no-index.html @@ -22,7 +22,7 @@ assert_equals(sheet.cssRules.length, 3); assert_throws("HierarchyRequestError", function() { sheet.insertRule("p { color: green; }"); }); assert_equals(sheet.cssRules.length, 3); - }, "inserRule with namespace and omitted index argument"); + }, "insertRule with namespace and omitted index argument"); test(function() { assert_equals(sheet.cssRules.length, 3); @@ -34,7 +34,7 @@ assert_equals(sheet.cssRules.length, 3); sheet.insertRule("@import url(\"support/a-green.css\");"); assert_equals(sheet.cssRules.length, 4); - }, "inserRule with namespace and omitted index argument should insert import"); + }, "insertRule with namespace and omitted index argument should insert import"); diff --git a/testing/web-platform/tests/css/cssom/insertRule-no-index.html b/testing/web-platform/tests/css/cssom/insertRule-no-index.html index c9704b7475a5..b4370bd080cf 100644 --- a/testing/web-platform/tests/css/cssom/insertRule-no-index.html +++ b/testing/web-platform/tests/css/cssom/insertRule-no-index.html @@ -22,7 +22,7 @@ sheet.insertRule("p { color: green; }"); assert_equals(sheet.cssRules.length, 2); assert_equals(sheet.cssRules.item(0).cssText, "p { color: green; }"); - }, "inserRule with omitted index argument"); + }, "insertRule with omitted index argument"); test(function() { assert_equals(sheet.cssRules.length, 2); diff --git a/testing/xpcshell/head.js b/testing/xpcshell/head.js index 5ff70321a1e2..42e036c65479 100644 --- a/testing/xpcshell/head.js +++ b/testing/xpcshell/head.js @@ -1005,7 +1005,7 @@ function do_load_manifest(path) { * @param aPath File path to the document. * @param aType Content type to use in DOMParser. * - * @return nsIDOMDocument from the file. + * @return Document from the file. */ function do_parse_document(aPath, aType) { switch (aType) { diff --git a/toolkit/components/extensions/test/xpcshell/test_ext_ipcBlob.js b/toolkit/components/extensions/test/xpcshell/test_ext_ipcBlob.js new file mode 100644 index 000000000000..c42cc4640e7b --- /dev/null +++ b/toolkit/components/extensions/test/xpcshell/test_ext_ipcBlob.js @@ -0,0 +1,138 @@ +"use strict"; + +const server = createHttpServer(); +server.registerDirectory("/data/", do_get_file("data")); + +const BASE_URL = `http://localhost:${server.identity.primaryPort}/data`; + +// ExtensionContent.jsm needs to know when it's running from xpcshell, +// to use the right timeout for content scripts executed at document_idle. +ExtensionTestUtils.mockAppInfo(); + +add_task(async function test_parent_to_child() { + async function background() { + const dbName = "broken-blob"; + const dbStore = "blob-store"; + const dbVersion = 1; + const blobContent = "Hello World!"; + + let db = await new Promise((resolve, reject) => { + let dbOpen = indexedDB.open(dbName, dbVersion); + dbOpen.onerror = event => { + browser.test.fail(`Error opening the DB: ${event.target.error}`); + browser.test.notifyFail("test-completed"); + reject(); + }; + dbOpen.onsuccess = event => { + resolve(event.target.result); + }; + dbOpen.onupgradeneeded = event => { + let dbobj = event.target.result; + dbobj.onerror = error => { + browser.test.fail(`Error updating the DB: ${error.target.error}`); + browser.test.notifyFail("test-completed"); + reject(); + }; + dbobj.createObjectStore(dbStore); + }; + }); + + async function save(blob) { + let txn = db.transaction([dbStore], "readwrite"); + let store = txn.objectStore(dbStore); + let req = store.put(blob, "key"); + + return new Promise((resolve, reject) => { + req.onsuccess = () => { + resolve(); + }; + req.onerror = event => { + browser.test.fail(`Error saving the blob into the DB: ${event.target.error}`); + browser.test.notifyFail("test-completed"); + reject(); + }; + }); + } + + async function load() { + let txn = db.transaction([dbStore], "readonly"); + let store = txn.objectStore(dbStore); + let req = store.getAll(); + + return new Promise((resolve, reject) => { + req.onsuccess = () => resolve(req.result); + req.onerror = () => reject(req.error); + }).then(loadDetails => { + let blobs = []; + loadDetails.forEach(details => { + blobs.push(details); + }); + return blobs[0]; + }).catch(err => { + browser.test.fail(`Error loading the blob from the DB: ${err} :: ${err.stack}`); + browser.test.notifyFail("test-completed"); + }); + } + + browser.test.log("Blob creation"); + await save(new Blob([blobContent])); + let blob = await load(); + + db.close(); + + browser.runtime.onMessage.addListener(([msg, what]) => { + browser.test.log("Message received from content: " + msg); + if (msg == "script-ready") { + return Promise.resolve({blob}); + } + + if (msg == "script-value") { + browser.test.assertEq(blobContent, what, "blob content matches"); + browser.test.notifyPass("test-completed"); + return; + } + + browser.test.fail(`Unexpected test message received: ${msg}`); + }); + + browser.test.sendMessage("bg-ready"); + } + + function contentScriptStart() { + browser.runtime.sendMessage(["script-ready"], response => { + let reader = new FileReader(); + reader.addEventListener("load", () => { + browser.runtime.sendMessage(["script-value", reader.result]); + }, {once: true}); + reader.readAsText(response.blob); + }); + } + + let extensionData = { + background, + manifest: { + content_scripts: [ + { + "matches": ["http://*/*/file_sample.html"], + "js": ["content_script_start.js"], + "run_at": "document_start", + }, + ], + }, + files: { + "content_script_start.js": contentScriptStart, + }, + }; + + let extension = ExtensionTestUtils.loadExtension(extensionData); + await extension.startup(); + + await extension.awaitMessage("bg-ready"); + + let contentPage = await ExtensionTestUtils.loadContentPage(`${BASE_URL}/file_sample.html`); + + await extension.awaitFinish("test-completed"); + + await contentPage.close(); + await extension.unload(); +}); diff --git a/toolkit/components/extensions/test/xpcshell/xpcshell.ini b/toolkit/components/extensions/test/xpcshell/xpcshell.ini index 1641e5b957af..abed2bbd7e90 100644 --- a/toolkit/components/extensions/test/xpcshell/xpcshell.ini +++ b/toolkit/components/extensions/test/xpcshell/xpcshell.ini @@ -49,6 +49,7 @@ tags = webextensions in-process-webextensions [test_ext_unknown_permissions.js] [test_locale_converter.js] [test_locale_data.js] +[test_ext_ipcBlob.js] [test_ext_runtime_sendMessage_args.js] diff --git a/toolkit/content/contentAreaUtils.js b/toolkit/content/contentAreaUtils.js index 5b3712e416e8..dc758c89731e 100644 --- a/toolkit/content/contentAreaUtils.js +++ b/toolkit/content/contentAreaUtils.js @@ -180,9 +180,9 @@ function saveBrowser(aBrowser, aSkipPrompt, aOuterWindowID = 0) { } // Saves a document; aDocument can be an nsIWebBrowserPersistDocument -// (see saveBrowser, above) or an nsIDOMDocument. +// (see saveBrowser, above) or a Document. // -// aDocument can also be a CPOW for a remote nsIDOMDocument, in which +// aDocument can also be a CPOW for a remote Document, in which // case "save as" modes that serialize the document's DOM are // unavailable. This is a temporary measure for the "Save Frame As" // command (bug 1141337) and pre-e10s add-ons. @@ -197,7 +197,7 @@ function saveDocument(aDocument, aSkipPrompt) { // nsIWebBrowserPersistDocument exposes these directly. contentDisposition = aDocument.contentDisposition; cacheKey = aDocument.cacheKey; - } else if (aDocument instanceof Ci.nsIDOMDocument) { + } else if (aDocument.nodeType == 9 /* DOCUMENT_NODE */) { // Otherwise it's an actual nsDocument (and possibly a CPOW). // We want to use cached data because the document is currently visible. let ifreq = @@ -406,7 +406,7 @@ function internalSave(aURL, aDocument, aDefaultFileName, aContentDisposition, let isPrivate = aIsContentWindowPrivate; if (isPrivate === undefined) { - isPrivate = aInitiatingDocument instanceof Ci.nsIDOMDocument + isPrivate = aInitiatingDocument.nodeType == 9 /* DOCUMENT_NODE */ ? PrivateBrowsingUtils.isContentWindowPrivate(aInitiatingDocument.defaultView) : aInitiatingDocument.isPrivate; } diff --git a/xpfe/appshell/nsXULWindow.cpp b/xpfe/appshell/nsXULWindow.cpp index e4e19eeb9784..2552469a9b47 100644 --- a/xpfe/appshell/nsXULWindow.cpp +++ b/xpfe/appshell/nsXULWindow.cpp @@ -448,9 +448,6 @@ NS_IMETHODIMP nsXULWindow::Create() NS_IMETHODIMP nsXULWindow::Destroy() { - MOZ_DIAGNOSTIC_ASSERT(!mSyncingAttributesToWidget, - "Destroying the window from SyncAttributesToWidget?"); - if (!mWindow) return NS_OK; @@ -1124,13 +1121,15 @@ void nsXULWindow::OnChromeLoaded() mChromeLoaded = true; ApplyChromeFlags(); SyncAttributesToWidget(); - SizeShell(); - - if (mShowAfterLoad) { - SetVisibility(true); - // At this point the window may have been closed during Show(), so - // nsXULWindow::Destroy may already have been called. Take care! + if (mWindow) { + SizeShell(); + if (mShowAfterLoad) { + SetVisibility(true); + } } + // At this point the window may have been closed already during Show() or + // SyncAttributesToWidget(), so nsXULWindow::Destroy may already have been + // called. Take care! } mPersistentAttributesMask |= PAD_POSITION | PAD_SIZE | PAD_MISC; } @@ -1550,9 +1549,6 @@ void nsXULWindow::SyncAttributesToWidget() if (!windowElement) return; - AutoRestore scope { mSyncingAttributesToWidget }; - mSyncingAttributesToWidget = true; - MOZ_DIAGNOSTIC_ASSERT(mWindow, "No widget on SyncAttributesToWidget?"); nsAutoString attr; @@ -2426,7 +2422,9 @@ nsXULWindow::BeforeStartLayout() ApplyChromeFlags(); LoadPersistentWindowState(); SyncAttributesToWidget(); - SizeShell(); + if (mWindow) { + SizeShell(); + } return NS_OK; } diff --git a/xpfe/appshell/nsXULWindow.h b/xpfe/appshell/nsXULWindow.h index 5735c1f68a5a..76aff72d4883 100644 --- a/xpfe/appshell/nsXULWindow.h +++ b/xpfe/appshell/nsXULWindow.h @@ -179,7 +179,6 @@ protected: // mDestroying is used to prevent reentry into into Destroy(), which can // otherwise happen due to script running as we tear down various things. bool mDestroying; - bool mSyncingAttributesToWidget = false; bool mRegistered; uint32_t mPersistentAttributesDirty; // persistentAttributes uint32_t mPersistentAttributesMask;