@@ -28,11 +28,11 @@ THE SOFTWARE.
28
28
#include " platform/PlatformConfig.h"
29
29
#if AX_TARGET_PLATFORM == AX_PLATFORM_WASM
30
30
31
- #include " platform/Device.h"
32
- #include " platform/FileUtils.h"
31
+ # include " platform/Device.h"
32
+ # include " platform/FileUtils.h"
33
33
34
- #include < emscripten/emscripten.h>
35
- #include < emscripten/html5.h>
34
+ # include < emscripten/emscripten.h>
35
+ # include < emscripten/html5.h>
36
36
37
37
namespace ax
38
38
{
@@ -57,76 +57,102 @@ void Device::setAccelerometerInterval(float interval)
57
57
// TODO: https://emscripten.org/docs/api_reference/html5.h.html?
58
58
}
59
59
60
- Data Device::getTextureDataForText (std::string_view text, const FontDefinition& textDefinition, TextAlign align, int &width, int &height, bool & hasPremultipliedAlpha)
60
+ Data Device::getTextureDataForText (std::string_view text,
61
+ const FontDefinition& textDefinition,
62
+ TextAlign align,
63
+ int & width,
64
+ int & height,
65
+ bool & hasPremultipliedAlpha)
61
66
{
62
67
char color[8 ];
63
- sprintf (color, " #%02x%02x%02x" , textDefinition._fontFillColor .r , textDefinition._fontFillColor .g , textDefinition._fontFillColor .b );
68
+ sprintf (color, " #%02x%02x%02x" , textDefinition._fontFillColor .r , textDefinition._fontFillColor .g ,
69
+ textDefinition._fontFillColor .b );
70
+ // clang-format off
64
71
unsigned char * ptr = (unsigned char *)EM_ASM_PTR ({
65
72
var lines = UTF8ToString ($0 ).split (" \n " );
66
- var linesWidth = [];
67
73
var fontName = UTF8ToString ($1 );
68
74
var fontSize = $2 ;
69
- var lineHeight = $2 * 1.2 ; // Nothing accurate
70
75
var color = UTF8ToString ($3 );
71
76
var dimWidth = $4 ;
72
77
var dimHeight = $5 ;
73
78
var align = $6 ;
74
79
80
+ // use shared canvas
75
81
var canvas = Module.axmolSharedCanvas = Module.axmolSharedCanvas || document.createElement (" canvas" );
76
82
var context = canvas.getContext (' 2d' , { willReadFrequently: true });
77
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 ;
78
92
79
- var canvasWidth = dimWidth;
80
- var canvasHeight = dimHeight;
93
+ // compute per line metrics
81
94
for (var i = 0 ; i < lines.length ; i++) {
82
- var lineWidth = context.measureText (lines[i]).width ;
83
- linesWidth[i] = lineWidth;
84
- if (lineWidth > canvasWidth && dimWidth <= 0 ) {
85
- canvasWidth = lineWidth;
95
+ var metrics = context.measureText (lines[i]);
96
+ var lineWidth = metrics.width ;
97
+ // if browser not support actualBoundingBoxAscent/descent, use fallback values
98
+ var ascent = (typeof metrics.actualBoundingBoxAscent === " number" ) ? metrics.actualBoundingBoxAscent : fontSize * 0.8 ;
99
+ var descent = (typeof metrics.actualBoundingBoxDescent === " number" ) ? metrics.actualBoundingBoxDescent : fontSize * 0.2 ;
100
+ var lineHeight = ascent + descent;
101
+ linesWidth.push (lineWidth);
102
+ linesAscent.push (ascent);
103
+ linesDescent.push (descent);
104
+ if (dimWidth <= 0 && lineWidth > maxWidth) {
105
+ maxWidth = lineWidth;
86
106
}
87
- };
107
+ totalHeight += lineHeight;
108
+ }
88
109
89
- if (dimHeight <= 0 ) {
90
- canvasHeight = lineHeight * lines.length ;
110
+ // if dimensions are specified, use them to limit the height
111
+ if (dimHeight > 0 ) {
112
+ totalHeight = dimHeight;
91
113
}
92
114
93
- canvasWidth = Math.ceil (canvasWidth );
94
- canvasHeight = Math.ceil (canvasHeight );
115
+ var canvasWidth = Math.ceil (maxWidth );
116
+ var canvasHeight = Math.ceil (totalHeight );
95
117
96
118
canvas.width = canvasWidth;
97
119
canvas.height = canvasHeight;
98
120
99
121
context.clearRect (0 , 0 , canvasWidth, canvasHeight);
100
122
context.font = fontSize + " px " + fontName;
101
123
context.fillStyle = color;
102
- context.textBaseline = " top " ;
124
+ context.textBaseline = " alphabetic " ;
103
125
104
- // Vertical top
126
+ // vertical top
105
127
var offsetY = 0 ;
106
- if ((align & 0xf0 ) == 0x30 ) {
107
- // Vertical center
108
- offsetY = (canvasHeight - lineHeight * lines. length ) / 2 ;
109
- } else if ((align & 0xf0 ) == 0x20 ) {
110
- // Vertical bottom
111
- offsetY = canvasHeight - lineHeight * lines. length ;
128
+ if ((align & 0xf0 ) === 0x30 ) {
129
+ // vertical center align
130
+ offsetY = (canvasHeight - totalHeight ) / 2 ;
131
+ } else if ((align & 0xf0 ) === 0x20 ) {
132
+ // bottom align
133
+ offsetY = canvasHeight - totalHeight ;
112
134
}
113
135
136
+ // draw each line of text
114
137
for (var i = 0 ; i < lines.length ; i++) {
115
- // Horizonal left
138
+ var lineH = linesAscent[i] + linesDescent[i];
139
+ // horizontal left
116
140
var offsetX = 0 ;
117
- if ((align & 0x0f ) == 0x03 ) {
118
- // Horizonal center
141
+ if ((align & 0x0f ) === 0x03 ) {
119
142
offsetX = (canvasWidth - linesWidth[i]) / 2 ;
120
- } else if ((align & 0x0f ) == 0x02 ) {
121
- // Horizonal right
143
+ } else if ((align & 0x0f ) === 0x02 ) {
122
144
offsetX = canvasWidth - linesWidth[i];
123
145
}
124
- context.fillText (lines[i], offsetX, offsetY + lineHeight * i);
146
+ // use align left by default, offsetX remains 0
147
+ var baselineY = offsetY + linesAscent[i];
148
+ context.fillText (lines[i], offsetX, baselineY);
149
+ offsetY += lineH;
125
150
}
126
151
152
+ // get pixel data from the canvas
127
153
var data = context.getImageData (0 , 0 , canvasWidth, canvasHeight).data ;
128
- var ptr = _malloc (data.byteLength ); // Cocos Data object free it
129
- var buffer= new Uint8Array (Module.HEAPU8 .buffer , ptr, data.byteLength );
154
+ var ptr = _malloc (data.byteLength );
155
+ var buffer = new Uint8Array (Module.HEAPU8 .buffer , ptr, data.byteLength );
130
156
buffer.set (data);
131
157
return ptr;
132
158
}, text.data (), textDefinition._fontName .c_str (), textDefinition._fontSize , color, textDefinition._dimensions .width , textDefinition._dimensions .height , align);
@@ -137,6 +163,8 @@ Data Device::getTextureDataForText(std::string_view text, const FontDefinition&
137
163
height = EM_ASM_INT ({
138
164
return Module.axmolSharedCanvas .height ;
139
165
});
166
+ // clang-format on
167
+
140
168
hasPremultipliedAlpha = false ;
141
169
142
170
Data ret;
@@ -166,6 +194,6 @@ void Device::prepareSelectionFeedbackGenerator() {}
166
194
167
195
void Device::selectionChanged () {}
168
196
169
- }
197
+ } // namespace ax
170
198
171
- #endif // AX_TARGET_PLATFORM == AX_PLATFORM_WASM
199
+ #endif // AX_TARGET_PLATFORM == AX_PLATFORM_WASM
0 commit comments