Example #1
2
int32_t FreeTypeFont::getTextLength(const std::u32string& text, const size_t size)
{
    if (!face)
    {
        return -1;
    }

    int32_t textLength = 0;

    size_t textIndex = 0;

    FontCacheEntry* fontCacheEntry;

    while (textIndex < text.length())
    {
        fontCacheEntry = getGlyph(text[textIndex], size);

        if (fontCacheEntry == nullptr)
        {
            return -1;
        }

        textLength += fontCacheEntry->advanceX;

        textIndex++;
    }

    return textLength;
}
Example #2
0
void CPetGlyphs::changeHighlight(int index) {
	if (index == _highlightIndex)
		return;

	if (_highlightIndex >= 0 && (_flags & GFLAG_4)) {
		CPetGlyph *glyph = getGlyph(_highlightIndex);
		if (glyph)
			glyph->unhighlightCurrent();
	}

	_highlightIndex = index;
	if (index >= 0) {
		CPetGlyph *glyph = getGlyph(_highlightIndex);

		if (glyph) {
			if (_flags & GFLAG_4) {
				Point pt;
				int idx = getHighlightedIndex(_highlightIndex);
				if (idx >= 0)
					pt = getPosition(idx);

				glyph->highlightCurrent(pt);
			}

			glyph->updateTooltip();
		}
	} else if (_owner) {
		_owner->removeText();
	}
}
Example #3
0
void CPetGlyphs::enter() {
	if (_highlightIndex != -1) {
		CPetGlyph *glyph = getGlyph(_highlightIndex);
		if (glyph)
			glyph->enter();
	}
}
Example #4
0
osgText::Glyph* ScaledAltFont::getGlyph(const osgText::FontResolution& fontRes, unsigned int charcode) {
	{
		OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_glyphMapMutex);
		FontSizeGlyphMap::iterator itr = _sizeGlyphMap.find(fontRes);
		if (itr != _sizeGlyphMap.end()) {
			GlyphMap& glyphmap = itr->second;
			GlyphMap::iterator gitr = glyphmap.find(charcode);
			if (gitr!=glyphmap.end()) return gitr->second.get();
		}
	}
	if (_implementation.valid()) {
		if (charcode >= 128) {
			unsigned int normal_code = charcode % 128;
			// Reload a scaled version of the glyph
			osgText::Glyph *normal_glyph = getGlyph(fontRes, normal_code);

			const osgText::FontResolution new_fontRes(fontRes.first * m_Scale, fontRes.second * m_Scale);
			osgText::Glyph *scaled_glyph = _implementation->getGlyph(new_fontRes, normal_code);
			if (m_VCenter) {
				osg::Vec2 hbearing = scaled_glyph->getHorizontalBearing();
				hbearing.y() += 0.5f * (normal_glyph->t() - scaled_glyph->t());
				scaled_glyph->setHorizontalBearing(hbearing);
			}
			addGlyph (fontRes, charcode, scaled_glyph);
			return scaled_glyph;
		} else {
			osgText::Glyph* g = _implementation->getGlyph(fontRes, charcode);
			addGlyph (fontRes, charcode, g);
			return g;
		}
	}
	return 0;
}
Example #5
0
Vector2i Font::getSize(const std::string &text) const {
	Vector2i size(0, getMaxVerticalBearing());
	int pos = 0;

	for (size_t i=0; i<text.length(); i++) {
		char character = text[i];
		if (character == '\r')
			continue;
		if (character == '\n') {
			size.y += (int) (getMaxVerticalBearing()*(4.0 / 3.0));
			size.x = std::max(size.x, pos);
			pos = 0;
			continue;
		}

		const Font::Glyph &glyph = getGlyph(character);

		pos += glyph.horizontalAdvance;

		if (i+1 < text.length())
			pos += getKerning(character, text[i+1]);
	}
	size.x = std::max(size.x, pos);

	return size;
}
Example #6
0
	const WgUnderline * Font::getUnderline( int size )
	{
		// Create an underline specification from the '_' character as default.
		// It should be possible to specify something different in the spec file later on...
	
		Glyph_p pUnder = getGlyph('_', WG_FONT_NORMAL, size);
	
		const GlyphBitmap * pSrc = pUnder->getBitmap();
	
		m_tempUnderline.pSurf = pSrc->pSurface;
		m_tempUnderline.rect = pSrc->rect;
		m_tempUnderline.bearingX = pSrc->bearingX;
		m_tempUnderline.bearingY = pSrc->bearingY;
	
		if( pSrc->rect.w > 2 )
		{
			m_tempUnderline.leftBorder = 1;
			m_tempUnderline.rightBorder = 1;
		}
		else
		{
			m_tempUnderline.leftBorder = 0;
			m_tempUnderline.rightBorder = 0;
		}
	
		return &m_tempUnderline;
	}
