public void DrawOverlay(Surface targetSurface) { Texture subTexture; Subtitle currentSubtitle; lock (_syncObj) { currentSubtitle = _currentSubtitle; subTexture = _subTexture; // Available sub is not due if (currentSubtitle == null || !currentSubtitle.ShouldDraw) { return; } if (targetSurface == null || targetSurface.Disposed || subTexture == null) { if (_drawCount > 0) { ServiceRegistration.Get <ILogger>().Debug("Draw count for last sub: {0}", _drawCount); } _drawCount = 0; return; } _drawCount++; } try { if (!subTexture.Disposed) { // TemporaryRenderTarget changes RenderTarget to texture and restores settings when done (Dispose) using (new TemporaryRenderTarget(targetSurface)) using (TemporaryRenderState temporaryRenderState = new TemporaryRenderState()) using (Sprite sprite = new Sprite(_device)) { sprite.Begin(SpriteFlags.AlphaBlend); // No alpha test here, allow all values temporaryRenderState.SetTemporaryRenderState(RenderState.AlphaTestEnable, 0); // Use the SourceAlpha channel and InverseSourceAlpha for destination temporaryRenderState.SetTemporaryRenderState(RenderState.BlendOperation, (int)BlendOperation.Add); temporaryRenderState.SetTemporaryRenderState(RenderState.SourceBlend, (int)Blend.SourceAlpha); temporaryRenderState.SetTemporaryRenderState(RenderState.DestinationBlend, (int)Blend.InverseSourceAlpha); // Check the target texture dimensions and adjust scaling and translation SurfaceDescription desc = targetSurface.Description; Matrix transform = Matrix.Identity; transform *= Matrix.Translation(currentSubtitle.HorizontalPosition, currentSubtitle.FirstScanLine, 0); // Subtitle could be smaller for 16:9 anamorphic video (subtitle width: 720, video texture: 1024) // then we need to scale the subtitle width also. if (currentSubtitle.ScreenWidth != desc.Width) { transform *= Matrix.Scaling((float)desc.Width / currentSubtitle.ScreenWidth, 1, 1); } sprite.Transform = transform; sprite.Draw(subTexture, Color.White); sprite.End(); } } } catch (Exception ex) { ServiceRegistration.Get <ILogger>().Debug("Error in DrawOverlay", ex); } if (_onTextureInvalidated != null) { _onTextureInvalidated(); } }
public void DrawOverlay(Texture targetTexture) { Subtitle currentSubtitle; lock (_syncObj) { currentSubtitle = _subtitles.ToList().FirstOrDefault(s => s.ShouldDraw); if (currentSubtitle == null) { return; } try { // TemporaryRenderTarget changes RenderTarget to texture and restores settings when done (Dispose) using (new TemporaryRenderTarget(targetTexture)) { // Check the target texture dimensions and adjust scaling and translation SurfaceDescription desc = targetTexture.GetLevelDescription(0); Matrix transform = Matrix.Identity; // Position subtitle and scale it to match video frame size, if required transform *= Matrix.Translation(currentSubtitle.HorizontalPosition, currentSubtitle.FirstScanLine, 0); if (currentSubtitle.ScreenWidth != desc.Width || currentSubtitle.ScreenHeight != desc.Height) { var factorW = (float)desc.Width / currentSubtitle.ScreenWidth; var factorH = (float)desc.Height / currentSubtitle.ScreenHeight; transform *= Matrix.Scaling(factorW, factorH, 1); } if (!string.IsNullOrWhiteSpace(currentSubtitle.Text)) { // TODO: this calculation works at the moment only in fullscreen mode. When using windowed mode, the text is off screen on bottom and not visible. // Calculate font size by the available target height divided by the number of teletext lines (25). float fontSize = (float)Math.Floor(desc.Height / 25f); if (_textBuffer == null) { _textBuffer = new TextBuffer(FontManager.DefaultFontFamily, fontSize); } _textBuffer.Text = currentSubtitle.Text; RectangleF rectangleF = new RectangleF(0, 0, desc.Width, desc.Height); HorizontalTextAlignEnum horzAlign = HorizontalTextAlignEnum.Center; VerticalTextAlignEnum vertAlign = VerticalTextAlignEnum.Top; // Render "glow" var offset = 1f; _textBuffer.Render(rectangleF, horzAlign, vertAlign, 0, Color4.Black, 0, transform * Matrix.Translation(-offset, 0f, 0)); _textBuffer.Render(rectangleF, horzAlign, vertAlign, 0, Color4.Black, 0, transform * Matrix.Translation(-offset, -offset, 0)); _textBuffer.Render(rectangleF, horzAlign, vertAlign, 0, Color4.Black, 0, transform * Matrix.Translation(0.0f, offset, 0)); _textBuffer.Render(rectangleF, horzAlign, vertAlign, 0, Color4.Black, 0, transform * Matrix.Translation(offset, offset, 0)); // Text _textBuffer.Render(rectangleF, horzAlign, vertAlign, 0, Color4.White, 0, transform); } else { using (TemporaryRenderState temporaryRenderState = new TemporaryRenderState()) { // No alpha test here, allow all values temporaryRenderState.SetTemporaryRenderState(RenderState.AlphaTestEnable, 0); // Use the SourceAlpha channel and InverseSourceAlpha for destination temporaryRenderState.SetTemporaryRenderState(RenderState.BlendOperation, (int)BlendOperation.Add); temporaryRenderState.SetTemporaryRenderState(RenderState.SourceBlend, (int)Blend.SourceAlpha); temporaryRenderState.SetTemporaryRenderState(RenderState.DestinationBlend, (int)Blend.InverseSourceAlpha); if (currentSubtitle.SubTexture != null && !currentSubtitle.SubTexture.IsDisposed) { _sprite.Begin(SpriteFlags.AlphaBlend); _sprite.Transform = transform; _sprite.Draw(currentSubtitle.SubTexture, SharpDX.Color.White); _sprite.End(); } } } } } catch (Exception ex) { ServiceRegistration.Get <ILogger>().Debug("Error in DrawOverlay", ex); } _onTextureInvalidated?.Invoke(); } }
public void DrawOverlay(Texture targetTexture) { Subtitle currentSubtitle; lock (_syncObj) { currentSubtitle = _subtitles.ToList().FirstOrDefault(s => s.ShouldDraw); if (currentSubtitle == null) { return; } if (targetTexture == null || targetTexture.IsDisposed || currentSubtitle.SubTexture == null || currentSubtitle.SubTexture.IsDisposed) { if (_drawCount > 0) { ServiceRegistration.Get <ILogger>().Debug("Draw count for last sub: {0}", _drawCount); } _drawCount = 0; return; } _drawCount++; } try { // TemporaryRenderTarget changes RenderTarget to texture and restores settings when done (Dispose) using (new TemporaryRenderTarget(targetTexture)) using (TemporaryRenderState temporaryRenderState = new TemporaryRenderState()) using (Sprite sprite = new Sprite(_device)) { sprite.Begin(SpriteFlags.AlphaBlend); // No alpha test here, allow all values temporaryRenderState.SetTemporaryRenderState(RenderState.AlphaTestEnable, 0); // Use the SourceAlpha channel and InverseSourceAlpha for destination temporaryRenderState.SetTemporaryRenderState(RenderState.BlendOperation, (int)BlendOperation.Add); temporaryRenderState.SetTemporaryRenderState(RenderState.SourceBlend, (int)Blend.SourceAlpha); temporaryRenderState.SetTemporaryRenderState(RenderState.DestinationBlend, (int)Blend.InverseSourceAlpha); // Check the target texture dimensions and adjust scaling and translation SurfaceDescription desc = targetTexture.GetLevelDescription(0); Matrix transform = Matrix.Identity; // Position subtitle and scale it to match video frame size, if required transform *= Matrix.Translation(currentSubtitle.HorizontalPosition, currentSubtitle.FirstScanLine, 0); if (currentSubtitle.ScreenWidth != desc.Width || currentSubtitle.ScreenHeight != desc.Height) { var factorW = (float)desc.Width / currentSubtitle.ScreenWidth; var factorH = (float)desc.Height / currentSubtitle.ScreenHeight; transform *= Matrix.Scaling(factorW, factorH, 1); } sprite.Transform = transform; sprite.Draw(currentSubtitle.SubTexture, SharpDX.Color.White); sprite.End(); } if (_onTextureInvalidated != null) { _onTextureInvalidated(); } } catch (Exception ex) { ServiceRegistration.Get <ILogger>().Debug("Error in DrawOverlay", ex); } }
public void DrawOverlay(Texture targetTexture) { Subtitle currentSubtitle; lock (_syncObj) { currentSubtitle = _subtitles.ToList().FirstOrDefault(s => s.ShouldDraw); if (currentSubtitle == null) { return; } try { // TemporaryRenderTarget changes RenderTarget to texture and restores settings when done (Dispose) using (new TemporaryRenderTarget(targetTexture)) { Matrix transform = Matrix.Identity; // Position subtitle transform *= Matrix.Translation(currentSubtitle.HorizontalPosition, currentSubtitle.FirstScanLine, 0); if (!string.IsNullOrWhiteSpace(currentSubtitle.Text)) { // Calculate font size by the available target height divided by the number of teletext lines (25). float fontSize = (float)Math.Floor(SkinContext.WindowSize.Height / 25f); if (_textBuffer == null) { _textBuffer = new TextBuffer(FontManager.DefaultFontFamily, fontSize); } _textBuffer.Text = currentSubtitle.Text; RectangleF rectangleF = new RectangleF(0, 0, SkinContext.WindowSize.Width, SkinContext.WindowSize.Height); HorizontalTextAlignEnum horzAlign = HorizontalTextAlignEnum.Center; VerticalTextAlignEnum vertAlign = VerticalTextAlignEnum.Top; // Render "glow" var offset = 1f; _textBuffer.Render(rectangleF, horzAlign, vertAlign, 0, Color4.Black, 0, transform * Matrix.Translation(-offset, 0f, 0)); _textBuffer.Render(rectangleF, horzAlign, vertAlign, 0, Color4.Black, 0, transform * Matrix.Translation(-offset, -offset, 0)); _textBuffer.Render(rectangleF, horzAlign, vertAlign, 0, Color4.Black, 0, transform * Matrix.Translation(0.0f, offset, 0)); _textBuffer.Render(rectangleF, horzAlign, vertAlign, 0, Color4.Black, 0, transform * Matrix.Translation(offset, offset, 0)); // Text _textBuffer.Render(rectangleF, horzAlign, vertAlign, 0, Color4.White, 0, transform); } else { using (TemporaryRenderState temporaryRenderState = new TemporaryRenderState()) { // No alpha test here, allow all values temporaryRenderState.SetTemporaryRenderState(RenderState.AlphaTestEnable, 0); // Use the SourceAlpha channel and InverseSourceAlpha for destination temporaryRenderState.SetTemporaryRenderState(RenderState.BlendOperation, (int)BlendOperation.Add); temporaryRenderState.SetTemporaryRenderState(RenderState.SourceBlend, (int)Blend.SourceAlpha); temporaryRenderState.SetTemporaryRenderState(RenderState.DestinationBlend, (int)Blend.InverseSourceAlpha); if (currentSubtitle.SubTexture != null && !currentSubtitle.SubTexture.IsDisposed) { _sprite.Begin(SpriteFlags.AlphaBlend); _sprite.Transform = transform; _sprite.Draw(currentSubtitle.SubTexture, SharpDX.Color.White); _sprite.End(); } } } } } catch (Exception ex) { ServiceRegistration.Get <ILogger>().Debug("Error in DrawOverlay", ex); } _onTextureInvalidated?.Invoke(); } }