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