コード例 #1
0
ファイル: Label.cs プロジェクト: toyotallday/MediaPortal-2
        public override void RenderOverride(RenderContext localRenderContext)
        {
            base.RenderOverride(localRenderContext);

            AllocFont();

            HorizontalTextAlignEnum horzAlign = HorizontalTextAlignEnum.Left;

            if (HorizontalContentAlignment == HorizontalAlignmentEnum.Right)
            {
                horzAlign = HorizontalTextAlignEnum.Right;
            }
            else if (HorizontalContentAlignment == HorizontalAlignmentEnum.Center)
            {
                horzAlign = HorizontalTextAlignEnum.Center;
            }

            VerticalTextAlignEnum vertAlign = VerticalTextAlignEnum.Top;

            if (VerticalContentAlignment == VerticalAlignmentEnum.Bottom)
            {
                vertAlign = VerticalTextAlignEnum.Bottom;
            }
            else if (VerticalContentAlignment == VerticalAlignmentEnum.Center)
            {
                vertAlign = VerticalTextAlignEnum.Center;
            }

            Color4 color = ColorConverter.FromColor(Color);

            color.Alpha *= (float)localRenderContext.Opacity;

            _asset.Render(_innerRect, horzAlign, vertAlign, color, Wrap, true, localRenderContext.ZOrder,
                          Scroll, (float)ScrollSpeed, (float)ScrollDelay, localRenderContext.Transform);
        }
コード例 #2
0
        public override void RenderOverride(RenderContext localRenderContext)
        {
            base.RenderOverride(localRenderContext);
            AllocFont();

            HorizontalTextAlignEnum horzAlign = HorizontalTextAlignEnum.Left;

            if (HorizontalContentAlignment == HorizontalAlignmentEnum.Right)
            {
                horzAlign = HorizontalTextAlignEnum.Right;
            }
            else if (HorizontalContentAlignment == HorizontalAlignmentEnum.Center)
            {
                horzAlign = HorizontalTextAlignEnum.Center;
            }

            VerticalTextAlignEnum vertAlign = VerticalTextAlignEnum.Top;

            if (VerticalContentAlignment == VerticalAlignmentEnum.Bottom)
            {
                vertAlign = VerticalTextAlignEnum.Bottom;
            }
            else if (VerticalContentAlignment == VerticalAlignmentEnum.Center)
            {
                vertAlign = VerticalTextAlignEnum.Center;
            }

            Color4 color = ColorConverter.FromColor(Color);

            color.Alpha *= (float)localRenderContext.Opacity;

            // Update text cursor
            if ((_cursorShapeInvalid || _cursorBrushInvalid) && CursorState == TextCursorState.Visible)
            {
                string textBeforeCaret = VisibleText;
                textBeforeCaret = string.IsNullOrEmpty(textBeforeCaret) ? string.Empty : textBeforeCaret.Substring(0, CaretIndex);
                float caretX     = _asset.TextWidth(textBeforeCaret);
                float textHeight = _asset.TextHeight(1);
                float textInsetY;
                switch (vertAlign)
                {
                case VerticalTextAlignEnum.Bottom:
                    textInsetY = _innerRect.Height - textHeight;
                    break;

                case VerticalTextAlignEnum.Center:
                    textInsetY = (_innerRect.Height - textHeight) / 2;
                    break;

                default: // VerticalTextAlignEnum.Top
                    textInsetY = 0;
                    break;
                }
                if (_virtualPosition + caretX < 10)
                {
                    _virtualPosition = _innerRect.Width / 3 - caretX;
                }
                if (_virtualPosition + caretX > _innerRect.Width - 10)
                {
                    _virtualPosition = _innerRect.Width * 2 / 3 - caretX;
                }
                Bound(ref _virtualPosition, -caretX, 0);
                RectangleF cursorBounds = new RectangleF(_innerRect.X + _virtualPosition + caretX, _innerRect.Y + textInsetY, CURSOR_THICKNESS, textHeight);
                UpdateCursorShape(cursorBounds, localRenderContext.ZOrder);
            }

            // Render text
            _asset.Render(_innerRect, horzAlign, vertAlign, _virtualPosition, color, localRenderContext.ZOrder, localRenderContext.Transform);

            // Render text cursor
            if (_cursorBrush != null && CursorState == TextCursorState.Visible)
            {
                _cursorBrush.BeginRenderBrush(_cursorContext, localRenderContext);
                _cursorContext.Render(0);
                _cursorBrush.EndRender();
            }
        }