Example #7
0
void Font::drawText(Bitmap *dest, Point2i pos, const std::string &text) const {
	int initial = pos.x;

	for (size_t i=0; i<text.length(); i++) {
		char character = text[i];
		if (character == '\r')
			continue;
		if (character == '\n') {
			pos.x = initial;
			pos.y += (int) (getMaxVerticalBearing()*4.0/3.0);
			continue;
		}

		const Font::Glyph &glyph = getGlyph(character);

		Point2i targetOffset = pos + Vector2i(
			glyph.horizontalBearing,
			getMaxVerticalBearing() - glyph.verticalBearing - 1
		);

		Point2i sourceOffset(
			(int) (glyph.tx.x * m_bitmap->getWidth()),
			(int) (glyph.tx.y * m_bitmap->getHeight()));

		dest->accumulate(m_bitmap.get(), sourceOffset, targetOffset, glyph.size);

		pos.x += glyph.horizontalAdvance;

		if (i+1 < text.length())
			pos.x += getKerning(character, text[i+1]);
	}
}
Example #8
0
VkBool32 FreeTypeFont::prepareText(const ICommandBuffersSP& cmdBuffer, const std::u32string& text, const size_t size)
{
    if (!face || !cmdBuffer.get())
    {
        return VK_FALSE;
    }

    size_t textIndex = 0;

    FontCacheEntry* fontCacheEntry;

    while (textIndex < text.length())
    {
        fontCacheEntry = getGlyph(cmdBuffer, text[textIndex], size);

        if (fontCacheEntry == nullptr)
        {
            return VK_FALSE;
        }

        textIndex++;
    }

    return VK_TRUE;
}
Example #9
0
void CPetGlyphs::leave() {
	if (_highlightIndex != -1) {
		CPetGlyph *glyph = getGlyph(_highlightIndex);
		if (glyph)
			glyph->leave();
	}
}
Example #10
0
bool CPetGlyphs::MouseButtonDownMsg(const Point &pt) {
	if (_scrollLeft.contains2(pt)) {
		scrollLeft();
		return true;
	}

	if (_scrollRight.contains2(pt)) {
		scrollRight();
		return true;
	}

	for (int idx = 0; idx < _numVisibleGlyphs; ++idx) {
		Rect glyphRect = getRect(idx);
		if (glyphRect.contains(pt)) {
			int index = getItemIndex(idx);
			CPetGlyph *glyph = getGlyph(index);
			if (glyph) {
				if (_highlightIndex == index) {
					glyph->selectGlyph(glyphRect, pt);
					glyph->updateTooltip();
				} else {
					changeHighlight(index);
					makePetDirty();
				}

				return true;
			}
		}
	}

	if (_highlightIndex != -1) {
		CPetGlyph *glyph = getGlyph(_highlightIndex);

		if (glyph) {
			if (glyph->MouseButtonDownMsg(pt))
				return true;

			if (!(_flags & GFLAG_2)) {
				changeHighlight(-1);
				makePetDirty();
			}
		}
	}

	return false;
}
//--------------------------------------------------------------------------------------------------
/// Get the extent (width and height) of the given text with this font in pixels
//--------------------------------------------------------------------------------------------------
cvf::Vec2ui Font::textExtent(const String& text)
{
    std::vector<cvf::String> lines = text.split("\n");

    float maxLineWidth = 0;
    uint textHeight = 0;
    uint lineSpacing = static_cast<uint>(this->lineSpacing());
    for (size_t lineIdx = 0; lineIdx < lines.size(); ++lineIdx)
    {
        String line = lines[lineIdx];
        size_t numCharacters = line.size();
        float lineWidth = 0;

        for (size_t j = 0; j < numCharacters; ++j)
        {
            wchar_t character = line[j];

            // Jump to the next character in the string, if any
            if (j < (numCharacters - 1))
            {
                float advance = static_cast<float>(this->advance(character, text[j + 1]));
                lineWidth += advance;
            }
            else
            {
                ref<Glyph> glyph = getGlyph(character);
                
                lineWidth += static_cast<float>(glyph->width()) + static_cast<float>(glyph->horizontalBearingX());
            }
        }

        maxLineWidth = CVF_MAX(lineWidth, maxLineWidth);

        if (lineIdx == 0)
        {
            ref<Glyph> glyph = getGlyph(L'A');
            textHeight += glyph->height();
        }
        else
        {
            textHeight += lineSpacing;
        }
    }

    return Vec2ui(static_cast<uint>(maxLineWidth), textHeight);
}
//--------------------------------------------------------------------------------------------------
/// 
//--------------------------------------------------------------------------------------------------
float Font::lineSpacing()
{
    ref<Glyph> glyph = getGlyph(L'A');

    float spacing = cvf::Math::floor(static_cast<float>(glyph->height())*1.75f);

    return spacing;
}
Example #13
0
bool CPetGlyphs::KeyCharMsg(int key) {
	if (_highlightIndex >= 0) {
		CPetGlyph *glyph = getGlyph(_highlightIndex);

		if (glyph && glyph->KeyCharMsg(key))
			return true;
	}

	return false;
}
Example #14
0
		void BitmapFont::render(const ref_ptr<SpriteBatch>& spriteBatch, const vector4f& rect, vector2f& pos, const colorf& color, const string& text)
		{
			for (auto ch = text.begin(); ch != text.end(); ++ch)  {
				char32_t id(*ch);
				const BitmapFontGlyph& glyph = getGlyph(id);
				if (glyph.page < 0 || size_t(glyph.page) >= pages.size())
					throw RuntimeError("page index out of range");
				const BitmapFontPage& page = pages[glyph.page];
				emit(spriteBatch, rect, pos, color, glyph, page);
			}
		}
