Publish Vulpes Preview 15 sources for desktop, Android and Tundra
Share Gaia assets and adapters, keep private profiles and development documents local, and update both public READMEs.
This commit is contained in:
parent
93e3a48004
commit
b38dea0597
25901 changed files with 9982925 additions and 369 deletions
198
gaia/shared/js/font_size_utils.js
Executable file
198
gaia/shared/js/font_size_utils.js
Executable file
|
|
@ -0,0 +1,198 @@
|
|||
/* jshint -W083 */
|
||||
|
||||
(function(exports) {
|
||||
'use strict';
|
||||
|
||||
/**
|
||||
* Utility functions for measuring and manipulating font sizes
|
||||
*/
|
||||
var FontSizeUtils = {
|
||||
|
||||
/**
|
||||
* Keep a cache of canvas contexts with a given font.
|
||||
* We do this because it is faster to create new canvases
|
||||
* than to re-set the font on existing contexts repeatedly.
|
||||
*/
|
||||
_cachedContexts: {},
|
||||
|
||||
/**
|
||||
* Grab or create a cached canvas context for a given fontSize/family pair.
|
||||
* @todo Add font-weight as a new dimension for caching.
|
||||
*
|
||||
* @param {Integer} fontSize The font size of the canvas we want.
|
||||
* @param {String} fontFamily The font family of the canvas we want.
|
||||
* @param {String} fontStyle The style of the font (default to italic).
|
||||
* @return {CanvasRenderingContext2D} A context with the specified font.
|
||||
*/
|
||||
_getCachedContext: function(fontSize, fontFamily, fontStyle) {
|
||||
// Default to italic style since this code is only ever used
|
||||
// by headers right now and header text is always italic.
|
||||
fontStyle = fontStyle || 'italic';
|
||||
|
||||
var cache = this._cachedContexts;
|
||||
var ctx = cache[fontSize] && cache[fontSize][fontFamily] ?
|
||||
cache[fontSize][fontFamily][fontStyle] : null;
|
||||
|
||||
if (!ctx) {
|
||||
var canvas = document.createElement('canvas');
|
||||
canvas.setAttribute('moz-opaque', 'true');
|
||||
canvas.setAttribute('width', '1');
|
||||
canvas.setAttribute('height', '1');
|
||||
|
||||
ctx = canvas.getContext('2d', { willReadFrequently: true });
|
||||
ctx.font = fontStyle + ' ' + fontSize + 'px ' + fontFamily;
|
||||
|
||||
// Populate the contexts cache.
|
||||
if (!cache[fontSize]) {
|
||||
cache[fontSize] = {};
|
||||
}
|
||||
if (!cache[fontSize][fontFamily]) {
|
||||
cache[fontSize][fontFamily] = {};
|
||||
}
|
||||
cache[fontSize][fontFamily][fontStyle] = ctx;
|
||||
}
|
||||
|
||||
return ctx;
|
||||
},
|
||||
|
||||
/**
|
||||
* Clear any current canvas contexts from the cache.
|
||||
*/
|
||||
resetCache: function() {
|
||||
this._cachedContexts = {};
|
||||
},
|
||||
|
||||
/**
|
||||
* Get the width of a string in pixels, given its fontSize and fontFamily.
|
||||
*
|
||||
* @param {String} string The string we are measuring.
|
||||
* @param {Integer} fontSize The size of the font to measure against.
|
||||
* @param {String} fontFamily The font family to measure against.
|
||||
* @param {String} fontStyle The style of the font (default to italic).
|
||||
* @return {Integer} The pixel width of the string with the given font.
|
||||
*/
|
||||
getFontWidth: function(string, fontSize, fontFamily, fontStyle) {
|
||||
var ctx = this._getCachedContext(fontSize, fontFamily, fontStyle);
|
||||
return ctx.measureText(string).width;
|
||||
},
|
||||
|
||||
/**
|
||||
* Get the maximum allowable fontSize for a string such that it will
|
||||
* not overflow past a maximum width.
|
||||
*
|
||||
* @param {String} string The string for which to check max font size.
|
||||
* @param {Array} allowedSizes A list of fontSizes allowed.
|
||||
* @param {String} fontFamily The font family of the string we're measuring.
|
||||
* @param {Integer} maxWidth The maximum number of pixels before overflow.
|
||||
* @return {Object} Dict containing fontSize, overflow and textWidth.
|
||||
*/
|
||||
getMaxFontSizeInfo: function(string, allowedSizes, fontFamily, maxWidth) {
|
||||
var fontSize;
|
||||
var resultWidth;
|
||||
var i = allowedSizes.length - 1;
|
||||
|
||||
do {
|
||||
fontSize = allowedSizes[i];
|
||||
resultWidth = this.getFontWidth(string, fontSize, fontFamily);
|
||||
i--;
|
||||
} while (resultWidth > maxWidth && i >= 0);
|
||||
|
||||
return {
|
||||
fontSize: fontSize,
|
||||
overflow: resultWidth > maxWidth,
|
||||
textWidth: resultWidth
|
||||
};
|
||||
},
|
||||
|
||||
/**
|
||||
* Last result of the overflow count computation. Every time we recompute
|
||||
* the overflow count we start from this value; if the string is larger
|
||||
* than the previous one this will cut down the number of computations, if
|
||||
* not we restart from 0.
|
||||
*/
|
||||
_overflowCountCache: -1,
|
||||
|
||||
/**
|
||||
* Get the amount of characters truncated from overflow ellipses.
|
||||
*
|
||||
* @param {String} string The string for which to check max font size.
|
||||
* @param {Integer} fontSize The font size of the string we are measuring.
|
||||
* @param {String} fontFamily The font family of the string we're measuring.
|
||||
* @param {Integer} maxWidth The maximum number of pixels before overflow.
|
||||
*/
|
||||
getOverflowCount: function(string, fontSize, fontFamily, maxWidth) {
|
||||
var substring;
|
||||
var resultWidth;
|
||||
var overflowCount = -1;
|
||||
|
||||
// If the new string is longer than the cached result of the previous
|
||||
// call, and if the calculation yields a coherent result then start from
|
||||
// the cached value to speed up the calculation. */
|
||||
if (string.length > this._overflowCountCache) {
|
||||
substring = string.substr(0, string.length - this._overflowCountCache);
|
||||
resultWidth = this.getFontWidth(substring, fontSize, fontFamily);
|
||||
|
||||
if (resultWidth > maxWidth) {
|
||||
overflowCount = this._overflowCountCache;
|
||||
}
|
||||
}
|
||||
|
||||
do {
|
||||
overflowCount++;
|
||||
substring = string.substr(0, string.length - overflowCount);
|
||||
resultWidth = this.getFontWidth(substring, fontSize, fontFamily);
|
||||
} while (substring.length > 0 && resultWidth > maxWidth);
|
||||
|
||||
this._overflowCountCache = overflowCount;
|
||||
return overflowCount;
|
||||
},
|
||||
|
||||
/**
|
||||
* Get an element's content width disregarding its box model sizing.
|
||||
*
|
||||
* @param {HTMLElement|Object} HTML element, or style object.
|
||||
* @returns {Number} width in pixels of elements content.
|
||||
*/
|
||||
getContentWidth: function(style) {
|
||||
var width = parseInt(style.width, 10);
|
||||
if (style.boxSizing === 'border-box') {
|
||||
width -= (parseInt(style.paddingRight, 10) +
|
||||
parseInt(style.paddingLeft, 10));
|
||||
}
|
||||
return width;
|
||||
},
|
||||
|
||||
/**
|
||||
* Get an element's style properies.
|
||||
*
|
||||
* @param {HTMLElement} element The element from which to fetch style.
|
||||
* @return {Object} A dictionary containing element's style properties.
|
||||
*/
|
||||
getStyleProperties: function(element) {
|
||||
var style = window.getComputedStyle(element);
|
||||
var contentWidth = this.getContentWidth(style);
|
||||
if (isNaN(contentWidth)) {
|
||||
contentWidth = 0;
|
||||
}
|
||||
|
||||
return {
|
||||
fontFamily: style.fontFamily,
|
||||
contentWidth: contentWidth,
|
||||
paddingRight: parseInt(style.paddingRight, 10),
|
||||
paddingLeft: parseInt(style.paddingLeft, 10),
|
||||
offsetLeft: element.offsetLeft
|
||||
};
|
||||
},
|
||||
|
||||
/**
|
||||
* Cache and return the width of the inner window.
|
||||
*
|
||||
* @return {Integer} The width of the inner window in pixels.
|
||||
*/
|
||||
getWindowWidth: function() {
|
||||
return window.innerWidth;
|
||||
}
|
||||
};
|
||||
|
||||
exports.FontSizeUtils = FontSizeUtils;
|
||||
}(this));
|
||||
Loading…
Reference in a new issue