コード例 #3
0
ファイル: TextBuffer.cs プロジェクト: pacificIT/MediaPortal-2
    /// <summary>
    /// Simplified render method to draw the text with a given text offset. This can be used for text edit controls where the text is
    /// shifted horizontally against its textbox.
    /// </summary>
    /// <param name="textBox">The box where the text should be drawn.</param>
    /// <param name="horzAlignment">The horizontal alignment.</param>
    /// <param name="vertAlignment">The vertical alignment.</param>
    /// <param name="offsetX">Horizontal offset of the text in relation to its text box. A negative offset will make the text start left of its
    /// normal position.</param>
    /// <param name="color">The color.</param>
    /// <param name="zOrder">A value indicating the depth (and thus position in the visual heirachy) that this element should be rendered at.</param>
    /// <param name="finalTransform">The final combined layout/render-transform.</param>
    public void Render(RectangleF textBox, HorizontalTextAlignEnum horzAlignment, VerticalTextAlignEnum vertAlignment, float offsetX,
        Color4 color, float zOrder, Matrix finalTransform)
    {
      if (!IsAllocated || _lastWrap || _textChanged)
      {
        Allocate(textBox.Width, false);
        if (!IsAllocated)
          return;
      }

      // Prepare horizontal alignment info for shader. X is position offset, Y is multiplyer for line width.
      Vector4 alignParam;
      switch (horzAlignment)
      {
        case HorizontalTextAlignEnum.Center:
          alignParam = new Vector4(textBox.Width / 2.0f, -0.5f, zOrder, 1.0f);
          break;
        case HorizontalTextAlignEnum.Right:
          alignParam = new Vector4(textBox.Width, -1.0f, zOrder, 1.0f);
          break;
        //case TextAlignEnum.Left:
        default:
          alignParam = new Vector4(0.0f, 0.0f, zOrder, 1.0f);
          break;
      }
      // Do vertical alignment by adjusting yPosition
      float yPosition = 0.0f;
      switch (vertAlignment)
      {
        case VerticalTextAlignEnum.Bottom:
          yPosition = Math.Max(textBox.Height - _lastTextSize.Height, 0.0f);
          break;
        case VerticalTextAlignEnum.Center:
          yPosition += Math.Max((textBox.Height - _lastTextSize.Height) / 2.0f, 0.0f);
          break;
        //case TextAlignEnum.Top:
        // Do nothing
      }

      // No fading
      _effect = ContentManager.Instance.GetEffect(EFFECT_FONT);

      // Render
      _effect.Parameters[PARAM_COLOR] = color;
      _effect.Parameters[PARAM_ALIGNMENT] = alignParam;
      _effect.Parameters[PARAM_SCROLL_POSITION] = new Vector4(offsetX, yPosition, 0.0f, 0.0f);
      _effect.Parameters[PARAM_TEXT_RECT] = new Vector4(textBox.Left, textBox.Top, textBox.Width, textBox.Height);
      DoRender(finalTransform);
      _lastTimeUsed = SkinContext.FrameRenderingStartTime;
    }
