Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 | 530x 530x 530x 453x 453x 453x 453x 453x 453x 453x 453x 453x 453x 453x 453x 453x 1x 1x 1x 453x 452x 452x 453x 453x 453x 453x 9984633x 453x 453x 453x 16782878x 453x 453x 453x 453x 24324x 3504650x 3504650x 453x 453x 453x 77x 532x 1x 531x 1x 530x 530x 530x 530x 530x 530x 530x 530x 530x 530x 530x 530x 530x 530x 1x 1x 530x 530x 530x 530x 530x 530x 530x 530x 530x 530x 530x 530x 530x 530x 530x 530x 530x 530x 530x 530x 530x 530x 524x 524x 530x 1x 1x 1x 530x 529x 529x 529x 530x | import Color from "./Color.js";
import Frozen from "./Frozen.js";
import defined from "./defined.js";
import DeveloperError from "./DeveloperError.js";
function measureText(context2D, textString, font, stroke, fill) {
const metrics = context2D.measureText(textString);
const isSpace = !/\S/.test(textString);
if (!isSpace) {
const fontSize = document.defaultView
.getComputedStyle(context2D.canvas)
.getPropertyValue("font-size")
.replace("px", "");
const canvas = document.createElement("canvas");
const padding = 100;
const width = (metrics.width + padding) | 0;
const height = 3 * fontSize;
const baseline = height / 2;
canvas.width = width;
canvas.height = height;
const ctx = canvas.getContext("2d");
ctx.font = font;
ctx.fillStyle = "white";
ctx.fillRect(0, 0, canvas.width + 1, canvas.height + 1);
if (stroke) {
ctx.strokeStyle = "black";
ctx.lineWidth = context2D.lineWidth;
ctx.strokeText(textString, padding / 2, baseline);
}
if (fill) {
ctx.fillStyle = "black";
ctx.fillText(textString, padding / 2, baseline);
}
// Context image data has width * height * 4 elements, because
// each pixel's R, G, B and A are consecutive values in the array.
const pixelData = ctx.getImageData(0, 0, width, height).data;
const length = pixelData.length;
const width4 = width * 4;
let i, j;
let ascent, descent;
// Find the number of rows (from the top) until the first non-white pixel
for (i = 0; i < length; ++i) {
if (pixelData[i] !== 255) {
ascent = (i / width4) | 0;
break;
}
}
// Find the number of rows (from the bottom) until the first non-white pixel
for (i = length - 1; i >= 0; --i) {
if (pixelData[i] !== 255) {
descent = (i / width4) | 0;
break;
}
}
let minx = -1;
// For each column, for each row, check for first non-white pixel
for (i = 0; i < width && minx === -1; ++i) {
for (j = 0; j < height; ++j) {
const pixelIndex = i * 4 + j * width4;
if (
pixelData[pixelIndex] !== 255 ||
pixelData[pixelIndex + 1] !== 255 ||
pixelData[pixelIndex + 2] !== 255 ||
pixelData[pixelIndex + 3] !== 255
) {
minx = i;
break;
}
}
}
return {
width: metrics.width,
height: descent - ascent,
ascent: baseline - ascent,
descent: descent - baseline,
minx: minx - padding / 2,
};
}
return {
width: metrics.width,
height: 0,
ascent: 0,
descent: 0,
minx: 0,
};
}
let imageSmoothingEnabledName;
/**
* Writes the given text into a new canvas. The canvas will be sized to fit the text.
* If text is blank, returns undefined.
*
* @param {string} text The text to write.
* @param {object} [options] Object with the following properties:
* @param {string} [options.font='10px sans-serif'] The CSS font to use.
* @param {boolean} [options.fill=true] Whether to fill the text.
* @param {boolean} [options.stroke=false] Whether to stroke the text.
* @param {Color} [options.fillColor=Color.WHITE] The fill color.
* @param {Color} [options.strokeColor=Color.BLACK] The stroke color.
* @param {number} [options.strokeWidth=1] The stroke width.
* @param {Color} [options.backgroundColor=Color.TRANSPARENT] The background color of the canvas.
* @param {number} [options.padding=0] The pixel size of the padding to add around the text.
* @returns {HTMLCanvasElement|undefined} A new canvas with the given text drawn into it. The dimensions object
* from measureText will also be added to the returned canvas. If text is
* blank, returns undefined.
* @function writeTextToCanvas
*/
function writeTextToCanvas(text, options) {
//>>includeStart('debug', pragmas.debug);
if (!defined(text)) {
throw new DeveloperError("text is required.");
}
//>>includeEnd('debug');
if (text === "") {
return undefined;
}
options = options ?? Frozen.EMPTY_OBJECT;
const font = options.font ?? "10px sans-serif";
const stroke = options.stroke ?? false;
const fill = options.fill ?? true;
const strokeWidth = options.strokeWidth ?? 1;
const backgroundColor = options.backgroundColor ?? Color.TRANSPARENT;
const padding = options.padding ?? 0;
const doublePadding = padding * 2.0;
const canvas = document.createElement("canvas");
canvas.width = 1;
canvas.height = 1;
canvas.style.font = font;
// Since multiple read-back operations are expected for labels, use the willReadFrequently option – See https://html.spec.whatwg.org/multipage/canvas.html#concept-canvas-will-read-frequently
const context2D = canvas.getContext("2d", { willReadFrequently: true });
if (!defined(imageSmoothingEnabledName)) {
if (defined(context2D.imageSmoothingEnabled)) {
imageSmoothingEnabledName = "imageSmoothingEnabled";
} else Eif (defined(context2D.mozImageSmoothingEnabled)) {
imageSmoothingEnabledName = "mozImageSmoothingEnabled";
} else if (defined(context2D.webkitImageSmoothingEnabled)) {
imageSmoothingEnabledName = "webkitImageSmoothingEnabled";
} else if (defined(context2D.msImageSmoothingEnabled)) {
imageSmoothingEnabledName = "msImageSmoothingEnabled";
}
}
context2D.font = font;
context2D.lineJoin = "round";
context2D.lineWidth = strokeWidth;
context2D[imageSmoothingEnabledName] = false;
// in order for measureText to calculate style, the canvas has to be
// (temporarily) added to the DOM.
canvas.style.visibility = "hidden";
document.body.appendChild(canvas);
const dimensions = measureText(context2D, text, font, stroke, fill);
// Set canvas.dimensions to be accessed in LabelCollection
canvas.dimensions = dimensions;
document.body.removeChild(canvas);
canvas.style.visibility = "";
// Some characters, such as the letter j, have a non-zero starting position.
// This value is used for kerning later, but we need to take it into account
// now in order to draw the text completely on the canvas
const x = -dimensions.minx;
// Expand the width to include the starting position.
const width = Math.ceil(dimensions.width) + x + doublePadding;
// While the height of the letter is correct, we need to adjust
// where we start drawing it so that letters like j and y properly dip
// below the line.
const height = dimensions.height + doublePadding;
const baseline = height - dimensions.ascent + padding;
const y = height - baseline + doublePadding;
canvas.width = width;
canvas.height = height;
// Properties must be explicitly set again after changing width and height
context2D.font = font;
context2D.lineJoin = "round";
context2D.lineWidth = strokeWidth;
context2D[imageSmoothingEnabledName] = false;
// Draw background
if (backgroundColor !== Color.TRANSPARENT) {
context2D.fillStyle = backgroundColor.toCssColorString();
context2D.fillRect(0, 0, canvas.width, canvas.height);
}
if (stroke) {
const strokeColor = options.strokeColor ?? Color.BLACK;
context2D.strokeStyle = strokeColor.toCssColorString();
context2D.strokeText(text, x + padding, y);
}
if (fill) {
const fillColor = options.fillColor ?? Color.WHITE;
context2D.fillStyle = fillColor.toCssColorString();
context2D.fillText(text, x + padding, y);
}
return canvas;
}
export default writeTextToCanvas;
|