コード例 #1
0
ファイル: karaokelyricstext.cpp プロジェクト: Bobbin007/xbmc
bool CKaraokeLyricsText::InitGraphics()
{
  if ( m_lyrics.empty() )
    return false;

  CStdString fontPath = "special://xbmc/media/Fonts/" + g_guiSettings.GetString("karaoke.font");
  m_karaokeFont = g_fontManager.LoadTTF("__karaoke__", fontPath,
                  m_colorLyrics, 0, g_guiSettings.GetInt("karaoke.fontheight"), FONT_STYLE_BOLD );
  CGUIFont *karaokeBorder = g_fontManager.LoadTTF("__karaokeborder__", fontPath,
                            m_colorLyrics, 0, g_guiSettings.GetInt("karaoke.fontheight"), FONT_STYLE_BOLD, true );

  if ( !m_karaokeFont )
  {
    CLog::Log(LOGERROR, "CKaraokeLyricsText::PrepareGraphicsData - Unable to load subtitle font");
    return false;
  }

  m_karaokeLayout = new CGUITextLayout( m_karaokeFont, true, 0, karaokeBorder );
  m_preambleLayout = new CGUITextLayout( m_karaokeFont, true, 0, karaokeBorder );

  if ( !m_karaokeLayout || !m_preambleLayout )
  {
    delete m_preambleLayout;
    delete m_karaokeLayout;
    m_karaokeLayout = m_preambleLayout = 0;

    CLog::Log(LOGERROR, "CKaraokeLyricsText::PrepareGraphicsData - cannot create layout");
    return false;
  }

  rescanLyrics();

  m_indexNextPara = 0;

  // Generate next paragraph
  nextParagraph();

  m_lyricsState = STATE_WAITING;
  return true;
}
コード例 #2
0
ファイル: rstparser.cpp プロジェクト: MelroLeandro/gromacs
bool RstParagraphIterator::nextParagraph()
{
    begin_     = nextBegin_;
    type_      = eParagraphType_Normal;
    breakSize_ = nextBreakSize_;
    // Skip leading newlines (includes those separating paragraphs).
    while (begin_ < text_.length() && text_[begin_] == '\n')
    {
        ++begin_;
    }
    if (begin_ == text_.length())
    {
        end_       = begin_;
        breakSize_ = 0;
        nextBegin_ = begin_;
        return false;
    }
    if (literalIndent_ >= 0)
    {
        type_ = eParagraphType_Literal;
    }
    // Loop over lines in input until the end of the current paragraph.
    size_t i         = begin_;
    int    lineCount = 0;
    while (true)
    {
        const bool   bFirstLine = (lineCount == 0);
        const size_t lineStart  = i;
        const size_t lineEnd    = std::min(text_.find('\n', i), text_.length());
        const int    lineIndent = countLeadingSpace(text_, lineStart, lineEnd);
        const size_t textStart  = lineStart + lineIndent;
        const bool   bListItem  = startsListItem(text_, textStart);
        // Return each list item as a separate paragraph to make the behavior
        // the same always; the item text could even contain multiple
        // paragraphs, that would anyways produce breaks.
        if (bListItem && !bFirstLine)
        {
            // Since there was no empty line in input, do not produce one in
            // the output, either.
            nextBreakSize_ = 1;
            // end_ is not updated to break the paragraph before the current line.
            break;
        }
        // Now we will actually use this line as part of this paragraph.
        end_ = lineEnd;
        ++lineCount;
        // Update indentation.
        if (bFirstLine)
        {
            firstLineIndent_ = indent_ = lineIndent;
            if (bListItem)
            {
                // Find the indentation of the actual text after the
                // bullet/number.
                int prefixLength = 0;
                while (!std::isspace(text_[textStart + prefixLength]))
                {
                    ++prefixLength;
                }
                while (textStart + prefixLength < text_.length()
                       && std::isspace(text_[textStart + prefixLength]))
                {
                    ++prefixLength;
                }
                indent_ += prefixLength;
            }
        }
        else
        {
            indent_ = std::min(indent_, lineIndent);
        }
        // We need to check for the title underline before checking for the
        // paragraph break so that the title is correctly recognized.
        if (lineCount == 2 && isTitleUnderline(text_, lineStart))
        {
            type_ = eParagraphType_Title;
        }
        // Check for end-of-input or an empty line, i.e., a normal paragraph
        // break.
        if (lineEnd + 1 >= text_.length() || text_[lineEnd + 1] == '\n')
        {
            nextBreakSize_ = 2;
            break;
        }
        // Always return the title as a separate paragraph, as it requires
        // different processing.
        // TODO: This should allow nicer formatting that shares
        // implementation with writeTitle() and honors the nesting depths etc.,
        // but that is not implemented.
        if (type_ == eParagraphType_Title)
        {
            // If we are here, there was no actual paragraph break, so do not
            // produce one in the output either.
            nextBreakSize_ = 1;
            break;
        }
        // Next loop starts at the character after the newline.
        i = lineEnd + 1;
    }
    nextBegin_ = end_;
    // Check if the next paragraph should be treated as a literal paragraph,
    // and deal with transformations for the :: marker.
    if (end_ - begin_ >= 2 && text_.compare(end_ - 2, 2, "::") == 0)
    {
        literalIndent_ = indent_;
        // Return the actual literal block if the paragraph was just an "::".
        if (end_ - begin_ == 2)
        {
            // Avoid leading whitespace at the beginning; breakSize_ == 0
            // only for the first paragraph.
            if (breakSize_ == 0)
            {
                nextBreakSize_ = 0;
            }
            return nextParagraph();
        }
        // Remove one of the colons, or both if preceded by whitespace.
        const bool bRemoveDoubleColon = (text_[end_ - 3] == ' ');
        end_ -= (bRemoveDoubleColon ? 3 : 1);
    }
    else
    {
        literalIndent_ = -1;
    }
    // Treat a table like a literal block (preserve newlines).
    if (startsTable(text_, begin_ + firstLineIndent_))
    {
        type_ = eParagraphType_Literal;
    }
    return true;
}
コード例 #3
0
ファイル: karaokelyricstext.cpp プロジェクト: Bobbin007/xbmc
void CKaraokeLyricsText::Render()
{
  if ( !m_karaokeLayout )
    return;

  // Get the current song timing
  unsigned int songTime = (unsigned int) MathUtils::round_int( (getSongTime() * 10) );

  bool updatePreamble = false;
  bool updateText = false;

  // No returns in switch if anything needs to be drawn! Just break!
  switch ( m_lyricsState )
  {
    // the next paragraph lyrics are not shown yet. Screen is clear.
    // m_index points to the first entry.
    case STATE_WAITING:
      if ( songTime + m_showLyricsBeforeStart < m_lyrics[ m_index ].timing )
        return;

      // Is it time to play already?
      if ( songTime >= m_lyrics[ m_index ].timing )
      {
        m_lyricsState = STATE_PLAYING_PARAGRAPH;
      }
      else
      {
        m_lyricsState = STATE_PREAMBLE;
        m_lastPreambleUpdate = songTime;
      }

      updateText = true;
      break;

    // the next paragraph lyrics are shown, but the paragraph hasn't start yet.
    // Using m_lastPreambleUpdate, we redraw the marker each second.
    case STATE_PREAMBLE:
      if ( songTime < m_lyrics[ m_index ].timing )
      {
        // Time to redraw preamble?
        if ( songTime + m_showPreambleBeforeStart >= m_lyrics[ m_index ].timing )
        {
          if ( songTime - m_lastPreambleUpdate >= 10 )
          {
            // Fall through out of switch() to redraw
            m_lastPreambleUpdate = songTime;
            updatePreamble = true;
          }
        }
      }
      else
      {
        updateText = true;
        m_lyricsState = STATE_PLAYING_PARAGRAPH;
      }
      break;

    // The lyrics are shown, but nothing is colored or no color is changed yet.
    // m_indexStart, m_indexEnd and m_index are set, m_index timing shows when to color.
    case STATE_PLAYING_PARAGRAPH:
      if ( songTime >= m_lyrics[ m_index ].timing )
      {
        m_index++;
        updateText = true;

        if ( m_index > m_indexEndPara )
          m_lyricsState = STATE_END_PARAGRAPH;
      }
      break;

    // the whole paragraph is colored, but still shown, waiting until it's time to clear the lyrics.
    // m_index still points to the last entry, and m_indexNextPara points to the first entry of next
    // paragraph, or to LYRICS_END. When the next paragraph is about to start (which is
    // m_indexNextPara timing - m_showLyricsBeforeStart), the state switches to STATE_START_PARAGRAPH. When time
    // goes after m_index timing + m_delayAfter, the state switches to STATE_WAITING,
    case STATE_END_PARAGRAPH:
      {
        unsigned int paraEnd = m_lyrics[ m_indexEndPara ].timing + m_delayAfter;

        // If the next paragraph starts before current ends, use its start time as our end
        if ( m_indexNextPara != LYRICS_END && m_lyrics[ m_indexNextPara ].timing <= paraEnd + m_showLyricsBeforeStart )
        {
          if ( m_lyrics[ m_indexNextPara ].timing > m_showLyricsBeforeStart )
            paraEnd = m_lyrics[ m_indexNextPara ].timing - m_showLyricsBeforeStart;
          else
            paraEnd = 0;
        }

        if ( songTime >= paraEnd )
        {
          // Is the song ended?
          if ( m_indexNextPara != LYRICS_END )
          {
            // Are we still waiting?
            if ( songTime >= m_lyrics[ m_indexNextPara ].timing )
              m_lyricsState = STATE_PLAYING_PARAGRAPH;
            else
              m_lyricsState = STATE_WAITING;

            // Get next paragraph
            nextParagraph();
            updateText = true;
          }
          else
          {
            m_lyricsState = STATE_END_SONG;
            return;
          }
        }
      }
      break;

    case STATE_END_SONG:
      // the song is completed, there are no more lyrics to show. This state is finita la comedia.
      return;
  }

  // Calculate drawing parameters
  RESOLUTION resolution = g_graphicsContext.GetVideoResolution();
  g_graphicsContext.SetRenderingResolution(resolution, false);
  float maxWidth = (float) g_settings.m_ResInfo[resolution].Overscan.right - g_settings.m_ResInfo[resolution].Overscan.left;

  // We must only fall through for STATE_DRAW_SYLLABLE or STATE_PREAMBLE
  if ( updateText )
  {
    // So we need to update the layout with current paragraph text, optionally colored according to index
    bool color_used = false;
    m_currentLyrics = "";

    // Draw the current paragraph test if needed
    if ( songTime + m_showLyricsBeforeStart >= m_lyrics[ m_indexStartPara ].timing )
    {
      for ( unsigned int i = m_indexStartPara; i <= m_indexEndPara; i++ )
      {
        if ( m_lyrics[i].flags & LYRICS_NEW_LINE )
          m_currentLyrics += "[CR]";

        if ( i == m_indexStartPara && songTime >= m_lyrics[ m_indexStartPara ].timing )
        {
          color_used = true;
          m_currentLyrics += "[COLOR " + m_colorSinging + "]";
        }

        if ( songTime < m_lyrics[ i ].timing && color_used )
        {
          color_used = false;
          m_currentLyrics += "[/COLOR]";
        }

        m_currentLyrics += m_lyrics[i].text;
      }

      if ( color_used )
        m_currentLyrics += "[/COLOR]";

//      CLog::Log( LOGERROR, "Updating text: state %d, time %d, start %d, index %d (time %d) [%s], text %s",
//        m_lyricsState, songTime, m_lyrics[ m_indexStartPara ].timing, m_index, m_lyrics[ m_index ].timing,
//        m_lyrics[ m_index ].text.c_str(), m_currentLyrics.c_str());
    }

    m_karaokeLayout->Update(m_currentLyrics, maxWidth * 0.9f);
    updateText = false;
  }

  if ( updatePreamble )
  {
    m_currentPreamble = "";

    // Get number of seconds left to the song start
    if ( m_lyrics[ m_indexStartPara ].timing >= songTime )
    {
      unsigned int seconds = (m_lyrics[ m_indexStartPara ].timing - songTime) / 10;

      while ( seconds-- > 0 )
        m_currentPreamble += "- ";
    }

    m_preambleLayout->Update( m_currentPreamble, maxWidth * 0.9f );
  }

  float x = maxWidth * 0.5f + g_settings.m_ResInfo[resolution].Overscan.left;
  float y = (float)g_settings.m_ResInfo[resolution].Overscan.top +
      (g_settings.m_ResInfo[resolution].Overscan.bottom - g_settings.m_ResInfo[resolution].Overscan.top) / 8;

  float textWidth, textHeight;
  m_karaokeLayout->GetTextExtent(textWidth, textHeight);
  m_karaokeLayout->RenderOutline(x, y, 0, m_colorLyricsOutline, XBFONT_CENTER_X, maxWidth);

  if ( !m_currentPreamble.IsEmpty() )
  {
    float pretextWidth, pretextHeight;
    m_preambleLayout->GetTextExtent(pretextWidth, pretextHeight);
    m_preambleLayout->RenderOutline(x - textWidth / 2, y - pretextHeight, 0, m_colorLyricsOutline, XBFONT_LEFT, maxWidth);
  }
}