コード例 #4
0
ファイル: TextBuffer.cs プロジェクト: pacificIT/MediaPortal-2
    /// <summary>
    /// Standard draw method for this text.
    /// </summary>
    /// <param name="textBox">The box where the text should be drawn.</param>
    /// <param name="horzAlignment">The horizontal alignment.</param>
    /// <param name="vertAlignment">The vertical alignment.</param>
    /// <param name="color">The color.</param>
    /// <param name="wrap">If <c>true</c> then text will be word-wrapped to fit the <paramref name="textBox"/>.</param>
    /// <param name="fade">If <c>true</c> then text will be faded at the edge of the <paramref name="textBox"/>.</param>
    /// <param name="zOrder">A value indicating the depth (and thus position in the visual heirachy) that this element should be rendered at.</param>
    /// <param name="scrollMode">Text scrolling behaviour.</param>
    /// <param name="scrollSpeed">Text scrolling speed in units (pixels at original skin size) per second.</param>
    /// <param name="scrollDelay">Text scrolling delay in seconds.</param>
    /// <param name="finalTransform">The final combined layout/render-transform.</param>
    public void Render(RectangleF textBox, HorizontalTextAlignEnum horzAlignment, VerticalTextAlignEnum vertAlignment, Color4 color,
        bool wrap, bool fade, float zOrder, TextScrollEnum scrollMode, float scrollSpeed, float scrollDelay, Matrix finalTransform)
    {
      if (!IsAllocated || wrap != _lastWrap || _textChanged || (wrap && textBox.Width != _lastTextBoxWidth))
      {
        Allocate(textBox.Width, wrap);
        if (!IsAllocated)
          return;
      }

      // Update scrolling
      TextScrollEnum actualScrollMode = scrollMode;
      if (scrollMode != TextScrollEnum.None && _lastTimeUsed != DateTime.MinValue)
        actualScrollMode = UpdateScrollPosition(textBox, scrollMode, scrollSpeed, scrollDelay);

      // Prepare horizontal alignment info for shader. X is position offset, Y is multiplyer for line width.
      Vector4 alignParam;
      switch (horzAlignment)
      {
        case HorizontalTextAlignEnum.Center:
          alignParam = new Vector4(textBox.Width / 2.0f, -0.5f, zOrder, 1.0f);
          break;
        case HorizontalTextAlignEnum.Right:
          alignParam = new Vector4(textBox.Width, -1.0f, zOrder, 1.0f);
          break;
        //case TextAlignEnum.Left:
        default:
          alignParam = new Vector4(0.0f, 0.0f, zOrder, 1.0f);
          break;
      }
      // Do vertical alignment by adjusting yPosition
      float yPosition = 0.0f;
      switch (vertAlignment)
      {
        case VerticalTextAlignEnum.Bottom:
          yPosition = Math.Max(textBox.Height - _lastTextSize.Height, 0.0f);
          break;
        case VerticalTextAlignEnum.Center:
          yPosition += Math.Max((textBox.Height - _lastTextSize.Height) / 2.0f, 0.0f);
          break;
        //case TextAlignEnum.Top:
        // Do nothing
      }

      // Do we need to add fading edges?
      Vector4 fadeBorder;
      if (fade && CalculateFadeBorder(actualScrollMode, textBox, horzAlignment, out fadeBorder))
      {
        _effect = ContentManager.Instance.GetEffect(EFFECT_FONT_FADE);
        _effect.Parameters[PARAM_FADE_BORDER] = fadeBorder;
      }
      else
        _effect = ContentManager.Instance.GetEffect(EFFECT_FONT);

      // Render
      _effect.Parameters[PARAM_COLOR] = color;
      _effect.Parameters[PARAM_ALIGNMENT] = alignParam;
      _effect.Parameters[PARAM_SCROLL_POSITION] = new Vector4(_scrollPos.X, _scrollPos.Y + yPosition, 0.0f, 0.0f);
      _effect.Parameters[PARAM_TEXT_RECT] = new Vector4(textBox.Left, textBox.Top, textBox.Width, textBox.Height);
      DoRender(finalTransform);

      // Because text wraps around before it is complete scrolled off the screen we may need to render a second copy 
      // to create the desired wrapping effect
      if (scrollMode != TextScrollEnum.None)
      {
        if (!float.IsNaN(_scrollWrapOffset.X))
        {
          _effect.Parameters[PARAM_SCROLL_POSITION] = new Vector4(_scrollPos.X + _scrollWrapOffset.X, _scrollPos.Y, 0.0f, 0.0f);
          DoRender(finalTransform);
        }
        else if (!float.IsNaN(_scrollWrapOffset.Y))
        {
          _effect.Parameters[PARAM_SCROLL_POSITION] = new Vector4(_scrollPos.X, _scrollPos.Y + _scrollWrapOffset.Y, 0.0f, 0.0f);
          DoRender(finalTransform);
        }
      }
      _lastTimeUsed = SkinContext.FrameRenderingStartTime;
    }