Example #15
0
bool CPetGlyphs::MouseButtonUpMsg(const Point &pt) {
	if (_highlightIndex >= 0) {
		CPetGlyph *glyph = getGlyph(_highlightIndex);
		if (glyph) {
			if (glyph->MouseButtonUpMsg(pt))
				return true;
		}
	}

	return false;
}
Example #16
0
bool CPetGlyphs::highlighted14() {
	if (_highlightIndex != -1) {
		CPetGlyph *pet = getGlyph(_highlightIndex);
		if (pet) {
			pet->updateTooltip();
			return true;
		}
	}

	return false;
}
Example #17
0
void T7GFont::drawChar(Graphics::Surface *dst, byte chr, int x, int y, uint32 color) const {
	// We ignore the color, as the font is already colored
	const Glyph *glyph = getGlyph(chr);
	const byte *src = glyph->pixels;
	byte *target = (byte *)dst->getBasePtr(x, y);

	for (int i = 0; i < glyph->height; i++) {
		memcpy(target, src, glyph->width);
		src += glyph->width;
		target += dst->pitch;
	}
}
Example #18
0
CGameObject *CPetGlyphs::getObjectAt(const Point &pt) const {
	for (int idx = 0; idx < _numVisibleGlyphs; ++idx) {
		Rect glyphRect = getRect(idx);
		if (glyphRect.contains(pt)) {
			CPetGlyph *glyph = getGlyph(getItemIndex(idx));
			if (glyph)
				return glyph->getObjectAt();
		}
	}

	return nullptr;
}
Example #19
0
void CPetGlyphs::draw(CScreenManager *screenManager) {
	if (_highlightIndex != -1) {
		int index = getHighlightedIndex(_highlightIndex);
		if (index != -1) {
			Point tempPoint;
			Point pt = getPosition(index);
			pt -= Point(12, 13);
			_selection.translate(pt.x, pt.y);
			_selection.draw(screenManager);
			_selection.translate(-pt.x, -pt.y);
		}
	}

	// Iterate through displaying glyphs on the screen
	int listSize = size();
	for (int index = 0; index < _numVisibleGlyphs; ++index) {
		int itemIndex = getItemIndex(index);

		if (itemIndex >= 0 && itemIndex < listSize) {
			Point pt = getPosition(index);
			CPetGlyph *glyph = getGlyph(itemIndex);

			if (glyph)
				glyph->drawAt(screenManager, pt, index == _highlightIndex);
		}
	}

	// Draw scrolling arrows if more than a screen's worth of items are showing
	if (listSize > _numVisibleGlyphs || (_flags & GFLAG_16)) {
		_scrollLeft.draw(screenManager);
		_scrollRight.draw(screenManager);
	}

	// Handle secondary highlight
	if (_highlightIndex != -1) {
		CPetGlyph *glyph = getGlyph(_highlightIndex);
		if (glyph)
			glyph->draw2(screenManager);
	}
}
Example #20
0
bool CPetGlyphs::MouseDragStartMsg(CMouseDragStartMsg *msg) {
	if (!(_flags & GFLAG_1) && _highlightIndex >= 0) {
		CPetGlyph *glyph = getGlyph(_highlightIndex);
		int index = getHighlightedIndex(_highlightIndex);
		Rect glyphRect = getRect(index);

		if (glyphRect.contains(msg->_mousePos))
			return glyph->dragGlyph(glyphRect, msg);
		else
			return glyph->MouseDragStartMsg(msg);
	}

	return false;
}
Example #21
0
void TtfFont::printText(const std::string &text,
                        int32_t x, int32_t y,
                        float Red, float Green, float Blue, float Alpha,
                        uint32_t fontSize)
{
    SDL_assert_release(g_ft);
    if(text.empty())
        return;

    uint32_t offsetX = 0;
    uint32_t offsetY = 0;

    const char *strIt  = text.c_str();
    const char *strEnd = strIt + text.size();
    for(; strIt < strEnd; strIt++)
    {
        const char &cx = *strIt;
        UTF8 ucx = static_cast<unsigned char>(cx);

        switch(cx)
        {
        case '\n':
            offsetX = 0;
            offsetY += (fontSize * 1.5);
            continue;

        case '\t':
            //Fake tabulation
            offsetX += offsetX + offsetX % uint32_t(fontSize * 1.5);
            continue;
//        case ' ':
//            offsetX += m_spaceWidth + m_interLetterSpace / 2;
//            continue;
        }

        TheGlyph &glyph = getGlyph(fontSize, get_utf8_char(&cx));
        GlRenderer::setTextureColor(Red, Green, Blue, Alpha);
        int32_t glyph_x = x + static_cast<int32_t>(offsetX);
        int32_t glyph_y = y + static_cast<int32_t>(offsetY + fontSize);
        GlRenderer::renderTexture(glyph.tx,
                                  static_cast<float>(glyph_x + glyph.left),
                                  static_cast<float>(glyph_y - glyph.top),
                                  glyph.width,
                                  glyph.height
                                  );
        offsetX += uint32_t(glyph.advance>>6);

        strIt += static_cast<size_t>(trailingBytesForUTF8[ucx]);
    }
}
Example #22
0
void CPetGlyphs::setFirstVisible(int index) {
	if (index != _firstVisibleIndex) {
		_firstVisibleIndex = index;

		if ((_flags & GFLAG_8) && _highlightIndex != -1) {
			CPetGlyph *glyph = getGlyph(_highlightIndex);

			if (glyph) {
				int idx = getHighlightedIndex(_highlightIndex);
				if (idx != -1) {
					Point tempPt = getPosition(idx);
					glyph->glyphFocused(tempPt, true);
				}
			}
		}
	}
}
Example #23
0
/** Render a text
  *
  * \param qr              The quad renderer used to draw
  * \param vText           The rendered text
  * \param vColor          The color of rendering
  * \param vPos            The position of rendering
  * \param vSelection      Is a selection should be drawn
  * \param vSelectionStart The start selection char
  * \param vSelectionEnd   The end selection char
  *
  */
