@pilio/gemini-watermark-remover 1.0.45 → 1.0.46

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.
Files changed (125) hide show
  1. package/LICENSE +22 -22
  2. package/README.md +426 -426
  3. package/README_zh.md +415 -415
  4. package/bin/gwr.mjs +12 -12
  5. package/dist/models/allenk-fdncnn/onnx-manifest.json +49 -49
  6. package/dist/onnxruntime/LICENSE +21 -21
  7. package/dist/onnxruntime/README.md +16 -16
  8. package/dist/onnxruntime/ThirdPartyNotices.txt +6121 -6121
  9. package/dist/onnxruntime/ort-wasm-simd-threaded.asyncify.mjs +112 -112
  10. package/dist/onnxruntime/ort-wasm-simd-threaded.js +59 -59
  11. package/dist/video-app.js +1 -1
  12. package/dist/video-preview.html +599 -599
  13. package/package.json +1 -1
  14. package/skills/gemini-watermark-remover/SKILL.md +32 -32
  15. package/skills/gemini-watermark-remover/agents/openai.yaml +3 -3
  16. package/skills/gemini-watermark-remover/references/inputs-and-outputs.md +9 -9
  17. package/skills/gemini-watermark-remover/references/limitations.md +5 -5
  18. package/skills/gemini-watermark-remover/references/usage.md +23 -23
  19. package/skills/gemini-watermark-remover/scripts/run.mjs +153 -153
  20. package/src/cli/gwrCli.js +17 -17
  21. package/src/cli/gwrRemoveCommand.js +433 -433
  22. package/src/core/adaptiveDetector.js +630 -630
  23. package/src/core/allenkFdncnnDenoise.js +653 -653
  24. package/src/core/allenkFdncnnNcnnModel.js +244 -244
  25. package/src/core/allenkFdncnnOnnxExport.js +346 -346
  26. package/src/core/allenkFdncnnOnnxRuntime.js +138 -138
  27. package/src/core/allenkFdncnnReferenceRuntime.js +169 -169
  28. package/src/core/alphaGradientMask.js +165 -165
  29. package/src/core/alphaMap.js +30 -30
  30. package/src/core/blendModes.js +75 -75
  31. package/src/core/candidateEvaluation.js +299 -299
  32. package/src/core/candidateSelector.js +3736 -3736
  33. package/src/core/canvasBlob.js +26 -26
  34. package/src/core/darkOutlineContourRepair.js +323 -323
  35. package/src/core/embeddedAlphaMaps.js +102 -102
  36. package/src/core/embeddedDarkOutlineAlphaMap.js +6 -6
  37. package/src/core/embeddedOutlineAlphaMap.js +5 -5
  38. package/src/core/geminiSizeCatalog.js +580 -580
  39. package/src/core/imageWatermarkPipeline.js +329 -329
  40. package/src/core/imageWatermarkPipelineRequest.js +39 -39
  41. package/src/core/multiPassRemoval.js +93 -93
  42. package/src/core/outputResidualLocalization.js +351 -351
  43. package/src/core/pipelineAcceptedExecutor.js +364 -364
  44. package/src/core/pipelineAcceptedExecutorRequest.js +46 -46
  45. package/src/core/pipelineAcceptedFinalizationRequest.js +21 -21
  46. package/src/core/pipelineAlphaStageSpecs.js +654 -654
  47. package/src/core/pipelineAlphaTraceContract.js +58 -58
  48. package/src/core/pipelineAlphaTrial.js +306 -306
  49. package/src/core/pipelineCandidatePool.js +125 -125
  50. package/src/core/pipelineCandidateQuality.js +838 -838
  51. package/src/core/pipelineCandidateRunner.js +109 -109
  52. package/src/core/pipelineDecisionPath.js +161 -161
  53. package/src/core/pipelineDetectionCandidate.js +128 -128
  54. package/src/core/pipelineFinalization.js +99 -99
  55. package/src/core/pipelineInitialContext.js +52 -52
  56. package/src/core/pipelineInitialSelection.js +1504 -1498
  57. package/src/core/pipelineLayerContracts.js +163 -163
  58. package/src/core/pipelineMeta.js +427 -427
  59. package/src/core/pipelineMetrics.js +88 -88
  60. package/src/core/pipelinePassState.js +36 -36
  61. package/src/core/pipelineRepairGates.js +154 -154
  62. package/src/core/pipelineRepairStageSpecs.js +525 -525
  63. package/src/core/pipelineRepairTrial.js +156 -156
  64. package/src/core/pipelineResult.js +197 -197
  65. package/src/core/pipelineRuntime.js +710 -710
  66. package/src/core/pipelineRuntimeBootstrap.js +78 -78
  67. package/src/core/pipelineState.js +134 -134
  68. package/src/core/pipelineTimings.js +36 -36
  69. package/src/core/pipelineTrace.js +28 -28
  70. package/src/core/planeAlphaEvidence.js +106 -106
  71. package/src/core/previewAlphaCalibration.js +825 -825
  72. package/src/core/restorationMetrics.js +807 -807
  73. package/src/core/rowAlphaEvidence.js +59 -59
  74. package/src/core/selectionDebug.js +93 -93
  75. package/src/core/watermarkConfig.js +146 -146
  76. package/src/core/watermarkDecisionPolicy.js +163 -163
  77. package/src/core/watermarkDisplay.js +89 -89
  78. package/src/core/watermarkEngine.js +173 -173
  79. package/src/core/watermarkPresence.js +14 -14
  80. package/src/core/watermarkProcessor.js +6332 -6332
  81. package/src/core/watermarkScoring.js +197 -197
  82. package/src/core/workerClient.js +114 -114
  83. package/src/runtime/browser.d.ts +7 -7
  84. package/src/runtime/browser.js +96 -96
  85. package/src/runtime/userscript.d.ts +6 -6
  86. package/src/runtime/userscript.js +28 -28
  87. package/src/sdk/browser.d.ts +13 -13
  88. package/src/sdk/browser.js +29 -29
  89. package/src/sdk/image-data.d.ts +14 -14
  90. package/src/sdk/image-data.js +78 -78
  91. package/src/sdk/index.d.ts +191 -191
  92. package/src/sdk/index.js +8 -8
  93. package/src/sdk/node.d.ts +56 -56
  94. package/src/sdk/node.js +84 -84
  95. package/src/sdk/runtime-browser.d.ts +32 -32
  96. package/src/sdk/runtime-browser.js +1 -1
  97. package/src/sdk/runtime-userscript.d.ts +41 -41
  98. package/src/sdk/runtime-userscript.js +1 -1
  99. package/src/sdk/video.d.ts +111 -111
  100. package/src/sdk/video.js +358 -358
  101. package/src/sdk/videoProgress.js +108 -108
  102. package/src/shared/actionContextCompat.js +54 -54
  103. package/src/shared/debugFileHandoff.js +109 -109
  104. package/src/shared/domAdapter.js +279 -279
  105. package/src/shared/errorUtils.js +62 -62
  106. package/src/shared/imageProcessing.js +162 -162
  107. package/src/shared/imageSessionContext.js +98 -98
  108. package/src/shared/imageSessionStore.js +495 -495
  109. package/src/shared/originalBlob.js +79 -79
  110. package/src/shared/pageImageReplacement.js +2366 -2366
  111. package/src/userscript/actionContext.js +210 -210
  112. package/src/userscript/bridgeShared.js +72 -72
  113. package/src/userscript/clipboardHook.js +351 -351
  114. package/src/userscript/crossOriginFetch.js +84 -84
  115. package/src/userscript/downloadHook.js +1576 -1576
  116. package/src/userscript/historyBindingBootstrap.js +163 -163
  117. package/src/userscript/index.js +346 -346
  118. package/src/userscript/pageProcessBridge.js +283 -283
  119. package/src/userscript/pageProcessorRuntime.js +153 -153
  120. package/src/userscript/processBridge.js +186 -186
  121. package/src/userscript/processingRuntime.js +261 -261
  122. package/src/userscript/runtimeFlags.js +46 -46
  123. package/src/userscript/trustedTypes.js +49 -49
  124. package/src/userscript/urlUtils.js +169 -169
  125. package/src/userscript/userNotice.js +19 -19
