Example #1
0
        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();
            }
        }
Example #3
0
        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);
            }
        }
Example #4
0
        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();
            }
        }