void RainbruRPG::OgreGui::Font::
render( Brush* qr, const string& vText, const ColourValue& vColor, 
	const Vector2& vPos, bool vSelection, int vSelectionStart, 
	int vSelectionEnd ) const{

  int count = vText.size();

  float currentX = vPos.x;
  float currentY = vPos.y;

  Vector2 tsize (mTexture->getWidth(), mTexture->getHeight());
  Ogre::Rectangle r;

  int x=0;

  for ( x = 0; x < count; x++ ){
    Glyph* g = getGlyph( vText[x] );
    r.top=currentY+g->getOffsetY()+g->getHeight();
    r.left=currentX;

    if ( vSelection == false ){
      r.bottom=r.top+g->getHeight();
      r.right=r.left+g->getWidth();

      Ogre::Rectangle uvr = g->getGeometry();
      uvr.left /= tsize.x;
      uvr.right /= tsize.x;
      uvr.top /= tsize.y;
      uvr.bottom /= tsize.y;
      
      qr->addGlyph( r, uvr, true );
    }
    else{
      r.right=r.left+g->getSpace();
      r.bottom=r.top+mMaxGlyphHeight;

      if ( (x >= vSelectionStart) && (x < vSelectionEnd) ){
	qr->addGlyph(r, Ogre::Rectangle());
      }
    }

    currentX += g->getSpace();
  }
}
Example #24
0
//--------------------------------------------------------------------------------------------------
/// Get the extent (width and height) of the given text with this font in pixels
//--------------------------------------------------------------------------------------------------
cvf::Vec2ui Font::textExtent(const String& text)
{
    Vec2ui textBB(0,0);

    int minHeight = std::numeric_limits<int>::max();
    int maxHeight = std::numeric_limits<int>::min();

    size_t numCharacters = text.size();
    for (size_t j = 0; j < numCharacters; j++)
    {
        wchar_t character = text[j];
        ref<Glyph> glyph = getGlyph(character);

        // Find bottom and top with regards to baseline (Y = 0)
        int minY = static_cast<int>(glyph->horizontalBearingY()) - static_cast<int>(glyph->height());
        int maxY = glyph->horizontalBearingY();

        if (minHeight > minY) minHeight = minY;
        if (maxHeight < maxY) maxHeight = maxY;

        uint charWidth  = 0;

        if (j < (numCharacters - 1))
        {
            charWidth = advance(character, text[j + 1]);
        }
        else
        {
            charWidth  = glyph->width() + glyph->horizontalBearingX();
        }

        textBB.x() += charWidth;
    }

    if (maxHeight < minHeight)
    {
        return Vec2ui(0,0);
    }

    textBB.y() = static_cast<uint>(maxHeight - minHeight);

    return textBB;
}
Example #25
0
void TextRenderer::draw(int x, int y, const char* str) {

    glEnable(GL_TEXTURE_2D);    
    
    for (const char* ch = str; *ch != 0; ch++) {
        const Glyph& glyph = getGlyph(*ch);
        if (glyph.textureID() == 0) {
            x += glyph.width();
            continue;
        }
        
        glBindTexture(GL_TEXTURE_2D, glyph.textureID());
        
        int left = x + glyph.bounds().x();
        int right = x + glyph.bounds().x() + glyph.bounds().width();
        int bottom = y + glyph.bounds().y();
        int top = y + glyph.bounds().y() + glyph.bounds().height();
        
        float scale = 1.0 / IMAGE_SIZE;
        float ls = glyph.location().x() * scale;
        float rs = (glyph.location().x() + glyph.bounds().width()) * scale;
        float bt = glyph.location().y() * scale;
        float tt = (glyph.location().y() + glyph.bounds().height()) * scale;
        
        glBegin(GL_QUADS);
        glTexCoord2f(ls, bt);
        glVertex2f(left, bottom);
        glTexCoord2f(rs, bt);
        glVertex2f(right, bottom);
        glTexCoord2f(rs, tt);
        glVertex2f(right, top);
        glTexCoord2f(ls, tt);
        glVertex2f(left, top);
        glEnd();
        
        x += glyph.width();
    }
    
    glBindTexture(GL_TEXTURE_2D, 0);
    glDisable(GL_TEXTURE_2D);
}
	ArrayList<RenderedGlyphContainer::RenderedGlyph> RenderedGlyphContainer::getRenderedGlyphs(void*fontptr, void*renderer, unsigned int size, int fontstyle, const GlyphString&txt, bool antialiasing)
	{
		mlock.lock();
		ArrayList<RenderedGlyph> glyphTextures;
		int ttf_style = Font::styleToTTFStyle(fontstyle);
		TTF_SetFontStyle((TTF_Font*)fontptr, ttf_style);
		size_t length = txt.length();
		for(size_t i=0; i<length; i++)
		{
			try
			{
				glyphTextures.add(getGlyph(txt.charAt(i), fontptr, renderer, size, fontstyle, antialiasing));
			}
			catch(const RenderGlyphException&e)
			{
				mlock.unlock();
				throw RenderGlyphException(e);
			}
		}
		mlock.unlock();
		return glyphTextures;
	}