@@ -1,88 +1,88 @@
1
- import {
2
- computeRegionGradientCorrelation,
3
- computeRegionSpatialCorrelation
4
- } from './adaptiveDetector.js';
5
- import { calculateNearBlackRatio } from './candidateSelector.js';
6
-
7
- const FIRST_PASS_SIGN_FLIP_GRADIENT_THRESHOLD = 0.08;
8
- const FIRST_PASS_SIGN_FLIP_MIN_GRADIENT_DROP = 0.2;
9
-
10
- export function shouldStopAfterFirstPass({
11
- originalSpatialScore,
12
- originalGradientScore,
13
- firstPassSpatialScore,
14
- firstPassGradientScore
15
- }) {
16
- if (Math.abs(firstPassSpatialScore) <= 0.25) {
17
- return true;
18
- }
19
-
20
- return originalSpatialScore >= 0 &&
21
- firstPassSpatialScore < 0 &&
22
- firstPassGradientScore <= FIRST_PASS_SIGN_FLIP_GRADIENT_THRESHOLD &&
23
- (originalGradientScore - firstPassGradientScore) >= FIRST_PASS_SIGN_FLIP_MIN_GRADIENT_DROP;
24
- }
25
-
26
- export function createRegionCorrelationMetrics({
27
- imageData,
28
- alphaMap,
29
- position,
30
- includeNearBlackRatio = false
31
- } = {}) {
32
- const region = { x: position.x, y: position.y, size: position.width };
33
- const metrics = {
34
- spatialScore: computeRegionSpatialCorrelation({
35
- imageData,
36
- alphaMap,
37
- region
38
- }),
39
- gradientScore: computeRegionGradientCorrelation({
40
- imageData,
41
- alphaMap,
42
- region
43
- })
44
- };
45
- if (includeNearBlackRatio) {
46
- metrics.nearBlackRatio = calculateNearBlackRatio(imageData, position);
47
- }
48
- return metrics;
49
- }
50
-
51
- export function createFirstPassMetrics({
52
- imageData,
53
- alphaMap,
54
- position,
55
- originalSpatialScore,
56
- originalGradientScore
57
- } = {}) {
58
- const firstPassMetrics = createRegionCorrelationMetrics({
59
- imageData,
60
- alphaMap,
61
- position,
62
- includeNearBlackRatio: true
63
- });
64
- const clearedResidual = shouldStopAfterFirstPass({
65
- originalSpatialScore,
66
- originalGradientScore,
67
- firstPassSpatialScore: firstPassMetrics.spatialScore,
68
- firstPassGradientScore: firstPassMetrics.gradientScore
69
- });
70
-
71
- return {
72
- spatialScore: firstPassMetrics.spatialScore,
73
- gradientScore: firstPassMetrics.gradientScore,
74
- nearBlackRatio: firstPassMetrics.nearBlackRatio,
75
- clearedResidual,
76
- passStopReason: clearedResidual ? 'residual-low' : 'single-pass',
77
- passRecord: {
78
- index: 1,
79
- beforeSpatialScore: originalSpatialScore,
80
- beforeGradientScore: originalGradientScore,
81
- afterSpatialScore: firstPassMetrics.spatialScore,
82
- afterGradientScore: firstPassMetrics.gradientScore,
83
- improvement: Math.abs(originalSpatialScore) - Math.abs(firstPassMetrics.spatialScore),
84
- gradientDelta: firstPassMetrics.gradientScore - originalGradientScore,
85
- nearBlackRatio: firstPassMetrics.nearBlackRatio
86
- }
87
- };
88
- }
1
+ import {
2
+ computeRegionGradientCorrelation,
3
+ computeRegionSpatialCorrelation
4
+ } from './adaptiveDetector.js';
5
+ import { calculateNearBlackRatio } from './candidateSelector.js';
6
+
7
+ const FIRST_PASS_SIGN_FLIP_GRADIENT_THRESHOLD = 0.08;
8
+ const FIRST_PASS_SIGN_FLIP_MIN_GRADIENT_DROP = 0.2;
9
+
10
+ export function shouldStopAfterFirstPass({
11
+ originalSpatialScore,
12
+ originalGradientScore,
13
+ firstPassSpatialScore,
14
+ firstPassGradientScore
15
+ }) {
16
+ if (Math.abs(firstPassSpatialScore) <= 0.25) {
17
+ return true;
18
+ }
19
+
20
+ return originalSpatialScore >= 0 &&
21
+ firstPassSpatialScore < 0 &&
22
+ firstPassGradientScore <= FIRST_PASS_SIGN_FLIP_GRADIENT_THRESHOLD &&
23
+ (originalGradientScore - firstPassGradientScore) >= FIRST_PASS_SIGN_FLIP_MIN_GRADIENT_DROP;
24
+ }
25
+
26
+ export function createRegionCorrelationMetrics({
27
+ imageData,
28
+ alphaMap,
29
+ position,
30
+ includeNearBlackRatio = false
31
+ } = {}) {
32
+ const region = { x: position.x, y: position.y, size: position.width };
33
+ const metrics = {
34
+ spatialScore: computeRegionSpatialCorrelation({
35
+ imageData,
36
+ alphaMap,
37
+ region
38
+ }),
39
+ gradientScore: computeRegionGradientCorrelation({
40
+ imageData,
41
+ alphaMap,
42
+ region
43
+ })
44
+ };
45
+ if (includeNearBlackRatio) {
46
+ metrics.nearBlackRatio = calculateNearBlackRatio(imageData, position);
47
+ }
48
+ return metrics;
49
+ }
50
+
51
+ export function createFirstPassMetrics({
52
+ imageData,
53
+ alphaMap,
54
+ position,
55
+ originalSpatialScore,
56
+ originalGradientScore
57
+ } = {}) {
58
+ const firstPassMetrics = createRegionCorrelationMetrics({
59
+ imageData,
60
+ alphaMap,
61
+ position,
62
+ includeNearBlackRatio: true
63
+ });
64
+ const clearedResidual = shouldStopAfterFirstPass({
65
+ originalSpatialScore,
66
+ originalGradientScore,
67
+ firstPassSpatialScore: firstPassMetrics.spatialScore,
68
+ firstPassGradientScore: firstPassMetrics.gradientScore
69
+ });
70
+
71
+ return {
72
+ spatialScore: firstPassMetrics.spatialScore,
73
+ gradientScore: firstPassMetrics.gradientScore,
74
+ nearBlackRatio: firstPassMetrics.nearBlackRatio,
75
+ clearedResidual,
76
+ passStopReason: clearedResidual ? 'residual-low' : 'single-pass',
77
+ passRecord: {
78
+ index: 1,
79
+ beforeSpatialScore: originalSpatialScore,
80
+ beforeGradientScore: originalGradientScore,
81
+ afterSpatialScore: firstPassMetrics.spatialScore,
82
+ afterGradientScore: firstPassMetrics.gradientScore,
83
+ improvement: Math.abs(originalSpatialScore) - Math.abs(firstPassMetrics.spatialScore),
84
+ gradientDelta: firstPassMetrics.gradientScore - originalGradientScore,
85
+ nearBlackRatio: firstPassMetrics.nearBlackRatio
86
+ }
87
+ };
88
+ }
@@ -1,36 +1,36 @@
1
- function finiteOrFallback(value, fallback) {
2
- return typeof value === 'number' && Number.isFinite(value) ? value : fallback;
3
- }
4
-
5
- export function createEmptyPipelinePassState() {
6
- return {
7
- passCount: 0,
8
- attemptedPassCount: 0,
9
- passStopReason: null,
10
- passes: null
11
- };
12
- }
13
-
14
- export function createFirstPassPipelinePassState({
15
- firstPassMetrics = null
16
- } = {}) {
17
- return {
18
- passCount: 1,
19
- attemptedPassCount: 1,
20
- passStopReason: firstPassMetrics?.passStopReason ?? null,
21
- passes: [firstPassMetrics?.passRecord]
22
- };
23
- }
24
-
25
- export function applyPipelinePassOutcome({
26
- current,
27
- outcome
28
- } = {}) {
29
- const passIncrement = Math.max(0, finiteOrFallback(outcome?.passIncrement, 0));
30
- return {
31
- passCount: finiteOrFallback(current?.passCount, 0) + passIncrement,
32
- attemptedPassCount: finiteOrFallback(current?.attemptedPassCount, 0) + passIncrement,
33
- passStopReason: outcome?.passStopReason ?? current?.passStopReason ?? null,
34
- passes: current?.passes ?? null
35
- };
36
- }
1
+ function finiteOrFallback(value, fallback) {
2
+ return typeof value === 'number' && Number.isFinite(value) ? value : fallback;
3
+ }
4
+
5
+ export function createEmptyPipelinePassState() {
6
+ return {
7
+ passCount: 0,
8
+ attemptedPassCount: 0,
9
+ passStopReason: null,
10
+ passes: null
11
+ };
12
+ }
13
+
14
+ export function createFirstPassPipelinePassState({
15
+ firstPassMetrics = null
16
+ } = {}) {
17
+ return {
18
+ passCount: 1,
19
+ attemptedPassCount: 1,
20
+ passStopReason: firstPassMetrics?.passStopReason ?? null,
21
+ passes: [firstPassMetrics?.passRecord]
22
+ };
23
+ }
24
+
25
+ export function applyPipelinePassOutcome({
26
+ current,
27
+ outcome
28
+ } = {}) {
29
+ const passIncrement = Math.max(0, finiteOrFallback(outcome?.passIncrement, 0));
30
+ return {
31
+ passCount: finiteOrFallback(current?.passCount, 0) + passIncrement,
32
+ attemptedPassCount: finiteOrFallback(current?.attemptedPassCount, 0) + passIncrement,
33
+ passStopReason: outcome?.passStopReason ?? current?.passStopReason ?? null,
34
+ passes: current?.passes ?? null
35
+ };
36
+ }
@@ -1,154 +1,154 @@
1
- const DEFAULT_PREVIEW_EDGE_CLEANUP_MAX_SIZE = 32;
2
- const DEFAULT_KNOWN_48_EDGE_CLEANUP_MIN_SIZE = 40;
3
- const DEFAULT_KNOWN_48_EDGE_CLEANUP_MAX_SIZE = 56;
4
- const DEFAULT_V2_SMALL_EDGE_CLEANUP_SIZE = 36;
5
- const DEFAULT_V2_SMALL_EDGE_CLEANUP_SIZE_TOLERANCE = 2;
6
-
7
- export function shouldUsePreviewAnchorFastCleanup(
8
- selectedTrial,
9
- position,
10
- { previewEdgeCleanupMaxSize = DEFAULT_PREVIEW_EDGE_CLEANUP_MAX_SIZE } = {}
11
- ) {
12
- return selectedTrial?.provenance?.previewAnchor === true &&
13
- position?.width >= 24 &&
14
- position?.width <= previewEdgeCleanupMaxSize;
15
- }
16
-
17
- export function isKnown48AnchorConfig(
18
- config,
19
- {
20
- known48EdgeCleanupMinSize = DEFAULT_KNOWN_48_EDGE_CLEANUP_MIN_SIZE,
21
- known48EdgeCleanupMaxSize = DEFAULT_KNOWN_48_EDGE_CLEANUP_MAX_SIZE
22
- } = {}
23
- ) {
24
- if (!config || config.logoSize < known48EdgeCleanupMinSize || config.logoSize > known48EdgeCleanupMaxSize) {
25
- return false;
26
- }
27
-
28
- const marginRight = Number(config.marginRight);
29
- const marginBottom = Number(config.marginBottom);
30
- if (!Number.isFinite(marginRight) || !Number.isFinite(marginBottom)) return false;
31
-
32
- const isCurrentLargeMargin = Math.abs(marginRight - 96) <= 2 && Math.abs(marginBottom - 96) <= 2;
33
- const isCurrentStandardMargin = marginRight >= 28 && marginRight <= 36 && marginBottom >= 28 && marginBottom <= 36;
34
- return isCurrentLargeMargin || isCurrentStandardMargin;
35
- }
36
-
37
- export function shouldUseKnown48EdgeCleanup({
38
- selectedTrial,
39
- position,
40
- source,
41
- known48EdgeCleanupMinSize = DEFAULT_KNOWN_48_EDGE_CLEANUP_MIN_SIZE,
42
- known48EdgeCleanupMaxSize = DEFAULT_KNOWN_48_EDGE_CLEANUP_MAX_SIZE
43
- } = {}) {
44
- if (selectedTrial?.provenance?.previewAnchor === true) return false;
45
- const sourceText = String(source || '');
46
- const isStrongUndersizedAdaptive = shouldUseStrongUndersizedAdaptiveCleanup({
47
- selectedTrial,
48
- position,
49
- source
50
- });
51
- if (
52
- !isStrongUndersizedAdaptive &&
53
- (position?.width < known48EdgeCleanupMinSize || position?.width > known48EdgeCleanupMaxSize)
54
- ) return false;
55
- if (!isStrongUndersizedAdaptive && !isKnown48AnchorConfig(selectedTrial?.config, {
56
- known48EdgeCleanupMinSize,
57
- known48EdgeCleanupMaxSize
58
- })) return false;
59
-
60
- if (isStrongUndersizedAdaptive) return true;
61
- return sourceText === 'standard' ||
62
- sourceText.startsWith('standard+gain') ||
63
- sourceText.includes('catalog') ||
64
- sourceText.includes('fixed-local');
65
- }
66
-
67
- export function shouldUseStrongUndersizedAdaptiveCleanup({
68
- selectedTrial,
69
- position,
70
- source
71
- } = {}) {
72
- if (selectedTrial?.provenance?.previewAnchor === true) return false;
73
- const sourceText = String(source || '');
74
- return (
75
- selectedTrial?.provenance?.adaptive === true &&
76
- selectedTrial?.provenance?.strongUndersizedMatch === true &&
77
- position?.width >= 38 &&
78
- position?.width <= 42 &&
79
- sourceText.startsWith('adaptive')
80
- );
81
- }
82
-
83
- export function isV2SmallAnchorConfig(
84
- config,
85
- { v2SmallEdgeCleanupSize = DEFAULT_V2_SMALL_EDGE_CLEANUP_SIZE } = {}
86
- ) {
87
- if (!config || config.logoSize !== v2SmallEdgeCleanupSize || config.alphaVariant !== 'v2') {
88
- return false;
89
- }
90
-
91
- const marginRight = Number(config.marginRight);
92
- const marginBottom = Number(config.marginBottom);
93
- return Number.isFinite(marginRight) &&
94
- Number.isFinite(marginBottom) &&
95
- marginRight >= 48 &&
96
- marginBottom >= 48;
97
- }
98
-
99
- export function shouldUseV2SmallEdgeCleanup({
100
- selectedTrial,
101
- position,
102
- source,
103
- v2SmallEdgeCleanupSize = DEFAULT_V2_SMALL_EDGE_CLEANUP_SIZE,
104
- v2SmallEdgeCleanupSizeTolerance = DEFAULT_V2_SMALL_EDGE_CLEANUP_SIZE_TOLERANCE
105
- } = {}) {
106
- if (selectedTrial?.provenance?.previewAnchor === true) return false;
107
- if (
108
- position?.width < v2SmallEdgeCleanupSize - v2SmallEdgeCleanupSizeTolerance ||
109
- position?.width > v2SmallEdgeCleanupSize + v2SmallEdgeCleanupSizeTolerance
110
- ) {
111
- return false;
112
- }
113
- if (!isV2SmallAnchorConfig(selectedTrial?.config, { v2SmallEdgeCleanupSize })) return false;
114
- if (selectedTrial?.provenance?.catalogFamily !== 'gemini-v2-small') return false;
115
-
116
- const sourceText = String(source || '');
117
- return sourceText.includes('catalog');
118
- }
119
-
120
- export function createRepairCleanupFlags({
121
- selectedTrial,
122
- position,
123
- source,
124
- previewEdgeCleanupMaxSize = DEFAULT_PREVIEW_EDGE_CLEANUP_MAX_SIZE,
125
- known48EdgeCleanupMinSize = DEFAULT_KNOWN_48_EDGE_CLEANUP_MIN_SIZE,
126
- known48EdgeCleanupMaxSize = DEFAULT_KNOWN_48_EDGE_CLEANUP_MAX_SIZE,
127
- v2SmallEdgeCleanupSize = DEFAULT_V2_SMALL_EDGE_CLEANUP_SIZE,
128
- v2SmallEdgeCleanupSizeTolerance = DEFAULT_V2_SMALL_EDGE_CLEANUP_SIZE_TOLERANCE
129
- } = {}) {
130
- return {
131
- usePreviewAnchorFastCleanup: shouldUsePreviewAnchorFastCleanup(selectedTrial, position, {
132
- previewEdgeCleanupMaxSize
133
- }),
134
- useKnown48EdgeCleanup: shouldUseKnown48EdgeCleanup({
135
- selectedTrial,
136
- position,
137
- source,
138
- known48EdgeCleanupMinSize,
139
- known48EdgeCleanupMaxSize
140
- }),
141
- useStrongUndersizedAdaptiveCleanup: shouldUseStrongUndersizedAdaptiveCleanup({
142
- selectedTrial,
143
- position,
144
- source
145
- }),
146
- useV2SmallEdgeCleanup: shouldUseV2SmallEdgeCleanup({
147
- selectedTrial,
148
- position,
149
- source,
150
- v2SmallEdgeCleanupSize,
151
- v2SmallEdgeCleanupSizeTolerance
152
- })
153
- };
154
- }
1
+ const DEFAULT_PREVIEW_EDGE_CLEANUP_MAX_SIZE = 32;
2
+ const DEFAULT_KNOWN_48_EDGE_CLEANUP_MIN_SIZE = 40;
3
+ const DEFAULT_KNOWN_48_EDGE_CLEANUP_MAX_SIZE = 56;
4
+ const DEFAULT_V2_SMALL_EDGE_CLEANUP_SIZE = 36;
5
+ const DEFAULT_V2_SMALL_EDGE_CLEANUP_SIZE_TOLERANCE = 2;
6
+
7
+ export function shouldUsePreviewAnchorFastCleanup(
8
+ selectedTrial,
9
+ position,
10
+ { previewEdgeCleanupMaxSize = DEFAULT_PREVIEW_EDGE_CLEANUP_MAX_SIZE } = {}
11
+ ) {
12
+ return selectedTrial?.provenance?.previewAnchor === true &&
13
+ position?.width >= 24 &&
14
+ position?.width <= previewEdgeCleanupMaxSize;
15
+ }
16
+
17
+ export function isKnown48AnchorConfig(
18
+ config,
19
+ {
20
+ known48EdgeCleanupMinSize = DEFAULT_KNOWN_48_EDGE_CLEANUP_MIN_SIZE,
21
+ known48EdgeCleanupMaxSize = DEFAULT_KNOWN_48_EDGE_CLEANUP_MAX_SIZE
22
+ } = {}
23
+ ) {
24
+ if (!config || config.logoSize < known48EdgeCleanupMinSize || config.logoSize > known48EdgeCleanupMaxSize) {
25
+ return false;
26
+ }
27
+
28
+ const marginRight = Number(config.marginRight);
29
+ const marginBottom = Number(config.marginBottom);
30
+ if (!Number.isFinite(marginRight) || !Number.isFinite(marginBottom)) return false;
31
+
32
+ const isCurrentLargeMargin = Math.abs(marginRight - 96) <= 2 && Math.abs(marginBottom - 96) <= 2;
33
+ const isCurrentStandardMargin = marginRight >= 28 && marginRight <= 36 && marginBottom >= 28 && marginBottom <= 36;
34
+ return isCurrentLargeMargin || isCurrentStandardMargin;
35
+ }
36
+
37
+ export function shouldUseKnown48EdgeCleanup({
38
+ selectedTrial,
39
+ position,
40
+ source,
41
+ known48EdgeCleanupMinSize = DEFAULT_KNOWN_48_EDGE_CLEANUP_MIN_SIZE,
42
+ known48EdgeCleanupMaxSize = DEFAULT_KNOWN_48_EDGE_CLEANUP_MAX_SIZE
43
+ } = {}) {
44
+ if (selectedTrial?.provenance?.previewAnchor === true) return false;
45
+ const sourceText = String(source || '');
46
+ const isStrongUndersizedAdaptive = shouldUseStrongUndersizedAdaptiveCleanup({
47
+ selectedTrial,
48
+ position,
49
+ source
50
+ });
51
+ if (
52
+ !isStrongUndersizedAdaptive &&
53
+ (position?.width < known48EdgeCleanupMinSize || position?.width > known48EdgeCleanupMaxSize)
54
+ ) return false;
55
+ if (!isStrongUndersizedAdaptive && !isKnown48AnchorConfig(selectedTrial?.config, {
56
+ known48EdgeCleanupMinSize,
57
+ known48EdgeCleanupMaxSize
58
+ })) return false;
59
+
60
+ if (isStrongUndersizedAdaptive) return true;
61
+ return sourceText === 'standard' ||
62
+ sourceText.startsWith('standard+gain') ||
63
+ sourceText.includes('catalog') ||
64
+ sourceText.includes('fixed-local');
65
+ }
66
+
67
+ export function shouldUseStrongUndersizedAdaptiveCleanup({
68
+ selectedTrial,
69
+ position,
70
+ source
71
+ } = {}) {
72
+ if (selectedTrial?.provenance?.previewAnchor === true) return false;
73
+ const sourceText = String(source || '');
74
+ return (
75
+ selectedTrial?.provenance?.adaptive === true &&
76
+ selectedTrial?.provenance?.strongUndersizedMatch === true &&
77
+ position?.width >= 38 &&
78
+ position?.width <= 42 &&
79
+ sourceText.startsWith('adaptive')
80
+ );
81
+ }
82
+
83
+ export function isV2SmallAnchorConfig(
84
+ config,
85
+ { v2SmallEdgeCleanupSize = DEFAULT_V2_SMALL_EDGE_CLEANUP_SIZE } = {}
86
+ ) {
87
+ if (!config || config.logoSize !== v2SmallEdgeCleanupSize || config.alphaVariant !== 'v2') {
88
+ return false;
89
+ }
90
+
91
+ const marginRight = Number(config.marginRight);
92
+ const marginBottom = Number(config.marginBottom);
93
+ return Number.isFinite(marginRight) &&
94
+ Number.isFinite(marginBottom) &&
95
+ marginRight >= 48 &&
96
+ marginBottom >= 48;
97
+ }
98
+
99
+ export function shouldUseV2SmallEdgeCleanup({
100
+ selectedTrial,
101
+ position,
102
+ source,
103
+ v2SmallEdgeCleanupSize = DEFAULT_V2_SMALL_EDGE_CLEANUP_SIZE,
104
+ v2SmallEdgeCleanupSizeTolerance = DEFAULT_V2_SMALL_EDGE_CLEANUP_SIZE_TOLERANCE
105
+ } = {}) {
106
+ if (selectedTrial?.provenance?.previewAnchor === true) return false;
107
+ if (
108
+ position?.width < v2SmallEdgeCleanupSize - v2SmallEdgeCleanupSizeTolerance ||
109
+ position?.width > v2SmallEdgeCleanupSize + v2SmallEdgeCleanupSizeTolerance
110
+ ) {
111
+ return false;
112
+ }
113
+ if (!isV2SmallAnchorConfig(selectedTrial?.config, { v2SmallEdgeCleanupSize })) return false;
114
+ if (selectedTrial?.provenance?.catalogFamily !== 'gemini-v2-small') return false;
115
+
116
+ const sourceText = String(source || '');
117
+ return sourceText.includes('catalog');
118
+ }
119
+
120
+ export function createRepairCleanupFlags({
121
+ selectedTrial,
122
+ position,
123
+ source,
124
+ previewEdgeCleanupMaxSize = DEFAULT_PREVIEW_EDGE_CLEANUP_MAX_SIZE,
125
+ known48EdgeCleanupMinSize = DEFAULT_KNOWN_48_EDGE_CLEANUP_MIN_SIZE,
126
+ known48EdgeCleanupMaxSize = DEFAULT_KNOWN_48_EDGE_CLEANUP_MAX_SIZE,
127
+ v2SmallEdgeCleanupSize = DEFAULT_V2_SMALL_EDGE_CLEANUP_SIZE,
128
+ v2SmallEdgeCleanupSizeTolerance = DEFAULT_V2_SMALL_EDGE_CLEANUP_SIZE_TOLERANCE
129
+ } = {}) {
130
+ return {
131
+ usePreviewAnchorFastCleanup: shouldUsePreviewAnchorFastCleanup(selectedTrial, position, {
132
+ previewEdgeCleanupMaxSize
133
+ }),
134
+ useKnown48EdgeCleanup: shouldUseKnown48EdgeCleanup({
135
+ selectedTrial,
136
+ position,
137
+ source,
138
+ known48EdgeCleanupMinSize,
139
+ known48EdgeCleanupMaxSize
140
+ }),
141
+ useStrongUndersizedAdaptiveCleanup: shouldUseStrongUndersizedAdaptiveCleanup({
142
+ selectedTrial,
143
+ position,
144
+ source
145
+ }),
146
+ useV2SmallEdgeCleanup: shouldUseV2SmallEdgeCleanup({
147
+ selectedTrial,
148
+ position,
149
+ source,
150
+ v2SmallEdgeCleanupSize,
151
+ v2SmallEdgeCleanupSizeTolerance
152
+ })
153
+ };
154
+ }