コード例 #5
0
        /// <summary>
        /// Simplified render method to draw the text with a given text offset. This can be used for text edit controls where the text is
        /// shifted horizontally against its textbox.
        /// </summary>
        /// <param name="textBox">The box where the text should be drawn.</param>
        /// <param name="horzAlignment">The horizontal alignment.</param>
        /// <param name="vertAlignment">The vertical alignment.</param>
        /// <param name="offsetX">Horizontal offset of the text in relation to its text box. A negative offset will make the text start left of its
        /// normal position.</param>
        /// <param name="color">The color.</param>
        /// <param name="zOrder">A value indicating the depth (and thus position in the visual heirachy) that this element should be rendered at.</param>
        /// <param name="finalTransform">The final combined layout/render-transform.</param>
        public void Render(RectangleF textBox, HorizontalTextAlignEnum horzAlignment, VerticalTextAlignEnum vertAlignment, float offsetX,
                           Color4 color, float zOrder, Matrix finalTransform)
        {
            if (!IsAllocated || _lastWrap || _textChanged)
            {
                Allocate(textBox.Width, false);
                if (!IsAllocated)
                {
                    return;
                }
            }

            // Prepare horizontal alignment info for shader. X is position offset, Y is multiplyer for line width.
            Vector4 alignParam;

            switch (horzAlignment)
            {
            case HorizontalTextAlignEnum.Center:
                alignParam = new Vector4(textBox.Width / 2.0f, -0.5f, zOrder, 1.0f);
                break;

            case HorizontalTextAlignEnum.Right:
                alignParam = new Vector4(textBox.Width, -1.0f, zOrder, 1.0f);
                break;

            //case TextAlignEnum.Left:
            default:
                alignParam = new Vector4(0.0f, 0.0f, zOrder, 1.0f);
                break;
            }
            // Do vertical alignment by adjusting yPosition
            float yPosition = 0.0f;

            switch (vertAlignment)
            {
            case VerticalTextAlignEnum.Bottom:
                yPosition = Math.Max(textBox.Height - _lastTextSize.Height, 0.0f);
                break;

            case VerticalTextAlignEnum.Center:
                yPosition += Math.Max((textBox.Height - _lastTextSize.Height) / 2.0f, 0.0f);
                break;
                //case TextAlignEnum.Top:
                // Do nothing
            }

            // No fading
            _effect = ContentManager.Instance.GetEffect(EFFECT_FONT);

            // Render
            _effect.Parameters[PARAM_COLOR]           = color;
            _effect.Parameters[PARAM_ALIGNMENT]       = alignParam;
            _effect.Parameters[PARAM_SCROLL_POSITION] = new Vector4(offsetX, yPosition, 0.0f, 0.0f);
            _effect.Parameters[PARAM_TEXT_RECT]       = new Vector4(textBox.Left, textBox.Top, textBox.Width, textBox.Height);
            DoRender(finalTransform);
            _lastTimeUsed = SkinContext.FrameRenderingStartTime;
        }