Example #27
0
VkBool32 FreeTypeFont::renderText(const ICommandBuffersSP& cmdBuffer, const std::u32string& text, const size_t size, const glm::vec4& color)
{
    if (!face || !cmdBuffer.get())
    {
        return VK_FALSE;
    }

    //

    // TODO: Create once vertex buffer etc. like in example 3.

    // TODO: Create for each letter a descriptor set.

    //

    size_t textIndex = 0;

    FontCacheEntry* fontCacheEntry;

    while (textIndex < text.length())
    {
        // Do not use the render command buffer for creation-
        fontCacheEntry = getGlyph(text[textIndex], size);

        if (fontCacheEntry == nullptr)
        {
            return VK_FALSE;
        }

        // TODO: Bind descriptor set.

        // TODO: Draw triangle square.

        textIndex++;
    }

    return VK_TRUE;
}
Example #28
0
Image* Font::getWord (const std::string &word)
{
  Image *img = new Image;

  Vec2 off( 0, 0 );
  const char *cword = word.c_str();
  for (int c=0; cword[c] != '\0'; ++c)
  {
    if (cword[c] == '\n') {
      off.y -= size;
      off.x = 0;
      continue;
    }

    Object *o = getGlyph( cword[c], off );
    img->addObject( o->cubicsToQuads() );
    delete o;

    off.x += ft266ToFloat( ftFace->glyph->metrics.horiAdvance );
  }

  return img;
}
Example #29
0
bool CPetGlyphs::VirtualKeyCharMsg(CVirtualKeyCharMsg *msg) {
	Common::KeyCode key = msg->_keyState.keycode;

	switch (key) {
	case Common::KEYCODE_LEFT:
		decSelection();
		return true;

	case Common::KEYCODE_RIGHT:
		incSelection();
		return true;

	default:
		break;
	}

	if (_highlightIndex >= 0) {
		CPetGlyph *glyph = getGlyph(_highlightIndex);
		if (glyph && glyph->VirtualKeyCharMsg(msg))
			return true;
	}

	return false;
}
Example #30
0
void *MMSFBFont::loadFTGlyph(unsigned int character) {
	FT_GlyphSlot g = NULL;

	// load glyph but do NOT render a bitmap
	if (!FT_Load_Glyph((FT_Face)this->ft_face,
			FT_Get_Char_Index((FT_Face)this->ft_face, (FT_ULong)character), FT_LOAD_DEFAULT
//			FT_Get_Char_Index((FT_Face)this->ft_face, (FT_ULong)character), FT_LOAD_DEFAULT | FT_LOAD_FORCE_AUTOHINT
//		| FT_LOAD_TARGET_LIGHT
//		| FT_LOAD_TARGET_MONO
//		| FT_LOAD_TARGET_LCD
//		| FT_LOAD_TARGET_LCD_V
		)) {
		g = ((FT_Face)this->ft_face)->glyph;
	} else {
		MMSFB_SetError(0, "FT_Load_Glyph(,,FT_LOAD_DEFAULT) failed for " + this->filename);
	}

/*TEST CODE
	if (!FT_Load_Glyph((FT_Face)this->ft_face,
		FT_Get_Char_Index((FT_Face)this->ft_face, (FT_ULong)character), FT_LOAD_RENDER | FT_LOAD_FORCE_AUTOHINT)) {
		g = ((FT_Face)this->ft_face)->glyph;
	} else {
		MMSFB_SetError(0, "FT_Load_Glyph(,,FT_LOAD_RENDER) failed for " + this->filename);
	}
	showGlyphAttributes(g);
	exit(0);
*/

	if (g) {
#ifdef __HAVE_OPENGL__
		if (!mmsfb->bei) {
#else
		if (1) {
#endif
			// OpenGL is not initialized, we need a bitmap from freetype
			if (g->format != FT_GLYPH_FORMAT_BITMAP) {
				if (FT_Render_Glyph(g, FT_RENDER_MODE_NORMAL)) {
					// failed to load glyph
					MMSFB_SetError(0, "FT_Render_Glyph(,FT_RENDER_MODE_NORMAL) failed for " + this->filename);
					return NULL;
				}
			}

			if (g->bitmap.pixel_mode != FT_PIXEL_MODE_GRAY) {
				// failed to load glyph
				MMSFB_SetError(0, "glyph->bitmap.pixel_mode != FT_PIXEL_MODE_GRAY for " + this->filename);
				return NULL;
			}
		}
		else {
#ifndef __HAVE_GLU__
			// OpenGL is initialized but GLU is missing, we need a bitmap from freetype
			if (g->format != FT_GLYPH_FORMAT_BITMAP) {
				if (FT_Render_Glyph(g, FT_RENDER_MODE_NORMAL)) {
					// failed to load glyph
					MMSFB_SetError(0, "FT_Render_Glyph(,FT_RENDER_MODE_NORMAL) failed for " + this->filename);
					return NULL;
				}
			}

			if (g->bitmap.pixel_mode != FT_PIXEL_MODE_GRAY) {
				// failed to load glyph
				MMSFB_SetError(0, "glyph->bitmap.pixel_mode != FT_PIXEL_MODE_GRAY for " + this->filename);
				return NULL;
			}
#endif
		}

		// successfully loaded
		return g;
	}
	else {
		// failed to load glyph
		return NULL;
	}
}


bool MMSFBFont::setupFTGlyph(unsigned int character, void *ftg, MMSFBFont_Glyph *glyph) {
	if (!ftg || !glyph) return false;
	FT_GlyphSlot g = (FT_GlyphSlot)ftg;

	glyph->character = character;

#ifdef __HAVE_OPENGL__
	if (!mmsfb->bei) {
#else
	if (1) {
#endif
		// OpenGL is not initialized, setup glyph for software rendering
		glyph->left		= g->bitmap_left;
		glyph->top		= g->bitmap_top;
		glyph->width	= g->bitmap.width;
		glyph->height	= g->bitmap.rows;
		glyph->advanceX	= g->advance.x / 64;
		glyph->pitch	= g->bitmap.pitch;

#ifdef __HAVE_OPENGL__
#ifdef __HAVE_GLU__
		glyph->meshes = NULL;
		glyph->outline = NULL;
#else
		glyph->texture = 0;
#endif
#endif
		glyph->buffer	= (unsigned char*)calloc(1, glyph->pitch * glyph->height);
		memcpy(glyph->buffer, g->bitmap.buffer, glyph->pitch * glyph->height);

		if (MMSFBBase_rotate180) {
			// rotate glyph by 180°
			rotateUCharBuffer180(glyph->buffer, glyph->pitch, glyph->width, glyph->height);
		}

		return true;
	}

#ifndef __HAVE_GLU__
#ifdef  __HAVE_OPENGL__
	// OpenGL is initialized but GLU is missing, we need a bitmap from freetype
	glyph->left		= g->bitmap_left;
	glyph->top		= g->bitmap_top;
	glyph->width	= g->bitmap.width;
	glyph->height	= g->bitmap.rows;
	glyph->advanceX	= g->advance.x / 64;

	/*
	printf("left %d width %d advanceX %d top %d height %d fonth %d - %d\n",
			glyph->left, glyph->width, glyph->advanceX, glyph->top, glyph->height, this->height, g->advance.y / 64);
	*/

	if (!g->bitmap.pitch) {
		// glyph has no bitmap (e.g. space char)
		glyph->pitch = 0;
		glyph->buffer = NULL;
		glyph->texture = 0;
		return true;
	}

	// add glyph to charmap, we use a pitch which is a multiple of 4 needed e.g. for OGL textures
	if(mmsfb->bei && (g->bitmap.pitch & 3)) {
		glyph->pitch = (g->bitmap.pitch & ~3) + 4;
		glyph->buffer = (unsigned char*)calloc(1, glyph->pitch * glyph->height);
		unsigned char *src = g->bitmap.buffer;
		unsigned char *dst = glyph->buffer;
		for(int i = 0; i < glyph->height; i++) {
			memcpy(dst, src, g->bitmap.pitch);
			src += g->bitmap.pitch;
			dst += glyph->pitch;
		}
	}
	else {
		glyph->pitch  = g->bitmap.pitch;
		glyph->buffer = (unsigned char*)calloc(1, glyph->pitch * glyph->height);
		memcpy(glyph->buffer, g->bitmap.buffer, glyph->pitch * glyph->height);
	}

	if (MMSFBBase_rotate180) {
		// rotate glyph by 180°
		rotateUCharBuffer180(glyph->buffer, glyph->pitch, glyph->width, glyph->height);
	}

	// create a texture for this glyph
	glyph->texture = 0;
	mmsfb->bei->createAlphaTexture(&glyph->texture, glyph->buffer,
							glyph->pitch, glyph->height);

	return true;
#endif

#else

	// OpenGL is initialized and GLU is available, we create meshes based on freetype outlines

bool with_outline = true;

	// init glyph basics
	glyph->buffer	= NULL;
	glyph->pitch	= 0;
/*	glyph->left		= (float)g->metrics.horiBearingX * this->scale_coeff;
	if (glyph->left>= 0) glyph->left = (glyph->left + 32) / 64; else glyph->left = (glyph->left - 32) / 64;
	glyph->top		= (float)g->metrics.horiBearingY * this->scale_coeff;
	if (glyph->top >= 0) glyph->top = (glyph->top + 32) / 64; else glyph->top = (glyph->top - 32) / 64;
	glyph->width	= ((float)g->metrics.width * this->scale_coeff + 32) / 64;
	glyph->height	= ((float)g->metrics.height * this->scale_coeff + 32) / 64;
	glyph->advanceX	= ((float)g->advance.x * this->scale_coeff + 32) / 64;
*/

	glyph->left		= g->metrics.horiBearingX / 64;
	glyph->top		= g->metrics.horiBearingY / 64;
	glyph->width	= g->metrics.width / 64;
	glyph->height	= g->metrics.height / 64;
	glyph->advanceX	= g->advance.x / 64;

	/*
	printf("left %d width %d advanceX %d top %d height %d fonth %d - %d\n",
			glyph->left, glyph->width, glyph->advanceX, glyph->top, glyph->height, this->height, g->advance.y / 64);
	*/

	// init glyph mesh and outline description
	glyph->meshes = NULL;
	glyph->outline = NULL;

	// my mesh id
	unsigned int subkey_mesh = glyph->character;
	glyph->meshes = new MMSFBBuffer(this->font_id, subkey_mesh);

	if (!with_outline) {
		// without outline
		if (glyph->meshes->isInitialized()) {
			// meshes already initialized
//			printf("MMSFBFont: meshes already initialized\n");
			return true;
		}
	}
	else {
		// my outline id
		unsigned int subkey_outline = 0x80000000 | glyph->character;
		glyph->outline = new MMSFBBuffer(this->font_id, subkey_outline);

		if (glyph->meshes->isInitialized() && glyph->outline->isInitialized()) {
			// meshes and outline already initialized
//			printf("MMSFBFont: meshes and outline already initialized\n");
			return true;
		}
	}

	// init tesselator
	MMSFTTesselator *ftv = new MMSFTTesselator(g);

	if (!glyph->meshes->isInitialized()) {
//		printf("MMSFBFont: have to generate meshes\n");

		ftv->generateGlyph();
		const MMSFTGlyph *ftglyph = ftv->getGlyph();
		if (!ftglyph) {
			// glyph not generated
			MMSFB_SetError(0, "MMSFTTesselator::generateGlyph() failed");
			delete ftv;
			return false;
		}

		if (!ftglyph->getMeshCount()) {
			// no meshes available, but o.k. (e.g. space char)
			delete ftv;
			return true;
		}

		// count max meshes
		unsigned short int max_meshes = 0;
		for (unsigned int m = 0; m < ftglyph->getMeshCount(); m++) {
			if (!ftglyph->getMesh(m)) continue;
			max_meshes++;
			if (max_meshes >= MMSFBFONT_GLYPH_MAX_MESHES) {
				printf("MMSFBFONT_GLYPH_MAX_MESHES(%u) reached, %u needed\n", MMSFBFONT_GLYPH_MAX_MESHES, ftglyph->getMeshCount());
			}
		}

		if (!max_meshes) {
			// no meshes available
			MMSFB_SetError(0, "no meshes available");
			delete ftv;
			return false;
		}

		// allocate base buffer for vertices and indices
		// we do not need to clear because all fields will be set separately
		MMSFBBuffer::INDEX_BUFFER index_buffer;
		MMSFBBuffer::VERTEX_BUFFER vertex_buffer;
		index_buffer.num_arrays = 0;
		index_buffer.max_arrays = max_meshes;
		index_buffer.arrays = (MMS_INDEX_ARRAY*)malloc(sizeof(MMS_INDEX_ARRAY) * index_buffer.max_arrays);
		vertex_buffer.num_arrays = 0;
		vertex_buffer.max_arrays = max_meshes;
		vertex_buffer.arrays = (MMS_VERTEX_ARRAY*)malloc(sizeof(MMS_VERTEX_ARRAY) * vertex_buffer.max_arrays);

		// for all meshes
		for (unsigned int m = 0; m < ftglyph->getMeshCount(); m++) {
			// prepare access to vertices and indices of glyph
			if (index_buffer.num_arrays >= max_meshes) {
				printf("max_meshes(%u) reached\n", max_meshes);
				break;
			}
			MMS_INDEX_ARRAY  *indices  = &index_buffer.arrays[index_buffer.num_arrays];
			MMS_VERTEX_ARRAY *vertices = &vertex_buffer.arrays[vertex_buffer.num_arrays];

			// get access to polygon data
			const MMSFTMesh *ftmesh = ftglyph->getMesh(m);
			if (!ftmesh) continue;

			// prepare indices
			// note: no need to allocate index buffer, because vertices are correctly sorted
			switch (ftmesh->getMeshType()) {
			case GL_TRIANGLES:
				initIndexArray(indices, MMS_INDEX_ARRAY_TYPE_TRIANGLES);
				break;
			case GL_TRIANGLE_STRIP:
				initIndexArray(indices, MMS_INDEX_ARRAY_TYPE_TRIANGLE_STRIP);
				break;
			case GL_TRIANGLE_FAN:
				initIndexArray(indices, MMS_INDEX_ARRAY_TYPE_TRIANGLE_FAN);
				break;
			default:
				// unsupported type
				printf("MMSFBFont: unsupported mesh type %u\n", ftmesh->getMeshType());
				delete ftv;
				return false;
			}

#ifndef __HAVE_OGL_HALF_FLOAT__
			// prepare vertices using normal 32bit floating point values
			initVertexArray(vertices, 2, ftmesh->getVertexCount(), MMS_VERTEX_DATA_TYPE_FLOAT);
#else
			// prepare vertices using 16bit half floating point values
			initVertexArray(vertices, 2, ftmesh->getVertexCount(), MMS_VERTEX_DATA_TYPE_HALF_FLOAT);
#endif
			// for all vertices in the polygon
			for (unsigned int v = 0; v < ftmesh->getVertexCount(); v++) {
				const MMSFTVertex &vertex = ftmesh->getVertex(v);
				MMS_VA_SET_VERTEX_2v(vertices, v,
									 (float)(vertex.X() - g->metrics.horiBearingX) / 64,
									 (float)(g->metrics.horiBearingY - vertex.Y()) / 64);
			}

			// next mesh
			index_buffer.num_arrays++;
			vertex_buffer.num_arrays++;
		}

		glyph->meshes->initBuffer(index_buffer, vertex_buffer);
	}

	if (with_outline && ftv->getContourCount() > 0) {
		if (!glyph->outline->isInitialized()) {
//			printf("MMSFBFont: have to generate outline\n");

			// add outline primitives
			unsigned short int max_outlines = ftv->getContourCount();

			// allocate base buffer for vertices and indices
			// we do not need to clear because all fields will be set separately
			MMSFBBuffer::INDEX_BUFFER index_buffer;
			MMSFBBuffer::VERTEX_BUFFER vertex_buffer;
			index_buffer.num_arrays = 0;
			index_buffer.max_arrays = max_outlines;
			index_buffer.arrays = (MMS_INDEX_ARRAY*)malloc(sizeof(MMS_INDEX_ARRAY) * index_buffer.max_arrays);
			vertex_buffer.num_arrays = 0;
			vertex_buffer.max_arrays = max_outlines;
			vertex_buffer.arrays = (MMS_VERTEX_ARRAY*)malloc(sizeof(MMS_VERTEX_ARRAY) * vertex_buffer.max_arrays);

			// for all contours (outlines)
			for (unsigned int c = 0; c < ftv->getContourCount(); c++) {
				// prepare access to vertices and indices of glyph
				if (index_buffer.num_arrays >= max_outlines) {
					printf("max_outlines(%u) reached\n", max_outlines);
					break;
				}
				MMS_INDEX_ARRAY  *indices  = &index_buffer.arrays[index_buffer.num_arrays];
				MMS_VERTEX_ARRAY *vertices = &vertex_buffer.arrays[vertex_buffer.num_arrays];

				// get access to contour data
				const MMSFTContour *ftcontour = ftv->getContour(c);
				if (!ftcontour) continue;

				// prepare indices
				// note: no need to allocate index buffer, because vertices are correctly sorted
				initIndexArray(indices, MMS_INDEX_ARRAY_TYPE_LINE_LOOP);

#ifndef __HAVE_OGL_HALF_FLOAT__
				// prepare vertices using normal 32bit floating point values
				initVertexArray(vertices, 2, ftcontour->getVertexCount(), MMS_VERTEX_DATA_TYPE_FLOAT);
#else
				// prepare vertices using 16bit half floating point values
				initVertexArray(vertices, 2, ftcontour->getVertexCount(), MMS_VERTEX_DATA_TYPE_HALF_FLOAT);
#endif
				// for all vertices in the polygon
				for (unsigned int v = 0; v < ftcontour->getVertexCount(); v++) {
					const MMSFTVertex &vertex = ftcontour->Vertex(v);
					MMS_VA_SET_VERTEX_2v(vertices, v,
										 (float)(vertex.X() - g->metrics.horiBearingX) / 64,
										 (float)(g->metrics.horiBearingY - vertex.Y()) / 64);
				}

				// next outline
				index_buffer.num_arrays++;
				vertex_buffer.num_arrays++;
			}

			glyph->outline->initBuffer(index_buffer, vertex_buffer);
		}
	}


// Test mit dreiecken zieht strom!!! dazu kommt noch das Skalierungsproblem...
/*	if (with_outline && ftv->getContourCount() > 0) {
		if (!glyph->outline->isInitialized()) {

			glyph->top		+= 0;
			glyph->width	+= 2;
			glyph->height	+= 2;
			glyph->advanceX	+= 2;


			// add outline primitives
			unsigned short int max_outlines = ftv->getContourCount();

			// allocate base buffer for vertices and indices
			// we do not need to clear because all fields will be set separately
			MMSFBBuffer::INDEX_BUFFER index_buffer;
			MMSFBBuffer::VERTEX_BUFFER vertex_buffer;
			index_buffer.num_arrays = 0;
			index_buffer.max_arrays = max_outlines;
			index_buffer.arrays = (MMS_INDEX_ARRAY*)malloc(sizeof(MMS_INDEX_ARRAY) * index_buffer.max_arrays);
			vertex_buffer.num_arrays = 0;
			vertex_buffer.max_arrays = max_outlines;
			vertex_buffer.arrays = (MMS_VERTEX_ARRAY*)malloc(sizeof(MMS_VERTEX_ARRAY) * vertex_buffer.max_arrays);

			// for all contours (outlines)
			for (unsigned int c = 0; c < ftv->getContourCount(); c++) {
				// prepare access to vertices and indices of glyph
				if (index_buffer.num_arrays >= max_outlines) {
					printf("max_outlines(%u) reached\n", max_outlines);
					break;
				}
				MMS_INDEX_ARRAY  *indices  = &index_buffer.arrays[index_buffer.num_arrays];
				MMS_VERTEX_ARRAY *vertices = &vertex_buffer.arrays[vertex_buffer.num_arrays];

				// get access to contour data
				const MMSFTContour *ftcontour = ftv->getContour(c);
				if (!ftcontour) continue;

				// prepare indices
				// note: no need to allocate index buffer, because vertices are correctly sorted
				initIndexArray(indices, MMS_INDEX_ARRAY_TYPE_TRIANGLES);

				// prepare vertices using normal 32bit floating point values
				initVertexArray(vertices, 2, ftcontour->getVertexCount() * 6, MMS_VERTEX_DATA_TYPE_FLOAT);
printf("*********************\n");
				for (unsigned int v = 0; v < ftcontour->getVertexCount(); v++) {
					const MMSFTVertex &vertex1 = ftcontour->Vertex(v);
					const MMSFTVertex &outset1 = ftcontour->Outset(v);
					const MMSFTVertex &vertex2 = ftcontour->Vertex((v+1 < ftcontour->getVertexCount()) ? v+1 : 0);
					const MMSFTVertex &outset2 = ftcontour->Outset((v+1 < ftcontour->getVertexCount()) ? v+1 : 0);
printf("v: %f,%f\n", vertex1.X(), vertex1.Y());
printf("o: %f,%f\n", outset1.X(), outset1.Y());

					float fac=3.0f;

					float *vdata = (float *)vertices->data;


					vdata[v*6 * vertices->eSize + 0] = (float)(vertex1.X() - g->metrics.horiBearingX) / 64;
					vdata[v*6 * vertices->eSize + 1] = (float)(g->metrics.horiBearingY - vertex1.Y()) / 64;

					vdata[v*6 * vertices->eSize + 2] = (float)(vertex1.X() + outset1.X() * fac - g->metrics.horiBearingX) / 64;
					vdata[v*6 * vertices->eSize + 3] = (float)(g->metrics.horiBearingY - vertex1.Y() - outset1.Y() * fac) / 64;

					vdata[v*6 * vertices->eSize + 4] = (float)(vertex2.X() - g->metrics.horiBearingX) / 64;
					vdata[v*6 * vertices->eSize + 5] = (float)(g->metrics.horiBearingY - vertex2.Y()) / 64;

					vdata[v*6 * vertices->eSize + 6] = (float)(vertex1.X() + outset1.X() * fac - g->metrics.horiBearingX) / 64;
					vdata[v*6 * vertices->eSize + 7] = (float)(g->metrics.horiBearingY - vertex1.Y() - outset1.Y() * fac) / 64;

					vdata[v*6 * vertices->eSize + 8] = (float)(vertex2.X() + outset2.X() * fac - g->metrics.horiBearingX) / 64;
					vdata[v*6 * vertices->eSize + 9] = (float)(g->metrics.horiBearingY - vertex2.Y() - outset2.Y() * fac) / 64;

					vdata[v*6 * vertices->eSize + 10]= (float)(vertex2.X() - g->metrics.horiBearingX) / 64;
					vdata[v*6 * vertices->eSize + 11]= (float)(g->metrics.horiBearingY - vertex2.Y()) / 64;
				}

				// next outline
				index_buffer.num_arrays++;
				vertex_buffer.num_arrays++;
			}

			glyph->outline->initBuffer(index_buffer, vertex_buffer);
		}
	}
*/

    // all is successfully done
	delete ftv;
	return true;

#endif

	return false;
}

bool MMSFBFont::getGlyph(unsigned int character, MMSFBFont_Glyph *glyph) {
	if (!glyph) {
		return false;
	}

    if (mmsfb->backend == MMSFB_BE_DFB) {
#ifdef  __HAVE_DIRECTFB__
#endif
    }
    else {
    	if(!this->ft_face) {
    		return false;
    	}

    	bool ret = false;

    	lock();

    	// check if requested character is already loaded
    	std::map<unsigned int, MMSFBFont_Glyph>::iterator it;
    	it = this->charmap.find(character);
    	if (it == this->charmap.end()) {
    		// no, have to load it
			FT_GlyphSlot g;
			if (!(g = (FT_GlyphSlot)loadFTGlyph(character))) {
				// failed to load glyph
				unlock();
				return false;
			}

			// setup glyph values
			if (!setupFTGlyph(character, g, glyph)) {
				// failed to setup glyph
				unlock();
				return false;
			}

			// add to charmap
			this->charmap.insert(std::make_pair(character, *glyph));
			ret = true;
    	}
    	else {
    		// already loaded
    		*glyph = it->second;
			ret = true;
    	}

    	unlock();

    	return ret;
    }

    return false;
}


bool MMSFBFont::getStringWidth(string text, int len, int *width) {
    // check if initialized
    INITCHECK;

    // reset width
    if (!width) return false;
	*width = 0;

	// get the length of the string
	if (len < 0) len = text.size();
	if (!len) return true;

    // get the width of the whole string
#ifdef  __HAVE_DIRECTFB__
    if (this->dfbfont) {
		if (((IDirectFBFont*)this->dfbfont)->GetStringWidth((IDirectFBFont*)this->dfbfont, text.c_str(), len, width) != DFB_OK)
			return false;
		return true;
    } else
#endif
    {
    	MMSFBFONT_GET_UNICODE_CHAR(text, len) {
    		MMSFBFont_Glyph glyph;
    		if (!getGlyph(character, &glyph)) break;

#if (defined(__HAVE_OPENGL__) && defined(__HAVE_GLU__))
			if (mmsfb->bei) {
				// have to calculate advanceX because of scale coefficient
				(*width)+= (int)((float)glyph.advanceX * this->scale_coeff + 0.5f);
			}
			else
#endif
				(*width)+= glyph.advanceX;
    	} }
    	return true;
    }