Exemple #1
0
void CGUITextLayout::LineBreakText(const vecText &text, vector<CGUIString> &lines)
{
  int nMaxLines = (m_maxHeight > 0 && m_font && m_font->GetLineHeight() > 0)?(int)ceilf(m_maxHeight / m_font->GetLineHeight()):-1;
  vecText::const_iterator lineStart = text.begin();
  vecText::const_iterator pos = text.begin();
  while (pos != text.end() && (nMaxLines <= 0 || lines.size() < (size_t)nMaxLines))
  {
    // Get the current letter in the string
    character_t letter = *pos;

    // Handle the newline character
    if ((letter & 0xffff) == L'\n' )
    { // push back everything up till now
      CGUIString string(lineStart, pos, true);
      lines.push_back(string);
      lineStart = pos + 1;
    }
    pos++;
  }
  // handle the last line if non-empty
  if (lineStart < text.end() && (nMaxLines <= 0 || lines.size() < (size_t)nMaxLines))
  {
    CGUIString string(lineStart, text.end(), true);
    lines.push_back(string);
  }
}
Exemple #2
0
void CGUITextLayout::LineBreakText(const vecText &text, vector<CGUIString> &lines)
{
  bool bUseHeight = (m_maxHeight > 0 && m_font && m_font->GetLineHeight() > 0);
  int nMaxLines = bUseHeight?(int)(m_maxHeight / m_font->GetLineHeight()):-1;
  if (bUseHeight && nMaxLines == 0) // hack. if height is not enough - force 1 line of text
    nMaxLines = 1;
  
  vecText::const_iterator lineStart = text.begin();
  vecText::const_iterator pos = text.begin();
  while (pos != text.end() && (nMaxLines <= 0 || lines.size() < (size_t)nMaxLines))
  {
    // Get the current letter in the string
    character_t letter = *pos;

    // Handle the newline character
    if ((letter & 0xffff) == L'\n' )
    { // push back everything up till now
      CGUIString string(lineStart, pos, true);
      lines.push_back(string);
      lineStart = pos + 1;
    }
    pos++;
  }
}
Exemple #3
0
void CGUIFontTTFBase::DrawTextInternal(float x, float y, const vecColors &colors, const vecText &text, uint32_t alignment, float maxPixelWidth, bool scrolling)
{
  Begin();

  // save the origin, which is scaled separately
  m_originX = x;
  m_originY = y;

  // Check if we will really need to truncate or justify the text
  if ( alignment & XBFONT_TRUNCATED )
  {
    if ( maxPixelWidth <= 0.0f || GetTextWidthInternal(text.begin(), text.end()) <= maxPixelWidth)
      alignment &= ~XBFONT_TRUNCATED;
  }
  else if ( alignment & XBFONT_JUSTIFIED )
  {
    if ( maxPixelWidth <= 0.0f )
      alignment &= ~XBFONT_JUSTIFIED;
  }

  // calculate sizing information
  float startX = 0;
  float startY = (alignment & XBFONT_CENTER_Y) ? -0.5f*m_cellHeight : 0;  // vertical centering

  if ( alignment & (XBFONT_RIGHT | XBFONT_CENTER_X) )
  {
    // Get the extent of this line
    float w = GetTextWidthInternal( text.begin(), text.end() );

    if ( alignment & XBFONT_TRUNCATED && w > maxPixelWidth + 0.5f ) // + 0.5f due to rounding issues
      w = maxPixelWidth;

    if ( alignment & XBFONT_CENTER_X)
      w *= 0.5f;
    // Offset this line's starting position
    startX -= w;
  }

  float spacePerLetter = 0; // for justification effects
  if ( alignment & XBFONT_JUSTIFIED )
  {
    // first compute the size of the text to render in both characters and pixels
    unsigned int lineChars = 0;
    float linePixels = 0;
    for (vecText::const_iterator pos = text.begin(); pos != text.end(); ++pos)
    {
      Character *ch = GetCharacter(*pos);
      if (ch)
      { // spaces have multiple times the justification spacing of normal letters
        lineChars += ((*pos & 0xffff) == L' ') ? justification_word_weight : 1;
        linePixels += ch->advance;
      }
    }
    if (lineChars > 1)
      spacePerLetter = (maxPixelWidth - linePixels) / (lineChars - 1);
  }
  float cursorX = 0; // current position along the line

  for (vecText::const_iterator pos = text.begin(); pos != text.end(); ++pos)
  {
    // If starting text on a new line, determine justification effects
    // Get the current letter in the CStdString
    color_t color = (*pos & 0xff0000) >> 16;
    if (color >= colors.size())
      color = 0;
    color = colors[color];

    // grab the next character
    Character *ch = GetCharacter(*pos);
    if (!ch) continue;

    if ( alignment & XBFONT_TRUNCATED )
    {
      // Check if we will be exceeded the max allowed width
      if ( cursorX + ch->advance + 3 * m_ellipsesWidth > maxPixelWidth )
      {
        // Yup. Let's draw the ellipses, then bail
        // Perhaps we should really bail to the next line in this case??
        Character *period = GetCharacter(L'.');
        if (!period)
          break;

        for (int i = 0; i < 3; i++)
        {
          RenderCharacter(startX + cursorX, startY, period, color, !scrolling);
          cursorX += period->advance;
        }
        break;
      }
    }
    else if (maxPixelWidth > 0 && cursorX > maxPixelWidth)
      break;  // exceeded max allowed width - stop rendering

    RenderCharacter(startX + cursorX, startY, ch, color, !scrolling);
    if ( alignment & XBFONT_JUSTIFIED )
    {
      if ((*pos & 0xffff) == L' ')
        cursorX += ch->advance + spacePerLetter * justification_word_weight;
      else
        cursorX += ch->advance + spacePerLetter;
    }
    else
      cursorX += ch->advance;
  }

  End();
}
Exemple #4
0
void CGUIFontTTFBase::DrawTextInternal(float x, float y, const vecColors &colors, const vecText &text, uint32_t alignment, float maxPixelWidth, bool scrolling)
{
  Begin();

  uint32_t rawAlignment = alignment;
  bool dirtyCache;
  bool hardwareClipping = g_Windowing.ScissorsCanEffectClipping();
  CGUIFontCacheStaticPosition staticPos(x, y);
  CGUIFontCacheDynamicPosition dynamicPos;
  if (hardwareClipping)
  {
    dynamicPos = CGUIFontCacheDynamicPosition(g_graphicsContext.ScaleFinalXCoord(x, y),
                                              g_graphicsContext.ScaleFinalYCoord(x, y),
                                              g_graphicsContext.ScaleFinalZCoord(x, y));
  }
  CVertexBuffer unusedVertexBuffer;
  CVertexBuffer &vertexBuffer = hardwareClipping ?
      m_dynamicCache.Lookup(dynamicPos,
                            colors, text,
                            alignment, maxPixelWidth,
                            scrolling,
                            XbmcThreads::SystemClockMillis(),
                            dirtyCache) :
      unusedVertexBuffer;
  std::shared_ptr<std::vector<SVertex> > tempVertices = std::make_shared<std::vector<SVertex> >();
  std::shared_ptr<std::vector<SVertex> > &vertices = hardwareClipping ?
      tempVertices :
      static_cast<std::shared_ptr<std::vector<SVertex> >&>(m_staticCache.Lookup(staticPos,
                           colors, text,
                           alignment, maxPixelWidth,
                           scrolling,
                           XbmcThreads::SystemClockMillis(),
                           dirtyCache));
  if (dirtyCache)
  {
    // save the origin, which is scaled separately
    m_originX = x;
    m_originY = y;

    // Check if we will really need to truncate or justify the text
    if ( alignment & XBFONT_TRUNCATED )
    {
      if ( maxPixelWidth <= 0.0f || GetTextWidthInternal(text.begin(), text.end()) <= maxPixelWidth)
        alignment &= ~XBFONT_TRUNCATED;
    }
    else if ( alignment & XBFONT_JUSTIFIED )
    {
      if ( maxPixelWidth <= 0.0f )
        alignment &= ~XBFONT_JUSTIFIED;
    }

    // calculate sizing information
    float startX = 0;
    float startY = (alignment & XBFONT_CENTER_Y) ? -0.5f*m_cellHeight : 0;  // vertical centering

    if ( alignment & (XBFONT_RIGHT | XBFONT_CENTER_X) )
    {
      // Get the extent of this line
      float w = GetTextWidthInternal( text.begin(), text.end() );

      if ( alignment & XBFONT_TRUNCATED && w > maxPixelWidth + 0.5f ) // + 0.5f due to rounding issues
        w = maxPixelWidth;

      if ( alignment & XBFONT_CENTER_X)
        w *= 0.5f;
      // Offset this line's starting position
      startX -= w;
    }

    float spacePerSpaceCharacter = 0; // for justification effects
    if ( alignment & XBFONT_JUSTIFIED )
    {
      // first compute the size of the text to render in both characters and pixels
      unsigned int numSpaces = 0;
      float linePixels = 0;
      for (vecText::const_iterator pos = text.begin(); pos != text.end(); ++pos)
      {
        Character *ch = GetCharacter(*pos);
        if (ch)
        {
          if ((*pos & 0xffff) == L' ')
            numSpaces +=  1;
          linePixels += ch->advance;
        }
      }
      if (numSpaces > 0)
        spacePerSpaceCharacter = (maxPixelWidth - linePixels) / numSpaces;
    }

    float cursorX = 0; // current position along the line
    for (vecText::const_iterator pos = text.begin(); pos != text.end(); ++pos)
    {
      // If starting text on a new line, determine justification effects
      // Get the current letter in the CStdString
      color_t color = (*pos & 0xff0000) >> 16;
      if (color >= colors.size())
        color = 0;
      color = colors[color];

      // grab the next character
      Character *ch = GetCharacter(*pos);
      if (!ch) continue;

      if ( alignment & XBFONT_TRUNCATED )
      {
        // Check if we will be exceeded the max allowed width
        if ( cursorX + ch->advance + 3 * m_ellipsesWidth > maxPixelWidth )
        {
          // Yup. Let's draw the ellipses, then bail
          // Perhaps we should really bail to the next line in this case??
          Character *period = GetCharacter(L'.');
          if (!period)
            break;

          for (int i = 0; i < 3; i++)
          {
            RenderCharacter(startX + cursorX, startY, period, color, !scrolling, *tempVertices);
            cursorX += period->advance;
          }
          break;
        }
      }
      else if (maxPixelWidth > 0 && cursorX > maxPixelWidth)
        break;  // exceeded max allowed width - stop rendering

      RenderCharacter(startX + cursorX, startY, ch, color, !scrolling, *tempVertices);
      if ( alignment & XBFONT_JUSTIFIED )
      {
        if ((*pos & 0xffff) == L' ')
          cursorX += ch->advance + spacePerSpaceCharacter;
        else
          cursorX += ch->advance;
      }
      else
        cursorX += ch->advance;
    }
    if (hardwareClipping)
    {
      CVertexBuffer &vertexBuffer = m_dynamicCache.Lookup(dynamicPos,
                                                          colors, text,
                                                          rawAlignment, maxPixelWidth,
                                                          scrolling,
                                                          XbmcThreads::SystemClockMillis(),
                                                          dirtyCache);
      CVertexBuffer newVertexBuffer = CreateVertexBuffer(*tempVertices);
      vertexBuffer = newVertexBuffer;
      m_vertexTrans.push_back(CTranslatedVertices(0, 0, 0, &vertexBuffer, g_graphicsContext.GetClipRegion()));
    }
    else
    {
      m_staticCache.Lookup(staticPos,
                           colors, text,
                           rawAlignment, maxPixelWidth,
                           scrolling,
                           XbmcThreads::SystemClockMillis(),
                           dirtyCache) = *static_cast<CGUIFontCacheStaticValue *>(&tempVertices);
      /* Append the new vertices to the set collected since the first Begin() call */
      m_vertex.insert(m_vertex.end(), tempVertices->begin(), tempVertices->end());
    }
  }
  else
  {
    if (hardwareClipping)
Exemple #5
0
float CGUIFont::GetTextWidth( const vecText &text )
{
  if (!m_font) return 0;
  CSingleLock lock(g_graphicsContext);
  return m_font->GetTextWidthInternal(text.begin(), text.end()) * g_graphicsContext.GetGUIScaleX();
}
Exemple #6
0
void CGUIFontTTFBase::BuildTextCoordinates(float x, float y, const vecColors &colors, color_t shadowColor,
        const vecText &text, uint32_t alignment, float maxPixelWidth, bool scrolling, FontCoordsIndiced& pData)
{
    // Check if we will really need to truncate or justify the text
    m_originX = x;
    m_originY = y;

    if ( alignment & XBFONT_TRUNCATED )
    {
        if ( maxPixelWidth <= 0.0f || GetTextWidthInternal(text.begin(), text.end()) <= maxPixelWidth)
            alignment &= ~XBFONT_TRUNCATED;
    }
    else if ( alignment & XBFONT_JUSTIFIED )
    {
        if ( maxPixelWidth <= 0.0f )
            alignment &= ~XBFONT_JUSTIFIED;
    }

    // calculate sizing information
    float startX = 0;
    float startY = (alignment & XBFONT_CENTER_Y) ? -0.5f*(m_cellHeight-2) : 0;  // vertical centering

    if ( alignment & (XBFONT_RIGHT | XBFONT_CENTER_X) )
    {
        // Get the extent of this line
        float w = GetTextWidthInternal( text.begin(), text.end() );

        if ( alignment & XBFONT_TRUNCATED && w > maxPixelWidth )
            w = maxPixelWidth;

        if ( alignment & XBFONT_CENTER_X)
            w *= 0.5f;
        // Offset this line's starting position
        startX -= w;
    }

    float spacePerLetter = 0; // for justification effects
#if 0
    if ( alignment & XBFONT_JUSTIFIED )
    {
        // first compute the size of the text to render in both characters and pixels
        unsigned int lineChars = 0;
        float linePixels = 0;
        for (vecText::const_iterator pos = text.begin(); pos != text.end(); pos++)
        {
            Character *ch = GetCharacter(*pos);
            if (ch)
            {   // spaces have multiple times the justification spacing of normal letters
                lineChars += ((*pos & 0xffff) == L' ') ? justification_word_weight : 1;
                linePixels += ch->advance;
            }
        }
        if (lineChars > 1)
            spacePerLetter = (maxPixelWidth - linePixels) / (lineChars - 1);
    }
#endif

    ReloadFace();

#ifdef HAS_HARFBUZZ_NG
    int i = 0;
    wchar_t strW[text.size()];
    for (vecText::const_iterator pos = text.begin(); pos != text.end(); pos++)
    {
        wchar_t letter = (wchar_t)((*pos) & 0xffff);
        strW[i] = letter;
        i++;
    }

    hb_buffer_t *hb_buffer = hb_buffer_create(text.size());
    hb_buffer_set_unicode_funcs(hb_buffer, hb_glib_get_unicode_funcs());
    hb_buffer_add_utf32(hb_buffer, (const uint32_t*) strW, text.size(), 0, text.size());
    hb_buffer_set_direction(hb_buffer, HB_DIRECTION_LTR);

    hb_shape (hb_font, hb_buffer, NULL, 0);
    unsigned int glyph_info_len;
    hb_glyph_info_t *hb_glyph = hb_buffer_get_glyph_infos (hb_buffer, &glyph_info_len);
    hb_glyph_position_t *hb_position = hb_buffer_get_glyph_positions (hb_buffer, &glyph_info_len);

#else /* HAS_HARFBUZZ_NG */
    FT_Vector delta;
    Character* previousCh = NULL;
#endif

    float cursorX = 0; // current position along the line

    for (vecText::const_iterator pos = text.begin(); pos != text.end(); pos++)
    {
        // If starting text on a new line, determine justification effects
        // Get the current letter in the CStdString
        color_t color = (*pos & 0xff0000) >> 16;
        if (color >= colors.size())
            color = 0;
        color = colors[color];

        // grab the next character
        Character *ch = GetCharacter(*pos);
        if (!ch) continue;

        if ( alignment & XBFONT_TRUNCATED )
        {
            // Check if we will be exceeded the max allowed width
            if ( cursorX + ch->advance + 3 * m_ellipsesWidth > maxPixelWidth )
            {
                // Yup. Let's draw the ellipses, then bail
                // Perhaps we should really bail to the next line in this case??
                Character *period = GetCharacter(L'.');
                if (!period)
                    break;

                for (int i = 0; i < 3; i++)
                {
                    BuildCharacterCoordinates(startX + cursorX, startY, period, color, shadowColor, !scrolling, pData);
                    cursorX += period->advance;
                }
                break;
            }
        }
        else if (maxPixelWidth > 0 && cursorX > maxPixelWidth)
            break;  // exceeded max allowed width - stop rendering

#ifdef HAS_HARFBUZZ_NG
        BuildCharacterCoordinates(startX + cursorX + (hb_position->x_offset * (1./64)), startY - (hb_position->y_offset * (1./64)), ch, color, shadowColor, !scrolling, pData);

        if ( alignment & XBFONT_JUSTIFIED )
        {
            if ((*pos & 0xffff) == L' ')
                cursorX +=  (hb_position->x_advance * (1./64)) + spacePerLetter * justification_word_weight;
            else
                cursorX += (hb_position->x_advance * (1./64)) + spacePerLetter;
        }
        else
            cursorX +=  hb_position->x_advance * (1./64);

        hb_glyph++;
        hb_position++;
#else
        if (previousCh)
        {
            FT_Get_Kerning(m_face, previousCh->glyphIndex, ch->glyphIndex,
                           FT_KERNING_DEFAULT, &delta);
            cursorX += (float) (delta.x / 64);
        }

        BuildCharacterCoordinates(startX + cursorX, startY, ch, color, shadowColor, !scrolling, pData);
        if ( alignment & XBFONT_JUSTIFIED )
        {
            if ((*pos & 0xffff) == L' ')
                cursorX += ch->advance + spacePerLetter * justification_word_weight;
            else
                cursorX += ch->advance + spacePerLetter;
        }
        else
            cursorX += ch->advance;

        previousCh = ch;
#endif
    }

#ifdef HAS_HARFBUZZ_NG
    hb_buffer_destroy(hb_buffer);
#endif
}