Example #1
0
		void FallbackFontRenderer::Draw(uint32_t unicode, spades::Vector2 offset,
										float size, spades::Vector4 color) {
			renderer->SetColorAlphaPremultiplied(color);
			float x = offset.x;
			float y = offset.y;
			
			auto glyph = FindGlyph(unicode);
			if(glyph.img == nullptr) {
				// no glyph found! draw box in the last resort
				IImage *img = whiteImage;
				renderer->DrawImage(img, AABB2(x, y, size, 1.f));
				renderer->DrawImage(img, AABB2(x, y + size - 1.f, size, 1.f));
				renderer->DrawImage(img, AABB2(x, y + 1.f, 1.f, size - 2.f));
				renderer->DrawImage(img, AABB2(x + size - 1.f, y + 1.f, 1.f, size - 2.f));
				return;
			}
			
			if(glyph.w == 0) {
				// null glyph.
				return;
			}
			
			float scale = size * glyph.sizeInverse;
			if(roundSize || scale < 1.f) {
				float newScale = std::max(1.f, floorf(scale));
				// vertical-align: baseline
				offset.y += (scale - newScale) * glyph.size;
				scale = newScale;
			}
			
			AABB2 inRect(glyph.x, glyph.y, glyph.w, glyph.h);
			AABB2 outRect(glyph.offX, glyph.offY, glyph.w, glyph.h);
			
			// margin to make the border completely transparent
			// (considering the OpenGL's linear interpolation)
			if(!roundSize){
				inRect.min.x -= 0.5f;
				inRect.min.y -= 0.5f;
				outRect.min.x -= 0.5f;
				outRect.min.y -= 0.5f;
				inRect.max.x += 0.5f;
				inRect.max.y += 0.5f;
				outRect.max.x += 0.5f;
				outRect.max.y += 0.5f;
			}
			
			outRect.min *= scale;
			outRect.max *= scale;
			
			outRect.min += offset;
			outRect.max += offset;
			
			renderer->DrawImage(glyph.img, outRect, inRect);
		}
Example #2
0
		float FallbackFontRenderer::Measure(uint32_t unicode, float size) {
			auto glyph = FindGlyph(unicode);
			if(glyph.img == nullptr) {
				// no glyph found! draw box in the last resort
				return size + 1.f;
			}
			
			float scale = size * glyph.sizeInverse;
			if(roundSize || scale < 1.f) {
				float newScale = std::max(1.f, floorf(scale));
				scale = newScale;
			}
			return glyph.advance * scale;
		}
CTextRenderer::CGlyph* CTextRenderer::GetGlyph(CGlyphCache* pCache, CGlyphId GlyphId)
{
	CTextRenderer::CGlyph* pGlyph = FindGlyph(pCache, GlyphId);
	
	//Load Glyph
	if(!pGlyph)
		pGlyph = LoadGlyph(pCache, GlyphId);
	
	//Update timer
	if(pGlyph)
		pGlyph->m_RenderTick = m_RenderTick;
	
	return pGlyph;
}
Example #4
0
/** Returns the width of a string. Only a single-line string is handled at
 *  this moment. The returned value is scaled. This routine ignores any
 *  rotation, so the returned value is the width of the bounding box when the
 *  text is drawn at zero degrees (horizontally, left to right).
 */
float CXFFont::GetTextExtent(const wchar_t* text) const
{
  assert(text);
  float total = 0;
  for (unsigned idx = 0; text[idx]; idx++) {
    unsigned short code = text[idx];
    if (idx > 0)
      total += m_LetterSpacing;
    if (code == ' ') {
      total += m_WordSpacing;
    } else {
      const CXFGlyph* glyph = FindGlyph(code);
      if (glyph)
        total += glyph->GetWidth();
    }
  }
  return total * m_ScaleX;
}
Example #5
0
/** Internal function that returns the height & depth of the character. These
 *  sizes are unscaled.
 *
 *  height = character height above the base line
 *  depth = descender height (negative value, or zero)
 */
