| 58 | } |
| 59 | |
| 60 | Data Device::getTextureDataForText(std::string_view text, |
| 61 | const FontDefinition& textDefinition, |
| 62 | TextAlign align, |
| 63 | int& width, |
| 64 | int& height, |
| 65 | bool& hasPremultipliedAlpha) |
| 66 | { |
| 67 | char color[10]; |
| 68 | fmt::format_to_z(color, "#{:02x}{:02x}{:02x}{:02x}", textDefinition._fontFillColor.r, textDefinition._fontFillColor.g, |
| 69 | textDefinition._fontFillColor.b, textDefinition._fontAlpha); |
| 70 | // clang-format off |
| 71 | unsigned char* ptr = (unsigned char*)EM_ASM_PTR({ |
| 72 | var lines = UTF8ToString($0).split("\n"); |
| 73 | var fontName = UTF8ToString($1); |
| 74 | var fontSize = $2; |
| 75 | var color = UTF8ToString($3); |
| 76 | var dimWidth = $4; |
| 77 | var dimHeight = $5; |
| 78 | var align = $6; |
| 79 | |
| 80 | // use shared canvas |
| 81 | var canvas = Module.axmolSharedCanvas = Module.axmolSharedCanvas || document.createElement("canvas"); |
| 82 | var context = canvas.getContext('2d', { willReadFrequently: true }); |
| 83 | context.font = fontSize + "px " + fontName; |
| 84 | // use alphabetic baseline for text rendering |
| 85 | context.textBaseline = "alphabetic"; |
| 86 | |
| 87 | var linesWidth = []; |
| 88 | var linesAscent = []; |
| 89 | var linesDescent = []; |
| 90 | var totalHeight = 0; |
| 91 | var maxWidth = dimWidth > 0 ? dimWidth : 0; |
| 92 | |
| 93 | var defaultAscent = 0; |
| 94 | var defaultDescent = 0; |
| 95 | |
| 96 | var measureDefault = ()=> { |
| 97 | if (defaultAscent == 0 && defaultDescent == 0) { |
| 98 | var metrics = context.measureText('M'); // or Hg |
| 99 | defaultAscent = (typeof metrics.actualBoundingBoxAscent === "number") ? metrics.actualBoundingBoxAscent : fontSize * 0.8; |
| 100 | defaultDescent = (typeof metrics.actualBoundingBoxDescent === "number") ? metrics.actualBoundingBoxDescent : fontSize * 0.2; |
| 101 | } |
| 102 | }; |
| 103 | |
| 104 | // compute per line metrics |
| 105 | for (var i = 0; i < lines.length; i++) { |
| 106 | var metrics = context.measureText(lines[i]); |
| 107 | var lineWidth = metrics.width; |
| 108 | // if browser not support actualBoundingBoxAscent/descent, use fallback values |
| 109 | var ascent = (typeof metrics.actualBoundingBoxAscent === "number") ? metrics.actualBoundingBoxAscent : fontSize * 0.8; |
| 110 | var descent = (typeof metrics.actualBoundingBoxDescent === "number") ? metrics.actualBoundingBoxDescent : fontSize * 0.2; |
| 111 | var lineHeight = ascent + descent; |
| 112 | // if the line text only contains white space chars, the lineHeight will be 0, |
| 113 | // so we re-calculate lineHeight by representative text, i.e. 'M' or 'Hg' |
| 114 | if (lineHeight == 0) { |
| 115 | measureDefault(); |
| 116 | ascent = defaultAscent; |
| 117 | descent = defaultDescent; |
nothing calls this directly
no test coverage detected