(context: CanvasRenderingContext2D)
| 334 | } |
| 335 | |
| 336 | protected override async draw(context: CanvasRenderingContext2D) { |
| 337 | if (!CodeBlock.initialized()) return; |
| 338 | |
| 339 | this.requestFontUpdate(); |
| 340 | this.applyStyle(context); |
| 341 | context.font = this.styles.font; |
| 342 | context.textBaseline = 'top'; |
| 343 | const lh = parseFloat(this.styles.lineHeight); |
| 344 | const w = context.measureText('X').width; |
| 345 | const size = this.computedSize(); |
| 346 | const progress = this.codeProgress(); |
| 347 | const unselectedOpacity = this.unselectedOpacity(); |
| 348 | const globalAlpha = context.globalAlpha; |
| 349 | |
| 350 | const getSelectionAlpha = (x: number, y: number) => |
| 351 | map(unselectedOpacity, 1, this.selectionStrength(x, y)); |
| 352 | |
| 353 | const drawToken = ( |
| 354 | code: string, |
| 355 | position: SerializedVector2, |
| 356 | alpha = 1, |
| 357 | ) => { |
| 358 | for (let i = 0; i < code.length; i++) { |
| 359 | const char = code.charAt(i); |
| 360 | if (char === '\n') { |
| 361 | position.y++; |
| 362 | position.x = 0; |
| 363 | continue; |
| 364 | } |
| 365 | context.globalAlpha = |
| 366 | globalAlpha * alpha * getSelectionAlpha(position.x, position.y); |
| 367 | context.fillText(char, position.x * w, position.y * lh); |
| 368 | position.x++; |
| 369 | } |
| 370 | }; |
| 371 | |
| 372 | context.translate(size.x / -2, size.y / -2); |
| 373 | if (progress == null) { |
| 374 | const parsed = this.parsed(); |
| 375 | const position = {x: 0, y: 0}; |
| 376 | for (const token of parsed) { |
| 377 | context.save(); |
| 378 | context.fillStyle = token.color ?? '#c9d1d9'; |
| 379 | drawToken(token.code, position); |
| 380 | context.restore(); |
| 381 | } |
| 382 | } else { |
| 383 | const diffed = this.diffed!; |
| 384 | const beginning = 0.2; |
| 385 | const ending = 0.8; |
| 386 | const overlap = 0.15; |
| 387 | for (const token of diffed) { |
| 388 | context.save(); |
| 389 | context.fillStyle = token.color ?? '#c9d1d9'; |
| 390 | |
| 391 | if (token.morph === 'delete') { |
| 392 | drawToken( |
| 393 | token.code, |
nothing calls this directly
no test coverage detected