void CXFFont::GetGlyphVSize(unsigned short code, float *height, float* depth)
{
  assert(height);
  assert(depth);
  *height = *depth = 0;

  const CXFGlyph* glyph = FindGlyph(code);
  if (glyph) {
    const CXFPolyLine* stroke;
    for (size_t sidx = 0; (stroke = glyph->GetPolyLine(sidx)) != 0; sidx++) {
      const CXFPoint* pt;
      for (size_t pidx = 0; (pt = stroke->GetPoint(pidx)) != 0; pidx++) {
        if (*depth > pt->m_y)
          *depth = pt->m_y;
        else if (*height < pt->m_y)
          *height = pt->m_y;
      }
    }
  }
}
Example #6
0
void CXFFont::DrawText(const wchar_t* text, std::vector<CXFPolyLine>* strokes) const
{
  assert(text);
  assert(strokes);
  strokes->clear();

  float scalex = m_ScaleX, scaley = m_ScaleY;
  if (m_Rotation > 135 && m_Rotation <= 315) {
    scalex = -m_ScaleX;
    scaley = -m_ScaleY;
  }
  bool vertmode = (m_Rotation > 45 && m_Rotation <= 135) || (m_Rotation > 225 && m_Rotation <= 315);

  float xpos = 0, ypos = 0;
  switch (m_AlignHor) {
  case CXF_ALIGNLEFT:
    xpos = 0;
    break;
  case CXF_ALIGNRIGHT:
    xpos = - GetTextExtent(text);
    break;
  case CXF_ALIGNCENTRE:
    xpos = - GetTextExtent(text) / 2;
    break;
  }
  switch (m_AlignVer) {
  case CXF_ALIGNBASE:
    ypos = 0;
    break;
  case CXF_ALIGNTOP:
    ypos = m_Ascender * m_ScaleY * 1.15;	/* assume 15% internal leading above the ascender */
    break;
  case CXF_ALIGNBOTTOM:
    ypos = m_Descender * m_ScaleY * 1.1;	/* assume 10% internal leading below the descender */
    break;
  case CXF_ALIGNCENTRE:
    ypos = (m_Ascender + m_Descender) * m_ScaleY;
    break;
  }
  if (!vertmode)
    ypos = -ypos;
  float xbase = xpos; /* save, for the overbar */

  for (unsigned idx = 0; text[idx]; idx++) {
    unsigned short code = text[idx];
    if (idx > 0)
      xpos += m_LetterSpacing * scalex;
    if (code == ' ') {
      xpos += m_WordSpacing * scalex;
    } else {
      const CXFGlyph* glyph = FindGlyph(code);
      if (glyph) {
        const CXFPolyLine *stroke;
        CXFPolyLine newstroke;
        for (size_t sidx = 0; (stroke = glyph->GetPolyLine(sidx)) != 0; sidx++) {
          newstroke.Clear();
          const CXFPoint* pt;
          CXFPoint newpt;
          for (size_t pidx = 0; (pt = stroke->GetPoint(pidx)) != 0; pidx++) {
            if (vertmode) {
              newpt.m_x = ypos - (pt->m_y * scaley);
              newpt.m_y = xpos + pt->m_x * scalex;
            } else {
              newpt.m_x = xpos + pt->m_x * scalex;
              newpt.m_y = ypos + pt->m_y * scaley;
            }
            newstroke.AddPoint(newpt);
          }
          strokes->push_back(newstroke);
        }
        xpos += glyph->GetWidth() * scalex;
      }
    }
  }
  /* optionally draw the overbar */
  if (m_Overbar) {
    CXFPolyLine newstroke;
    float y = m_CapsHeight * scaley * 1.2;  /* overbar 12% above caps height */
    if (vertmode) {
      newstroke.AddPoint(CXFPoint(ypos - y, xbase));
      newstroke.AddPoint(CXFPoint(ypos - y, xpos));
    } else {
      newstroke.AddPoint(CXFPoint(xbase, ypos + y));
      newstroke.AddPoint(CXFPoint(xpos, ypos + y));
    }
    strokes->push_back(newstroke);
  }
}