mirror of
https://github.com/ksyasuda/SubMiner.git
synced 2026-08-25 12:15:26 -07:00
fix(subtitles): preserve opaque text beside ASS texture fragments
- Require structural texture evidence before suppressing same-font fragments
This commit is contained in:
@@ -1265,6 +1265,21 @@ test('parseSubtitleCues drops clipped repeated-glyph texture text', () => {
|
||||
);
|
||||
});
|
||||
|
||||
test('parseSubtitleCues preserves opaque same-font text beside texture fragments', () => {
|
||||
const content = [
|
||||
'[Events]',
|
||||
'Format: Layer, Start, End, Style, Name, MarginL, MarginR, MarginV, Effect, Text',
|
||||
'Dialogue: 2,0:00:01.00,0:00:04.00,MarySigns,seed,0,0,0,,{\\pos(960,80)\\fnSerangkaian Pattern Regular\\clip(800,20,1120,140)}LLLLLLLLLLLLLLLLLLLLLLLL',
|
||||
'Dialogue: 2,0:00:01.00,0:00:04.00,MarySigns,piece,0,0,0,,{\\pos(960,110)\\fnSerangkaian Pattern Regular\\clip(800,20,1120,140)}LLLL',
|
||||
'Dialogue: 3,0:00:01.00,0:00:04.00,MarySigns,label,0,0,0,,{\\pos(960,150)\\fnSerangkaian Pattern Regular}Keep this label',
|
||||
].join('\n');
|
||||
|
||||
assert.deepEqual(
|
||||
parseSubtitleCues(content, 'test.ass').map((cue) => cue.text),
|
||||
['Keep this label'],
|
||||
);
|
||||
});
|
||||
|
||||
test('parseSubtitleCues drops clipped repeated-glyph texture text without a font override', () => {
|
||||
const content = [
|
||||
'[Events]',
|
||||
|
||||
@@ -1038,6 +1038,14 @@ function isNearlyTransparentPositionedText(cue: AnnotatedSubtitleCue): boolean {
|
||||
);
|
||||
}
|
||||
|
||||
function hasAssTextureCandidateEvidence(cue: AnnotatedSubtitleCue): boolean {
|
||||
return (
|
||||
isClippedRepeatedGlyphFragment(cue) ||
|
||||
isNearlyTransparentPositionedText(cue) ||
|
||||
hasStaticOverride(cue, '2a')
|
||||
);
|
||||
}
|
||||
|
||||
function assFontTextureGroupKey(cue: AnnotatedSubtitleCue): string | null {
|
||||
const font = staticFontOverride(cue);
|
||||
return font === null ? null : `${cue.style}\0${cue.startTime}\0${cue.endTime}\0${font}`;
|
||||
@@ -1050,9 +1058,9 @@ function assTextureTimingGroupKey(cue: AnnotatedSubtitleCue): string {
|
||||
function removeAssFontTextureEvents(events: ParsedAssEvents): ParsedAssEvents {
|
||||
const seeds = events.dialogue.filter(isAssTextureSeed);
|
||||
const seedSet = new Set(seeds);
|
||||
// Short pieces can share the seeded font effect under another actor without carrying
|
||||
// enough tags to identify themselves. The exact style, time, and font group catches
|
||||
// those pieces without inspecting their content.
|
||||
// Short pieces can share the seeded font effect under another actor. Matching the
|
||||
// seed's style, timing, and font only narrows the candidates; each piece must still
|
||||
// carry structural texture evidence.
|
||||
const textureGroups = new Set(
|
||||
seeds.map(assFontTextureGroupKey).filter((key): key is string => key !== null),
|
||||
);
|
||||
@@ -1090,7 +1098,7 @@ function removeAssFontTextureEvents(events: ParsedAssEvents): ParsedAssEvents {
|
||||
return false;
|
||||
}
|
||||
const key = assFontTextureGroupKey(cue);
|
||||
if (key !== null && textureGroups.has(key)) {
|
||||
if (key !== null && textureGroups.has(key) && hasAssTextureCandidateEvidence(cue)) {
|
||||
return false;
|
||||
}
|
||||
if (!isNearlyTransparentPositionedText(cue)) {
|
||||
|
||||
Reference in New Issue
Block a user