Ejemplo n.º 1
0
/// @brief Actually process subtitles
///
void DialogTimingProcessor::Process() {
    SortDialogues();
    int rows = Sorted.size();

    // Options
    long inVal = 0;
    long outVal = 0;
    leadIn->GetValue().ToLong(&inVal);
    leadOut->GetValue().ToLong(&outVal);
    bool addIn = hasLeadIn->IsChecked() && inVal;
    bool addOut = hasLeadOut->IsChecked() && outVal;

    // Add lead-in/out
    if (addIn || addOut) {
        for (int i=0; i<rows; i++) {
            AssDialogue *cur = Sorted[i];

            // Compare to every previous line (yay for O(n^2)!) to see if it's OK to add lead-in
            if (inVal) {
                int startLead = cur->Start.GetMS() - inVal;
                for (int j=0; j<i; j++) {
                    AssDialogue *comp = Sorted[j];

                    // Check if they don't already collide (ignore it in that case)
                    if (cur->CollidesWith(comp)) continue;

                    // Get comparison times
                    startLead = std::max(startLead, comp->End.GetMS());
                }
                cur->Start.SetMS(startLead);
            }

            // Compare to every line to see how far can lead-out be extended
            if (outVal) {
                int endLead = cur->End.GetMS() + outVal;
                for (int j=i+1; j<rows; j++) {
                    AssDialogue *comp = Sorted[j];

                    // Check if they don't already collide (ignore it in that case)
                    if (cur->CollidesWith(comp)) continue;

                    // Get comparison times
                    endLead = std::min(endLead, comp->Start.GetMS());
                }
                cur->End.SetMS(endLead);
            }
        }
    }

    // Make adjacent
    if (adjsEnable->IsChecked()) {
        AssDialogue *prev = Sorted.front();

        long adjsThres = 0;
        adjacentThres->GetValue().ToLong(&adjsThres);

        float bias = adjacentBias->GetValue() / 100.0;

        for (int i=1; i < rows; i++) {
            AssDialogue *cur = Sorted[i];

            // Check if they don't collide
            if (cur->CollidesWith(prev)) continue;

            // Compare distance
            int curStart = cur->Start.GetMS();
            int prevEnd = prev->End.GetMS();
            int dist = curStart-prevEnd;
            if (dist > 0 && dist < adjsThres) {
                int setPos = prevEnd+int(dist*bias);
                cur->Start.SetMS(setPos);
                prev->End.SetMS(setPos);
            }

            prev = cur;
        }
    }

    // Keyframe snapping
    if (keysEnable->IsChecked()) {
        KeyFrames = c->videoController->GetKeyFrames();
        KeyFrames.push_back(c->videoController->GetLength() - 1);

        long beforeStart = 0;
        long afterStart = 0;
        long beforeEnd = 0;
        long afterEnd = 0;
        keysStartBefore->GetValue().ToLong(&beforeStart);
        keysStartAfter->GetValue().ToLong(&afterStart);
        keysEndBefore->GetValue().ToLong(&beforeEnd);
        keysEndAfter->GetValue().ToLong(&afterEnd);

        for (int i=0; i<rows; i++) {
            AssDialogue *cur = Sorted[i];

            // Get start/end frames
            int startF = c->videoController->FrameAtTime(cur->Start.GetMS(),agi::vfr::START);
            int endF = c->videoController->FrameAtTime(cur->End.GetMS(),agi::vfr::END);

            // Get closest for start
            int closest = GetClosestKeyFrame(startF);
            if ((closest > startF && closest-startF <= beforeStart) || (closest < startF && startF-closest <= afterStart)) {
                cur->Start.SetMS(c->videoController->TimeAtFrame(closest,agi::vfr::START));
            }

            // Get closest for end
            closest = GetClosestKeyFrame(endF)-1;
            if ((closest > endF && closest-endF <= beforeEnd) || (closest < endF && endF-closest <= afterEnd)) {
                cur->End.SetMS(c->videoController->TimeAtFrame(closest,agi::vfr::END));
            }
        }
    }

    // Update grid
    c->ass->Commit(_("timing processor"), AssFile::COMMIT_TIMES);
}
Ejemplo n.º 2
0
//////////////
// Draw image
void BaseGrid::DrawImage(wxDC &dc) {
	dc.BeginDrawing();

	// Get size and pos
	int w = 0;
	int h = 0;
	GetClientSize(&w,&h);

	// Set font
	dc.SetFont(font);

	// Clear background
	dc.SetBackground(wxBrush(Options.AsColour(_T("Grid Background"))));
	dc.Clear();

	// Draw labels
	dc.SetPen(*wxTRANSPARENT_PEN);
	dc.SetBrush(wxBrush(Options.AsColour(_T("Grid left column"))));
	dc.DrawRectangle(0,lineHeight,colWidth[0],h-lineHeight);

	// Visible lines
	int drawPerScreen = h/lineHeight + 1;
	int nDraw = MID(0,drawPerScreen,GetRows()-yPos);
	int maxH = (nDraw+1) * lineHeight;

	// Row colors
	std::vector<wxBrush> rowColors;
	std::vector<wxColor> foreColors;
	rowColors.push_back(wxBrush(Options.AsColour(_T("Grid Background"))));					// 0 = Standard
	foreColors.push_back(Options.AsColour(_T("Grid standard foreground")));
	rowColors.push_back(wxBrush(Options.AsColour(_T("Grid Header"))));						// 1 = Header
	foreColors.push_back(Options.AsColour(_T("Grid standard foreground")));
	rowColors.push_back(wxBrush(Options.AsColour(_T("Grid selection background"))));		// 2 = Selected
	foreColors.push_back(Options.AsColour(_T("Grid selection foreground")));
	rowColors.push_back(wxBrush(Options.AsColour(_T("Grid comment background"))));			// 3 = Commented
	foreColors.push_back(Options.AsColour(_T("Grid selection foreground")));
	rowColors.push_back(wxBrush(Options.AsColour(_T("Grid inframe background"))));			// 4 = Video Highlighted
	foreColors.push_back(Options.AsColour(_T("Grid selection foreground")));
	rowColors.push_back(wxBrush(Options.AsColour(_T("Grid selected comment background"))));	// 5 = Commented & selected
	foreColors.push_back(Options.AsColour(_T("Grid selection foreground")));

	// First grid row
	bool drawGrid = true;
	if (drawGrid) {
		dc.SetPen(wxPen(Options.AsColour(_T("Grid lines"))));
		dc.DrawLine(0,0,w,0);
		dc.SetPen(*wxTRANSPARENT_PEN);
	}

	// Draw rows
	int dx = 0;
	int dy = 0;
	int curColor = 0;
	AssDialogue *curDiag;
	for (int i=0;i<nDraw+1;i++) {
		// Prepare
		int curRow = i+yPos-1;
		curDiag = GetDialogue(curRow);
		dx = 0;
		dy = i*lineHeight;

		// Check for collisions
		bool collides = false;
		if (curDiag) {
			AssDialogue *sel = GetDialogue(editBox->linen);
			if (sel && sel != curDiag) {
				if (curDiag->CollidesWith(sel)) collides = true;
			}
		}

		// Text array
		wxArrayString strings;

		// Header
		if (i == 0) {
			strings.Add(_("#"));
			strings.Add(_("L"));
			strings.Add(_("Start"));
			strings.Add(_("End"));
			strings.Add(_("Style"));
			strings.Add(_("Actor"));
			strings.Add(_("Effect"));
			strings.Add(_("Left"));
			strings.Add(_("Right"));
			strings.Add(_("Vert"));
			strings.Add(_("Text"));
			curColor = 1;
		}

		// Lines
		else if (curDiag) {
			// Set fields
			strings.Add(wxString::Format(_T("%i"),curRow+1));
			strings.Add(wxString::Format(_T("%i"),curDiag->Layer));
			if (byFrame) {
				strings.Add(wxString::Format(_T("%i"),VFR_Output.GetFrameAtTime(curDiag->Start.GetMS(),true)));
				strings.Add(wxString::Format(_T("%i"),VFR_Output.GetFrameAtTime(curDiag->End.GetMS(),true)));
			}
			else {
				strings.Add(curDiag->Start.GetASSFormated());
				strings.Add(curDiag->End.GetASSFormated());
			}
			strings.Add(curDiag->Style);
			strings.Add(curDiag->Actor);
			strings.Add(curDiag->Effect);
			strings.Add(curDiag->GetMarginString(1));
			strings.Add(curDiag->GetMarginString(2));
			strings.Add(curDiag->GetMarginString(3));

			// Set text
			int mode = Options.AsInt(_T("Grid Hide Overrides"));
			wxString value = _T("");

			// Hidden overrides
			if (mode == 1 || mode == 2) {
				wxString replaceWith = Options.AsText(_T("Grid hide overrides char"));
				curDiag->ParseASSTags();
				size_t n = curDiag->Blocks.size();
				for (size_t i=0;i<n;i++) {
					AssDialogueBlock *block = curDiag->Blocks.at(i);
					AssDialogueBlockPlain *plain = AssDialogueBlock::GetAsPlain(block);
					if (plain) {
						value += plain->GetText();
					}
					else {
						if (mode == 1) {
							value += replaceWith;
						}
					}
				}
				curDiag->ClearBlocks();
			}

			// Show overrides
			else value = curDiag->Text;

			// Cap length and set text
			if (value.Length() > 512) value = value.Left(512) + _T("...");
			strings.Add(value);

			// Set color
			curColor = 0;
			bool inSel = IsInSelection(curRow,0);
			if (inSel && curDiag->Comment) curColor = 5;
			else if (inSel) curColor = 2;
			else if (curDiag->Comment) curColor = 3;
			else if (Options.AsBool(_T("Highlight subs in frame")) && IsDisplayed(curDiag)) curColor = 4;
		}

		else {
			for (int j=0;j<11;j++) strings.Add(_T("?"));
		}

		// Draw row background color
		if (curColor) {
			dc.SetBrush(rowColors[curColor]);
			dc.DrawRectangle((curColor == 1) ? 0 : colWidth[0],i*lineHeight+1,w,lineHeight);
		}

		// Set text color
		if (collides) dc.SetTextForeground(Options.AsColour(_T("Grid collision foreground")));
		else {
			dc.SetTextForeground(foreColors[curColor]);
		}

		// Draw text
		wxRect cur;
		bool isCenter;
		for (int j=0;j<11;j++) {
			// Is center?
			isCenter = !(j == 4 || j == 5 || j == 6 || j == 10);

			// Calculate clipping
			cur = wxRect(dx+4,dy,colWidth[j]-6,lineHeight);

			// Set clipping
			dc.DestroyClippingRegion();
			dc.SetClippingRegion(cur);

			// Draw
			dc.DrawLabel(strings[j],cur,isCenter ? wxALIGN_CENTER : (wxALIGN_CENTER_VERTICAL | wxALIGN_LEFT));
			dx += colWidth[j];
		}
		//if (collides) dc.SetPen(wxPen(wxColour(255,0,0)));

		// Draw grid
		dc.DestroyClippingRegion();
		if (drawGrid) {
			dc.SetPen(wxPen(Options.AsColour(_T("Grid lines"))));
			dc.DrawLine(0,dy+lineHeight,w,dy+lineHeight);
			dc.SetPen(*wxTRANSPARENT_PEN);
		}
	}

	// Draw grid columns
	dx = 0;
	if (drawGrid) {
		dc.SetPen(wxPen(Options.AsColour(_T("Grid lines"))));
		for (int i=0;i<10;i++) {
			dx += colWidth[i];
			dc.DrawLine(dx,0,dx,maxH);
		}
		dc.DrawLine(0,0,0,maxH);
		dc.DrawLine(w-1,0,w-1,h);
	}

	// Draw currently active line border
	dc.SetPen(wxPen(Options.AsColour(_T("Grid Active border"))));
	dc.SetBrush(*wxTRANSPARENT_BRUSH);
	dy = (editBox->linen+1-yPos) * lineHeight;
	dc.DrawRectangle(0,dy,w,lineHeight+1);

	// Done
	dc.EndDrawing();
}
//////////////////////////////
// Actually process subtitles
void DialogTimingProcessor::Process() {
	// Sort rows
	SortDialogues();
	int rows = Sorted.size();

	// Options
	long inVal = 0;
	long outVal = 0;
	leadIn->GetValue().ToLong(&inVal);
	leadOut->GetValue().ToLong(&outVal);
	bool addIn = hasLeadIn->IsChecked() && inVal;
	bool addOut = hasLeadOut->IsChecked() && outVal;

	// Add lead-in/out
	if (addIn || addOut) {
		// Variables
		AssDialogue *cur;
		AssDialogue *comp;
		int start,end;
		int startLead,endLead;
		int compStart,compEnd;

		// For each row
		for (int i=0;i<rows;i++) {
			// Get line and check if it's OK
			cur = GetSortedDialogue(i);

			// Set variables
			start = cur->Start.GetMS();
			end = cur->End.GetMS();
			if (addIn) startLead = start - inVal;
			else startLead = start;
			if (addOut) endLead = end + outVal;
			else endLead = end;

			// Compare to every previous line (yay for O(n^2)!) to see if it's OK to add lead-in
			if (addIn) {
				for (int j=0;j<i;j++) {
					comp = GetSortedDialogue(j);

					// Check if they don't already collide (ignore it in that case)
					if (cur->CollidesWith(comp)) continue;

					// Get comparison times
					compEnd = comp->End.GetMS();

					// Limit lead-in if needed
					if (compEnd > startLead) startLead = compEnd;
				}
			}

			// Compare to every line to see how far can lead-out be extended
			if (addOut) {
				for (int j=i+1;j<rows;j++) {
					comp = GetSortedDialogue(j);

					// Check if they don't already collide (ignore it in that case)
					if (cur->CollidesWith(comp)) continue;

					// Get comparison times
					compStart = comp->Start.GetMS();

					// Limit lead-in if needed
					if (compStart < endLead) endLead = compStart;
				}
			}

			// Set times
			cur->Start.SetMS(startLead);
			cur->End.SetMS(endLead);
			cur->UpdateData();
		}
	}

	// Make adjascent
	if (adjsEnable->IsChecked()) {
		// Variables
		AssDialogue *cur;
		AssDialogue *prev = NULL;
		int curStart,prevEnd;
		long adjsThres = 0;
		int dist;

		// Get threshold
		adjascentThres->GetValue().ToLong(&adjsThres);

		// Get bias
		float bias = adjascentBias->GetValue() / 100.0;

		// For each row
		for (int i=0;i<rows;i++) {
			// Get line and check if it's OK
			cur = GetSortedDialogue(i);

			// Check if previous is OK
			if (!prev) {
				prev = cur;
				continue;
			}

			// Check if they don't collide
			if (cur->CollidesWith(prev)) continue;

			// Compare distance
			curStart = cur->Start.GetMS();
			prevEnd = prev->End.GetMS();
			dist = curStart-prevEnd;
			if (dist > 0 && dist < adjsThres) {
				int setPos = prevEnd+int(dist*bias);
				cur->Start.SetMS(setPos);
				cur->UpdateData();
				prev->End.SetMS(setPos);
				prev->UpdateData();
			}

			// Set previous
			prev = cur;
		}
	}

	// Keyframe snapping
	if (keysEnable->IsChecked()) {
		// Get keyframes
		KeyFrames = grid->video->KeyFrames;
		KeyFrames.Add(grid->video->length-1);

		// Variables
		int startF,endF;
		int closest;
		bool changed;
		AssDialogue *cur;

		// Get variables
		long beforeStart = 0;
		long afterStart = 0;
		long beforeEnd = 0;
		long afterEnd = 0;
		keysStartBefore->GetValue().ToLong(&beforeStart);
		keysStartAfter->GetValue().ToLong(&afterStart);
		keysEndBefore->GetValue().ToLong(&beforeEnd);
		keysEndAfter->GetValue().ToLong(&afterEnd);
		
		// For each row
		for (int i=0;i<rows;i++) {
			// Get line and check if it's OK
			cur = GetSortedDialogue(i);

			// Get start/end frames
			startF = VFR_Output.GetFrameAtTime(cur->Start.GetMS(),true);
			endF = VFR_Output.GetFrameAtTime(cur->End.GetMS(),false);
			changed = false;

			// Get closest for start
			closest = GetClosestKeyFrame(startF);
			if ((closest > startF && closest-startF <= beforeStart) || (closest < startF && startF-closest <= afterStart)) {
				cur->Start.SetMS(VFR_Output.GetTimeAtFrame(closest,true));
				changed = true;
			}

			// Get closest for end
			closest = GetClosestKeyFrame(endF)-1;
			if ((closest > endF && closest-endF <= beforeEnd) || (closest < endF && endF-closest <= afterEnd)) {
				cur->End.SetMS(VFR_Output.GetTimeAtFrame(closest,false));
				changed = true;
			}

			// Apply changes
			if (changed) {
				cur->UpdateData();
			}
		}
	}

	// Update grid
	grid->ass->FlagAsModified();
	grid->CommitChanges();
}