|
13 | 13 | * limitations under the License.
|
14 | 14 | */
|
15 | 15 |
|
16 |
| -import { ImageKind, OPS, RenderingIntentFlag, warn } from "../shared/util.js"; |
| 16 | +import { |
| 17 | + DrawOPS, |
| 18 | + ImageKind, |
| 19 | + OPS, |
| 20 | + RenderingIntentFlag, |
| 21 | + Util, |
| 22 | + warn, |
| 23 | +} from "../shared/util.js"; |
17 | 24 |
|
18 | 25 | function addState(parentState, pattern, checkFn, iterateFn, processFn) {
|
19 | 26 | let state = parentState;
|
@@ -470,6 +477,70 @@ addState(
|
470 | 477 | }
|
471 | 478 | );
|
472 | 479 |
|
| 480 | +// This replaces (save, transform, constructPath, restore) |
| 481 | +// sequences with |constructPath| operation. |
| 482 | +addState( |
| 483 | + InitialState, |
| 484 | + [OPS.save, OPS.transform, OPS.constructPath, OPS.restore], |
| 485 | + context => { |
| 486 | + const argsArray = context.argsArray; |
| 487 | + const iFirstConstructPath = context.iCurr - 1; |
| 488 | + const op = argsArray[iFirstConstructPath][0]; |
| 489 | + |
| 490 | + // When stroking the transform has to be applied to the line width too. |
| 491 | + // So we can only optimize if the transform is an identity. |
| 492 | + if ( |
| 493 | + op !== OPS.stroke && |
| 494 | + op !== OPS.closeStroke && |
| 495 | + op !== OPS.fillStroke && |
| 496 | + op !== OPS.eoFillStroke && |
| 497 | + op !== OPS.closeFillStroke && |
| 498 | + op !== OPS.closeEOFillStroke |
| 499 | + ) { |
| 500 | + return true; |
| 501 | + } |
| 502 | + const iFirstTransform = context.iCurr - 2; |
| 503 | + const transform = argsArray[iFirstTransform]; |
| 504 | + return ( |
| 505 | + transform[0] === 1 && |
| 506 | + transform[1] === 0 && |
| 507 | + transform[2] === 0 && |
| 508 | + transform[3] === 1 |
| 509 | + ); |
| 510 | + }, |
| 511 | + () => false, |
| 512 | + (context, i) => { |
| 513 | + const { fnArray, argsArray } = context; |
| 514 | + const curr = context.iCurr; |
| 515 | + const iFirstSave = curr - 3; |
| 516 | + const iFirstTransform = curr - 2; |
| 517 | + const iFirstConstructPath = curr - 1; |
| 518 | + const args = argsArray[iFirstConstructPath]; |
| 519 | + const transform = argsArray[iFirstTransform]; |
| 520 | + const [, [buffer], minMax] = args; |
| 521 | + |
| 522 | + Util.scaleMinMax(transform, minMax); |
| 523 | + for (let k = 0, kk = buffer.length; k < kk; ) { |
| 524 | + switch (buffer[k++]) { |
| 525 | + case DrawOPS.moveTo: |
| 526 | + case DrawOPS.lineTo: |
| 527 | + Util.applyTransformInPlace(buffer.subarray(k), transform); |
| 528 | + k += 2; |
| 529 | + break; |
| 530 | + case DrawOPS.curveTo: |
| 531 | + Util.applyTransformToBezierInPlace(buffer.subarray(k), transform); |
| 532 | + k += 6; |
| 533 | + break; |
| 534 | + } |
| 535 | + } |
| 536 | + // Replace queue items. |
| 537 | + fnArray.splice(iFirstSave, 4, OPS.constructPath); |
| 538 | + argsArray.splice(iFirstSave, 4, args); |
| 539 | + |
| 540 | + return iFirstSave + 1; |
| 541 | + } |
| 542 | +); |
| 543 | + |
473 | 544 | class NullOptimizer {
|
474 | 545 | constructor(queue) {
|
475 | 546 | this.queue = queue;
|
|
0 commit comments