Exemple #1
0
void render(const text::utf32_string& inText, const vector<Range>& lines, const FontPtr& font, const RenderedTextPtr& target, bool characterMetrics, int align)
{
  // these arrays will receive the character geometry in space, relative to a 0,0 baseline
  // and the corresponding pixel coordinates of the subtexture within the font texture atlas
  // used to draw the character
  vector<math::Vec2> lineBounds;
  vector<math::Rect> characterRects;
  vector<math::Rect> pixelCoordRects;
    
  // size calculation 
  Vec2 pmin, pmax; 
  uint32_t addIndex=0; // we iterate over all chracters, but not all of them might be drawable
                       // so we need a separate index for the actual insertion of a character into the mesh

  uint32_t previousGlyphIndex = 0;
  float xoffset = 0;    
  float yoffset = std::max((float)lines.size()-1, 0.0f)*floorf(font->lineHeight);
  if(characterMetrics) {target->resetCharacterMetrics(); }
  for(vector<Range>::const_iterator pos=lines.begin(); pos!=lines.end(); ++pos)
  {
    if(characterMetrics) {target->pushEmptyCharacterMetricLine();}
    if(pos->begin != pos->end) // skip empty lines
    {
      Vec2 bounds(addIndex,addIndex);
      for(uint32_t i=pos->begin; i<pos->end; ++i)
      {
        text::utf32_char c = inText[i];
        xoffset+=font->kerningOffset(previousGlyphIndex, c);
        GlyphPtr glyph = font->glyph(c);
        if (!glyph) continue;
        if (glyph->drawable)
        {
          addGlyph(characterRects, pixelCoordRects, glyph, xoffset, yoffset, pmin, pmax);
          if(characterMetrics) {target->pushCharacterRect(characterRects[addIndex]);}
          addIndex++;
        }
        else
        {
          // push dummy rect for metrics if char was not drawable
          if(characterMetrics) {target->pushCharacterRect(Rect(xoffset,yoffset,glyph->advance,font->lineHeight));}
        }
        xoffset+=glyph->advance;
      }
      if (align != 0 && addIndex > 0) {
        bounds.max = addIndex-1;
        lineBounds.push_back(bounds);
      }
    }
    xoffset = 0;
    yoffset -= floorf(font->lineHeight);
    previousGlyphIndex = 0;
  }

  // horizontal align center/right
  if (align != 0) {
    float maxWidth = (pmax.x-pmin.x)+1;
    for (vector<math::Vec2>::iterator b = lineBounds.begin(); b != lineBounds.end(); ++b) {
      int offset = (maxWidth - (characterRects[b->max].x+characterRects[b->max].width-characterRects[b->min].x));
      if (offset > 0) {
        if (align == 1) {
          offset /= 2.0f;
        }
        for (int c = b->min; c <= b->max; ++c) {
          characterRects[c].x += offset;
        }
      }
    }
  }

  target->init(characterRects, font->atlas, pixelCoordRects, false);
  target->min = pmin;
  target->max = pmax;
  target->size.width = (pmax.x-pmin.x)+1;  
  target->size.height = (pmax.y-pmin.y)+1;
  target->material->blendPremultiplied();
  target->numLines = lines.size();
}