コード例 #6
0
        /// <summary>
        /// Standard draw method for this text.
        /// </summary>
        /// <param name="textBox">The box where the text should be drawn.</param>
        /// <param name="horzAlignment">The horizontal alignment.</param>
        /// <param name="vertAlignment">The vertical alignment.</param>
        /// <param name="color">The color.</param>
        /// <param name="wrap">If <c>true</c> then text will be word-wrapped to fit the <paramref name="textBox"/>.</param>
        /// <param name="fade">If <c>true</c> then text will be faded at the edge of the <paramref name="textBox"/>.</param>
        /// <param name="zOrder">A value indicating the depth (and thus position in the visual heirachy) that this element should be rendered at.</param>
        /// <param name="scrollMode">Text scrolling behaviour.</param>
        /// <param name="scrollSpeed">Text scrolling speed in units (pixels at original skin size) per second.</param>
        /// <param name="scrollDelay">Text scrolling delay in seconds.</param>
        /// <param name="finalTransform">The final combined layout/render-transform.</param>
        public void Render(RectangleF textBox, HorizontalTextAlignEnum horzAlignment, VerticalTextAlignEnum vertAlignment, Color4 color,
                           bool wrap, bool fade, float zOrder, TextScrollEnum scrollMode, float scrollSpeed, float scrollDelay, Matrix finalTransform)
        {
            if (!IsAllocated || wrap != _lastWrap || _textChanged || (wrap && textBox.Width != _lastTextBoxWidth))
            {
                Allocate(textBox.Width, wrap);
                if (!IsAllocated)
                {
                    return;
                }
            }

            // Update scrolling
            TextScrollEnum actualScrollMode = scrollMode;

            if (scrollMode != TextScrollEnum.None && _lastTimeUsed != DateTime.MinValue)
            {
                actualScrollMode = UpdateScrollPosition(textBox, scrollMode, scrollSpeed, scrollDelay);
            }

            // Prepare horizontal alignment info for shader. X is position offset, Y is multiplyer for line width.
            Vector4 alignParam;

            switch (horzAlignment)
            {
            case HorizontalTextAlignEnum.Center:
                alignParam = new Vector4(textBox.Width / 2.0f, -0.5f, zOrder, 1.0f);
                break;

            case HorizontalTextAlignEnum.Right:
                alignParam = new Vector4(textBox.Width, -1.0f, zOrder, 1.0f);
                break;

            //case TextAlignEnum.Left:
            default:
                alignParam = new Vector4(0.0f, 0.0f, zOrder, 1.0f);
                break;
            }
            // Do vertical alignment by adjusting yPosition
            float yPosition = 0.0f;

            switch (vertAlignment)
            {
            case VerticalTextAlignEnum.Bottom:
                yPosition = Math.Max(textBox.Height - _lastTextSize.Height, 0.0f);
                break;

            case VerticalTextAlignEnum.Center:
                yPosition += Math.Max((textBox.Height - _lastTextSize.Height) / 2.0f, 0.0f);
                break;
                //case TextAlignEnum.Top:
                // Do nothing
            }

            // Do we need to add fading edges?
            Vector4 fadeBorder;

            if (fade && CalculateFadeBorder(actualScrollMode, textBox, horzAlignment, out fadeBorder))
            {
                _effect = ContentManager.Instance.GetEffect(EFFECT_FONT_FADE);
                _effect.Parameters[PARAM_FADE_BORDER] = fadeBorder;
            }
            else
            {
                _effect = ContentManager.Instance.GetEffect(EFFECT_FONT);
            }

            // Render
            _effect.Parameters[PARAM_COLOR]           = color;
            _effect.Parameters[PARAM_ALIGNMENT]       = alignParam;
            _effect.Parameters[PARAM_SCROLL_POSITION] = new Vector4(_scrollPos.X, _scrollPos.Y + yPosition, 0.0f, 0.0f);
            _effect.Parameters[PARAM_TEXT_RECT]       = new Vector4(textBox.Left, textBox.Top, textBox.Width, textBox.Height);
            DoRender(finalTransform);

            // Because text wraps around before it is complete scrolled off the screen we may need to render a second copy
            // to create the desired wrapping effect
            if (scrollMode != TextScrollEnum.None)
            {
                if (!float.IsNaN(_scrollWrapOffset.X))
                {
                    _effect.Parameters[PARAM_SCROLL_POSITION] = new Vector4(_scrollPos.X + _scrollWrapOffset.X, _scrollPos.Y, 0.0f, 0.0f);
                    DoRender(finalTransform);
                }
                else if (!float.IsNaN(_scrollWrapOffset.Y))
                {
                    _effect.Parameters[PARAM_SCROLL_POSITION] = new Vector4(_scrollPos.X, _scrollPos.Y + _scrollWrapOffset.Y, 0.0f, 0.0f);
                    DoRender(finalTransform);
                }
            }
            _lastTimeUsed = SkinContext.FrameRenderingStartTime;
        }
コード例 #7
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))
                    {
                        // 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();
            }
        }
コード例 #8
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();
            }
        }