pdfnative 1.3.0 → 1.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -3581,15 +3581,86 @@ function radialShadingDict(p, m) {
3581
3581
  const s = (sx + sy) / 2 || 1;
3582
3582
  return `<< /ShadingType 3 /ColorSpace /DeviceRGB /Coords [${n(x0)} ${n(y0)} ${n(p.r0 * s)} ${n(x1)} ${n(y1)} ${n(p.r1 * s)}] /Function ${buildGradientFunction(p.stops)} /Extend ${extendFlags(p.extend)} >>`;
3583
3583
  }
3584
+ function colorAtOffset(stops, t) {
3585
+ if (stops.length === 0) return [0, 0, 0, 255];
3586
+ const sorted = stops.slice().sort((a, b) => a.offset - b.offset);
3587
+ if (t <= sorted[0].offset) return sorted[0].color;
3588
+ const last = sorted[sorted.length - 1];
3589
+ if (t >= last.offset) return last.color;
3590
+ for (let i = 0; i < sorted.length - 1; i++) {
3591
+ const a = sorted[i], b = sorted[i + 1];
3592
+ if (t >= a.offset && t <= b.offset) {
3593
+ const span = b.offset - a.offset || 1;
3594
+ const f = (t - a.offset) / span;
3595
+ return [
3596
+ Math.round(a.color[0] + (b.color[0] - a.color[0]) * f),
3597
+ Math.round(a.color[1] + (b.color[1] - a.color[1]) * f),
3598
+ Math.round(a.color[2] + (b.color[2] - a.color[2]) * f),
3599
+ Math.round(a.color[3] + (b.color[3] - a.color[3]) * f)
3600
+ ];
3601
+ }
3602
+ }
3603
+ return last.color;
3604
+ }
3605
+ function emitSweep(p, cx, cy, maxR, body, gsFor, blendMode) {
3606
+ const start = p.startAngle;
3607
+ const end = p.endAngle;
3608
+ const span = end - start;
3609
+ if (Math.abs(span) < 0.01) {
3610
+ const c = colorAtOffset(p.stops, 0);
3611
+ const gs = gsFor(c[3] / 255, blendMode);
3612
+ if (gs) body.push(`/${gs} gs`);
3613
+ body.push(`${ch(c[0])} ${ch(c[1])} ${ch(c[2])} rg`);
3614
+ body.push(`${n(cx - maxR)} ${n(cy - maxR)} ${n(2 * maxR)} ${n(2 * maxR)} re`);
3615
+ body.push("f");
3616
+ return;
3617
+ }
3618
+ const steps = Math.max(12, Math.min(180, Math.ceil(Math.abs(span) / 3)));
3619
+ const r = maxR * 1.5;
3620
+ const rad = Math.PI / 180;
3621
+ for (let i = 0; i < steps; i++) {
3622
+ const a0 = start + span * i / steps;
3623
+ const a1 = start + span * (i + 1) / steps;
3624
+ const tMid = (i + 0.5) / steps;
3625
+ const c = colorAtOffset(p.stops, tMid);
3626
+ const gs = gsFor(c[3] / 255, blendMode);
3627
+ body.push("q");
3628
+ if (gs) body.push(`/${gs} gs`);
3629
+ body.push(`${ch(c[0])} ${ch(c[1])} ${ch(c[2])} rg`);
3630
+ const x0 = cx + r * Math.cos(a0 * rad), y0 = cy + r * Math.sin(a0 * rad);
3631
+ const x1 = cx + r * Math.cos(a1 * rad), y1 = cy + r * Math.sin(a1 * rad);
3632
+ body.push(`${n(cx)} ${n(cy)} m ${n(x0)} ${n(y0)} l ${n(x1)} ${n(y1)} l h`);
3633
+ body.push("f");
3634
+ body.push("Q");
3635
+ }
3636
+ }
3584
3637
  function renderColorGlyph(glyph, outlines, unitsPerEm) {
3585
3638
  const body = [];
3586
3639
  const shadings = [];
3587
3640
  const extGStates = [];
3588
- const alphaMap = /* @__PURE__ */ new Map();
3641
+ const gsMap = /* @__PURE__ */ new Map();
3589
3642
  let shadingIdx = 0;
3643
+ const gsFor = (alpha, bm) => {
3644
+ const a = Math.max(0, Math.min(1, alpha));
3645
+ const needAlpha = a < 0.999;
3646
+ const needBm = bm !== void 0 && bm !== "Normal";
3647
+ if (!needAlpha && !needBm) return "";
3648
+ const key = `${needAlpha ? a.toFixed(3) : "1"}|${needBm ? bm : ""}`;
3649
+ let name = gsMap.get(key);
3650
+ if (!name) {
3651
+ name = `Gs${gsMap.size}`;
3652
+ gsMap.set(key, name);
3653
+ const parts = [];
3654
+ if (needAlpha) parts.push(`/ca ${n(a)}`, `/CA ${n(a)}`);
3655
+ if (needBm) parts.push(`/BM /${bm}`);
3656
+ extGStates.push({ name, dict: `<< ${parts.join(" ")} >>` });
3657
+ }
3658
+ return name;
3659
+ };
3590
3660
  let minX = Infinity, minY = Infinity, maxX = -Infinity, maxY = -Infinity;
3591
3661
  for (const layer of glyph.layers) {
3592
3662
  const m = layer.transform ?? ID;
3663
+ const bm = layer.blendMode;
3593
3664
  const contours = outlines(layer.glyphId);
3594
3665
  if (contours.length === 0) continue;
3595
3666
  const path = contoursToPath(contours, m);
@@ -3604,26 +3675,36 @@ function renderColorGlyph(glyph, outlines, unitsPerEm) {
3604
3675
  }
3605
3676
  if (layer.paint.kind === "solid") {
3606
3677
  const c = layer.paint.color;
3607
- const alpha = c[3] / 255;
3608
3678
  body.push("q");
3609
- if (alpha < 0.999) {
3610
- let gs = alphaMap.get(c[3]);
3611
- if (!gs) {
3612
- gs = `GsA${alphaMap.size}`;
3613
- alphaMap.set(c[3], gs);
3614
- extGStates.push({ name: gs, dict: `<< /ca ${n(alpha)} /CA ${n(alpha)} >>` });
3615
- }
3616
- body.push(`/${gs} gs`);
3617
- }
3679
+ const gs = gsFor(c[3] / 255, bm);
3680
+ if (gs) body.push(`/${gs} gs`);
3618
3681
  body.push(`${ch(c[0])} ${ch(c[1])} ${ch(c[2])} rg`);
3619
3682
  body.push(path);
3620
3683
  body.push("f");
3621
3684
  body.push("Q");
3685
+ } else if (layer.paint.kind === "sweep") {
3686
+ const [cx, cy] = tx(m, layer.paint.center[0], layer.paint.center[1]);
3687
+ let r2 = 0;
3688
+ for (const contour of contours) {
3689
+ for (const pt of contour) {
3690
+ const [px, py] = tx(m, pt.x, pt.y);
3691
+ const d = (px - cx) * (px - cx) + (py - cy) * (py - cy);
3692
+ if (d > r2) r2 = d;
3693
+ }
3694
+ }
3695
+ const maxR = Math.sqrt(r2) || 1;
3696
+ body.push("q");
3697
+ body.push(path);
3698
+ body.push("W n");
3699
+ emitSweep(layer.paint, cx, cy, maxR, body, gsFor, bm);
3700
+ body.push("Q");
3622
3701
  } else {
3623
3702
  const name = `Sh${shadingIdx++}`;
3624
3703
  const dict = layer.paint.kind === "linear" ? linearShadingDict(layer.paint, m) : radialShadingDict(layer.paint, m);
3625
3704
  shadings.push({ name, dict });
3626
3705
  body.push("q");
3706
+ const gs = gsFor(1, bm);
3707
+ if (gs) body.push(`/${gs} gs`);
3627
3708
  body.push(path);
3628
3709
  body.push("W n");
3629
3710
  body.push(`/${name} sh`);