Ejemplo n.º 1
0
void GSOsdManager::upload_texture_atlas(GSTexture* t) {
	if (!m_face) return;

	if (m_char_info.size() > 96) // we only reserved space for this many glyphs
		fprintf(stderr, "More than 96 glyphs needed for OSD");

	// This can be sped up a bit by only uploading new glyphs
	int x = 0;
	for(auto &pair : m_char_info) {
		if(FT_Load_Char(m_face, pair.first, FT_LOAD_RENDER)) {
			fprintf(stderr, "failed to load char U%d\n", (int)pair.first);
			continue;
		}

		// Size of char
		pair.second.ax = m_face->glyph->advance.x >> 6;
		pair.second.ay = m_face->glyph->advance.y >> 6;

		pair.second.bw = m_face->glyph->bitmap.width;
		pair.second.bh = m_face->glyph->bitmap.rows;

		pair.second.bl = m_face->glyph->bitmap_left;
		pair.second.bt = m_face->glyph->bitmap_top;

		GSVector4i r(x, 0, x+pair.second.bw, pair.second.bh);
		if (r.width())
			t->Update(r, m_face->glyph->bitmap.buffer, m_face->glyph->bitmap.pitch);

		if (r.width() > m_max_width) m_max_width = r.width();

		pair.second.tx = (float)x / m_atlas_w;
		pair.second.ty = (float)pair.second.bh / m_atlas_h;
		pair.second.tw = (float)pair.second.bw / m_atlas_w;

		x += pair.second.bw;
	}

	m_texture_dirty = false;
}
double PdfFontMetricsFreetype::UnicodeCharWidth( unsigned short c ) const
{
    FT_Error ftErr;
    double   dWidth = 0.0;


    if( static_cast<int>(c) < PODOFO_WIDTH_CACHE_SIZE ) 
    {
        dWidth = m_vecWidth[static_cast<unsigned int>(c)];
    }
    else
    {
        ftErr = FT_Load_Char( m_pFace, static_cast<FT_UInt>(c), FT_LOAD_NO_SCALE | FT_LOAD_NO_BITMAP );
        if( ftErr )
            return dWidth;

        dWidth = m_pFace->glyph->metrics.horiAdvance * 1000.0 / m_pFace->units_per_EM;
    }

    return dWidth * static_cast<double>(this->GetFontSize() * this->GetFontScale() / 100.0) / 1000.0 +
        static_cast<double>( this->GetFontSize() * this->GetFontScale() / 100.0 * this->GetFontCharSpace() / 100.0);
}
Ejemplo n.º 3
0
double swfStrWidthUTF8(const char *str, const pGEcontext gc, pDevDesc dd)
{
#ifdef SWF_DEBUG
    Rprintf("strWidthUTF8 called\n");
    Rprintf("** family = %s, str[0] = %d, str[1] = %d\n",
        gc->fontfamily, str[0], str[1]);
#endif
    /* Convert UTF-8 string to Unicode array */
    int maxLen = strlen(str);
    wchar_t *unicode = (wchar_t *) calloc(maxLen + 1, sizeof(wchar_t));
    int len = utf8towcs(unicode, str, maxLen);
    /* Get the font face object */
    FT_Face face = swfGetFTFace(gc);
    FT_Error err;
    double fontSize = gc->ps * gc->cex;
    double ratio = fontSize / face->units_per_EM;
    double width = 0.0;
    int i;
    /* Add up the 'advance' of each character */
    for(i = 0; i < len; i++)
    {
        err = FT_Load_Char(face, unicode[i], FT_LOAD_NO_SCALE);
        if(err)
        {
            errorcode(err);
            continue;
        }
        width += face->glyph->metrics.horiAdvance * ratio;
    }
    
    free(unicode);

#ifdef SWF_DEBUG
    Rprintf("** strWidthUTF8(width = %f)\n", width);
#endif

    return width;
}
Ejemplo n.º 4
0
void render_text(const std::string &str, FT_Face face, float x, float y, float sx, float sy) {
	glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
	const FT_GlyphSlot glyph = face->glyph;

	for (auto c : str) {
		if (FT_Load_Char(face, c, FT_LOAD_RENDER) != 0)
			continue;

		glTexImage2D(GL_TEXTURE_2D, 0, GL_R8,
			glyph->bitmap.width, glyph->bitmap.rows,
			0, GL_RED, GL_UNSIGNED_BYTE, glyph->bitmap.buffer);

		const float vx = x + glyph->bitmap_left * sx;
		const float vy = y + glyph->bitmap_top * sy;
		const float w = glyph->bitmap.width * sx;
		const float h = glyph->bitmap.rows * sy;

		struct {
			float x, y, s, t;
		} data[6] = {
			{ vx    , vy    , 0, 0 },
			{ vx    , vy - h, 0, 1 },
			{ vx + w, vy    , 1, 0 },
			{ vx + w, vy    , 1, 0 },
			{ vx    , vy - h, 0, 1 },
			{ vx + w, vy - h, 1, 1 }
		};

		glBufferData(GL_ARRAY_BUFFER, 24 * sizeof(float), data, GL_DYNAMIC_DRAW);
		glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, 0, 0);
		glDrawArrays(GL_TRIANGLES, 0, 6);

		x += (glyph->advance.x >> 6) * sx;
		y += (glyph->advance.y >> 6) * sy;
	}

	glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
}
Ejemplo n.º 5
0
/**
* Gets the width of a string. The width of a string is not necesserily
* the sum of all the widths of it's glyphs.
*
* @param text The string to return the width of.
* @return The width of a string.
*/
int OpenGLFont::getWidth(const std::string& text) const
{
	unsigned int w = 0;

	const char* ptr = text.c_str();
	size_t textlen = strlen(ptr);
	while (textlen > 0) {
		Uint32 c = UTF8_getch(&ptr, &textlen);
		if (c == UNICODE_BOM_NATIVE || c == UNICODE_BOM_SWAPPED) {
			continue;
		}

		FT_GlyphSlot slot = this->pmpl->face->glyph;

		// Load glyph image into the slot
		int error = FT_Load_Char(this->pmpl->face, c, FT_LOAD_DEFAULT);
		if (error) continue;

		w += (slot->advance.x >> 6);
	}

	return w;
}
Ejemplo n.º 6
0
Face *FontManager::getFont(const std::string fontPath, const int size) {
    if (fonts.count(fontPath + std::to_string(size)) == 0) {
        FT_Face face;
        if (FT_New_Face(ft, fontPath.c_str(), 0, &face)) {
            std::cerr << "Could not create font with path=[" << fontPath << "]" << std::endl
            << "Creating with default path=[" << DEFAULT_FONT_PATH << "]" << std::endl;

            //if path is broken, this can be broken too, we need better error handling
            FT_New_Face(ft, DEFAULT_FONT_PATH.c_str(), 0, &face);
        }

        fonts[fontPath + std::to_string(size)] = new Face(glHelper, fontPath, size, face);
        FT_Set_Pixel_Sizes(face, 0, size);
        //now we should calculate what we have


        unsigned int w = 0;
        unsigned int h = 0;

        for (unsigned int i = 0; i < 256; i++) {
            if (FT_Load_Char(face, i, FT_LOAD_RENDER)) {
                fprintf(stderr, "Loading character %c failed!\n", i);
                continue;
            }

            w = std::max(w, face->glyph->bitmap.width);
            h = std::max(h, face->glyph->bitmap.rows);

        }

        std::cout << "atlas h: " << h << ", w " << w << std::endl;

        //now we have maximum size of the textures
    }

    return fonts[fontPath + std::to_string(size)];
}
Ejemplo n.º 7
0
static void YE_LoadGlyph(Font *font, FT_Face face, char c)
{
    FT_Error error = FT_Load_Char(face, c, FT_LOAD_RENDER);
    if (error)
    {
        Log(1, "[Font loader] Failed to load glyph \"%c\": %s", c, FTErrorString(error));
        return;
    }

    FT_GlyphSlot glyph = face->glyph;

    byte *image = YE_ConvertBitmap(&glyph->bitmap);

    auto size = Vector2i(glyph->bitmap.width, glyph->bitmap.rows);
    auto offset = Vector2f(glyph->metrics.horiBearingX>>6, -(size.y - (glyph->metrics.horiBearingY>>6)));
    auto advance = Vector2f(glyph->advance.x>>6, glyph->advance.y>>6);

    GLuint texture;
    GLenum origformat = GL_LUMINANCE;
    GLenum gpuformat = GL_LUMINANCE8;

    glGenTextures(1, &texture);
    glBindTexture(GL_TEXTURE_2D, texture);

    // Turn off mipmaps and enable linear interpolation
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);

    glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
    glTexImage2D(GL_TEXTURE_2D, 0, gpuformat,
                 size.x, size.y,
                 0, // <----------------------------------------- old useless crap
                 origformat, GL_UNSIGNED_BYTE, image);

    font->SetGlyph(c, make_unique<Glyph>(texture, size, offset, advance));
    delete image;
}
Ejemplo n.º 8
0
void swfMetricInfo(int c, const pGEcontext gc, double* ascent, double* descent, double* width, pDevDesc dd)
{
#ifdef SWF_DEBUG
    Rprintf("metricInfo called\n");
    Rprintf("** family = %s, c = %d\n", gc->fontfamily, c);
#endif
    pswfDesc swfInfo = (pswfDesc) dd->deviceSpecific;
    FT_Face face = swfGetFTFace(gc, swfInfo);
    FT_Error err;
    double fontSize = gc->ps * gc->cex;
    double ratio = fontSize / face->units_per_EM;
  
    if(c == 0) c = 77;
    if(c < 0)
    {
        c = -c;
    }
    
    /* c is the unicode of the character */
    FT_Set_Char_Size(face, 0, fontSize * 64, 72, 0);
    err = FT_Load_Char(face, c, FT_LOAD_NO_SCALE);
    if(err)
    {
        errorcode(err);
        *ascent = *descent = *width = 0.0;
        return;
    }
    
    *ascent = face->glyph->metrics.horiBearingY * ratio;
    *descent = face->glyph->metrics.height * ratio - *ascent;
    *width = face->glyph->metrics.horiAdvance * ratio;
#ifdef SWF_DEBUG
    Rprintf("** metricInfo(ascent = %f, descent = %f, width = %f)\n",
            *ascent, *descent, *width);
#endif
}
Ejemplo n.º 9
0
void create_font_atlas(FontAtlas* fa, char* filename, unsigned int height) {
  Font f;
  if (!load_font(&f, filename)) {
    fprintf(stderr, "Couldn't load font from file: %s\n", filename);
  }
  FT_Set_Pixel_Sizes(f.face, 0, height);
  FT_GlyphSlot g = f.face->glyph;
  int roww = 0;
  int rowh = 0;
  fa->w = 0;
  fa->h = 0;
  memset(fa->c, 0, sizeof fa->c);
  /* Find minimum size for a texture holding all visible ASCII characters */
  for (int i = 32; i < 128; i++) {
    if (FT_Load_Char(f.face, i, FT_LOAD_RENDER)) {
      fprintf(stderr, "Loading character %c failed!\n", i);
      continue;
    }
    if (roww + g->bitmap.width + 1 >= MAXWIDTH) {
      fa->w = max(fa->w, roww);
      fa->h += rowh;
      roww = 0;
      rowh = 0;
    }
    roww += g->bitmap.width + 1;
    rowh = max(rowh, g->bitmap.rows);
  }

  fa->w = max(fa->w, roww);
  fa->h += rowh;

  init_atlas_texture(fa);
  copy_glyphs_to_texture(fa, &f);
  // Clean up
  delete_font(&f);
}
Ejemplo n.º 10
0
		CharStruct Measure(Char const *string, int length=0)
		{
			if (not length) while (string[length]) ++length;

			CharStruct extent;
			for (int it = 0; it < length; ++it)
			{
				FT_Load_Char(face, string[it], FT_LOAD_NO_BITMAP);
				FT_Glyph_Metrics &meter = face->glyph->metrics;

				extent.advance += meter.horiAdvance;
				if (extent.ascent < meter.horiBearingY)
				{
					extent.ascent = meter.horiBearingY;
				}

				FT_Pos diff = meter.height - meter.horiBearingY;
				if (extent.descent < diff)
				{
					extent.descent = diff;
				}
			}
			return extent;
		}
Ejemplo n.º 11
0
void SWFShape_addString(SWFShape shape, const wchar_t* str, size_t nchar,
                        double fontSize,
                        FT_Face face, FT_Outline_Funcs *funs)
{
    OutlineData data;
    FT_Outline outline;
    FT_Error err;
    int i;
    
    data.shape = shape;
    data.ratio_EM = fontSize / face->units_per_EM;
    data.deltax = 0.0;

    for(i = 0; i < nchar; i++)
    {
        /* str should be Unicode */
        err = FT_Load_Char(face, str[i], FT_LOAD_NO_SCALE);
        if(err)
        {
            errorcode(err);
            continue;
        }
        outline = face->glyph->outline;
        err = FT_Outline_Decompose(&outline, funs, &data);
        if(err)
        {
            errorcode(err);
            continue;
        }
        /* After we draw a character, we move the pen right to a distance
        of the advance */
        /* See the picture in
        http://www.freetype.org/freetype2/docs/tutorial/step2.html */
        data.deltax += face->glyph->metrics.horiAdvance * data.ratio_EM;
    }
}
Ejemplo n.º 12
0
void FreeTypeFont::initGlCmds()
{
	std::string vertex = vertexSource;
	std::string fragment = fragmentSource;
	mShaderManager = new ShaderManager(vertex, fragment, false);
	GLuint program = mShaderManager->getProgram();

	if (program == 0)
	{
		LOGE("In Font::initGlCmds() program is 0");
	}
	mHudMVPMatrixLocation = glGetUniformLocation(program, "u_mvpMatrix");
	mVetextLocation = glGetAttribLocation(program, "a_position");
	mTextureLocation = glGetAttribLocation(program, "a_texCoord");
	mSamplerLocation = glGetUniformLocation(program, "s_texture");
	mColorLocation = glGetUniformLocation(program, "u_color");

	glGenBuffers(1, &mVertexVBO);
	// Bind the VBO
	glBindBuffer(GL_ARRAY_BUFFER, mVertexVBO);

	if(FT_Load_Char(mFace, 'A', FT_LOAD_RENDER)) {
		LOGE("Could not load character 'X'\n");
		return ;
	}
	FT_GlyphSlot g = mFace->glyph;
	float sx = 2.0 / Scene::getInstance()->getWidth();
	float sy = 2.0 / Scene::getInstance()->getHeight();
	float x2 = 0.1 + g->bitmap_left * sx;
	float y2 = -0.1 - g->bitmap_top * sy;
	float w = g->bitmap.width * sx;
	float h = g->bitmap.rows * sy;

	GLfloat box[] = {
			x2,     -y2 ,
			x2 + w, -y2 ,
			x2,     -y2 - h,
			x2 + w, -y2 - h,
	};

	glGenTextures(1, &mTextureId);
	// Set the filtering mode
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);

	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
	// Bind the texture
	glActiveTexture(GL_TEXTURE0);
	glBindTexture(GL_TEXTURE_2D, mTextureId);

	glTexImage2D(
	      GL_TEXTURE_2D,
	      0,
	      GL_ALPHA,
	      g->bitmap.width,
	      g->bitmap.rows,
	      0,
	      GL_ALPHA,
	      GL_UNSIGNED_BYTE,
	      g->bitmap.buffer
	    );

	glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
	//glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 128, 128, 0, GL_RGBA, GL_UNSIGNED_BYTE, mTextureData);
	//delete[] mTextureData;
	float sceneWidth = Scene::getInstance()->getWidth();
	float sceneHeight = Scene::getInstance()->getHeight();
	float a = g->bitmap.width / sceneWidth;
	float b = g->bitmap.rows / sceneHeight;

	glm::mat4 mModelMatrix = glm::mat4(1.0);
	mModelMatrix = glm::translate(mModelMatrix, glm::vec3(0.5, 0.5, 0));
	mModelMatrix = glm::scale(mModelMatrix, glm::vec3(a, b, 0));
	Scene::getInstance()->getCamera()->updateHudMVP(128, 128);
	mHudMVPMatrix = Scene::getInstance()->getCamera()->getHudMVP() * mModelMatrix;

	mGLHasInitialized = true;
}
Ejemplo n.º 13
0
void Font::buildAtlas()
{
	//find the size we should use
	FT_GlyphSlot g = face->glyph;
	int w = 0;
	int h = 0;

	/*for(int i = 32; i < 128; i++)
	{
		if(FT_Load_Char(face, i, FT_LOAD_RENDER))
		{
			fprintf(stderr, "Loading character %c failed!\n", i);
			continue;
		}

		w += g->bitmap.width;
		h = std::max(h, g->bitmap.rows);
	}*/

	//the max size (GL_MAX_TEXTURE_SIZE) is like 3300
	w = 2048;
	h = 512;

	textureWidth = w;
	textureHeight = h;



	//create the texture
	glGenTextures(1, &textureID);
	glBindTexture(GL_TEXTURE_2D, textureID);

	glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
	glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);

	glPixelStorei(GL_PACK_ALIGNMENT, 1);
	glPixelStorei(GL_UNPACK_ALIGNMENT, 1);

	glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, w, h, 0, GL_ALPHA, GL_UNSIGNED_BYTE, NULL);

	//copy the glyphs into the texture
	int x = 0;
	int y = 0;
	int maxHeight = 0;
	for(int i = 32; i < 128; i++)
	{
		if(FT_Load_Char(face, i, FT_LOAD_RENDER))
			continue;

		 //prints rendered texture to the console
		/*std::cout << "uploading at x: " << x << ", w: " << g->bitmap.width << " h: " << g->bitmap.rows << "\n";

		for(int k = 0; k < g->bitmap.rows; k++)
		{
			for(int j = 0; j < g->bitmap.width; j++)
			{
				if(g->bitmap.buffer[g->bitmap.width * k + j])
					std::cout << ".";
				else
					std::cout << " ";
			}
			std::cout << "\n";
		}*/

		if(x + g->bitmap.width >= textureWidth)
		{
			x = 0;
			y += maxHeight;
			maxHeight = 0;
		}

		if(g->bitmap.rows > maxHeight)
			maxHeight = g->bitmap.rows;

		glTexSubImage2D(GL_TEXTURE_2D, 0, x, y, g->bitmap.width, g->bitmap.rows, GL_ALPHA, GL_UNSIGNED_BYTE, g->bitmap.buffer);


		charData[i].texX = x;
		charData[i].texY = y;
		charData[i].texW = g->bitmap.width;
		charData[i].texH = g->bitmap.rows;
		charData[i].advX = g->metrics.horiAdvance >> 6;
		charData[i].advY = g->advance.y >> 6;
		charData[i].bearingY = g->metrics.horiBearingY >> 6;

		if(charData[i].texH > mMaxGlyphHeight)
			mMaxGlyphHeight = charData[i].texH;

		x += g->bitmap.width;
	}

	glBindTexture(GL_TEXTURE_2D, 0);

	//std::cout << "generated texture \"" << textureID << "\" (w: " << w << " h: " << h << ")" << std::endl;
}
Ejemplo n.º 14
0
//------------------------------------------------------------------------------------
// загрузка и генерация всех необходимых данных для символа (utf32)
//------------------------------------------------------------------------------------
eFontChar* vw_LoadFontChar(unsigned UTF32)
{
	// устанавливаем размеры
	if (FT_Set_Char_Size( InternalFace, InternalFontSize <<6, InternalFontSize <<6, 96, 96 ))
	{
		fprintf(stderr, "Can't set char size %i.", InternalFontSize);
		return 0;
	}


	// загрузка глифа нужного нам символа
	if (FT_Load_Char( InternalFace, UTF32, FT_LOAD_RENDER | FT_LOAD_NO_HINTING | FT_LOAD_NO_AUTOHINT))
	{
		fprintf(stderr, "Can't load Char: %u\n", UTF32);
		return 0;
	}


	// создаем структуру FontChar
	eFontChar* NewChar;
	NewChar = new eFontChar;

	NewChar->UTF32 = UTF32;
	NewChar->CharTexture = 0;
	NewChar->FontSize = InternalFontSize;
	NewChar->TexturePositionLeft = 0;
	NewChar->TexturePositionRight = InternalFace->glyph->bitmap.width; // в случае одной текстуры совпадают с шириной
	NewChar->TexturePositionTop = 0;
	NewChar->TexturePositionBottom = InternalFace->glyph->bitmap.rows; // в случае одной текстуры совпадают с высотой
	NewChar->Width = InternalFace->glyph->bitmap.width;
	NewChar->Height = InternalFace->glyph->bitmap.rows;
	NewChar->Left = InternalFace->glyph->bitmap_left;
	NewChar->Top = InternalFace->glyph->bitmap_top;
	NewChar->AdvanceX = InternalFace->glyph->advance.x / 64.0f;
	NewChar->Prev = 0;
	NewChar->Next = 0;

	BYTE * pixels;
	pixels = new BYTE[NewChar->Width*NewChar->Height*4];

	// битмап идет в 1 канале градаций серого, делаем 32бита rgba
	int k=0;
	BYTE ColorRGB[3]={255,255,255};
	for (int j=0; j<NewChar->Height; j++)
	{
		for (int i=0; i<NewChar->Width; i++)
		{
			// RGB составляющую заполняем белым
			memcpy(pixels + k, ColorRGB, 3);
			k+=3;
			memcpy(pixels + k, InternalFace->glyph->bitmap.buffer+(NewChar->Height-j-1)*NewChar->Width+i, 1);
			k++;
		}
	}

	// называем текстуру номером символа в утф32
	char texturefilename[MAX_PATH];
	sprintf(texturefilename, "%i", UTF32);

	vw_SetTextureProp(RI_MAGFILTER_LINEAR | RI_MINFILTER_LINEAR | RI_MIPFILTER_NONE, RI_CLAMP_TO_EDGE, true, TX_ALPHA_GREYSC, false);
	NewChar->CharTexture = vw_CreateTextureFromMemory(texturefilename, pixels, NewChar->Width, NewChar->Height, 4, false, 0, 0, false);
	// очищаем память
	delete [] pixels;

	// подключаем к менеджеру
	vw_AttachFontChar(NewChar);
	return NewChar;
}
Ejemplo n.º 15
0
//-----------------------------------------------------------------------------
// делаем генерацию нужных символов по списку генерируя одну текстуру
//-----------------------------------------------------------------------------
void vw_GenerateFontChars(int FontTextureWidth, int FontTextureHeight, const char * CharsList)
{

	printf("Font characters generation start.\n");

	// будем использовать последовательность как имя текстуры
	const char *TextureName = CharsList;
	// временный массив
	BYTE * DIB;
	DIB = new BYTE[FontTextureWidth*FontTextureHeight*4]; // всегда делаем rgba
	// устанавливаем 0 везде, чтобы потом не краcить rgb, а только формировать альфу
	memset(DIB, 0, FontTextureWidth*FontTextureHeight*4);

	// данные для работы с вклеиванием в текстуру
	int CurrentDIBX = 0;
	int CurrentDIBY = 0;
	int EdgingSpace = 2;
	int MaxHeightInCurrentLine = 0;

	// устанавливаем размеры
	if (FT_Set_Char_Size( InternalFace, InternalFontSize <<6, InternalFontSize <<6, 96, 96 ))
	{
		fprintf(stderr, "Can't set char size %i.", InternalFontSize);
		return;
	}

	// первый проход, формируем одну большую текстуру
	const char *CharsList2 = CharsList;
	while (strlen(CharsList) > 0)
	{
		unsigned CurrentChar;
		// преобразуем в утф32 и "сдвигаемся" на следующий символ в строке
		CharsList = utf8_to_utf32(CharsList, &CurrentChar);


		// загрузка глифа нужного нам символа
		if (FT_Load_Char( InternalFace, CurrentChar, FT_LOAD_RENDER | FT_LOAD_NO_HINTING | FT_LOAD_NO_AUTOHINT))
		{
			fprintf(stderr, "Can't load Char: %u\n", CurrentChar);
			return;
		}

		// создаем структуру FontChar
		eFontChar* NewChar;
		NewChar = new eFontChar;

		NewChar->UTF32 = CurrentChar;
		NewChar->CharTexture = 0;
		NewChar->FontSize = InternalFontSize;
		NewChar->TexturePositionLeft = 0;
		NewChar->TexturePositionRight = 0;
		NewChar->TexturePositionTop = 0;
		NewChar->TexturePositionBottom = 0;
		NewChar->Width = InternalFace->glyph->bitmap.width;
		NewChar->Height = InternalFace->glyph->bitmap.rows;
		NewChar->Left = InternalFace->glyph->bitmap_left;
		NewChar->Top = InternalFace->glyph->bitmap_top;
		NewChar->AdvanceX = InternalFace->glyph->advance.x / 64.0f;
		NewChar->Prev = 0;
		NewChar->Next = 0;

		// делаем установку параметров для вклеивания

		// если в текущую строку символов уже не можем вписывать - смещаемся на новую, ниже
		if (CurrentDIBX + NewChar->Width > FontTextureWidth)
		{
			CurrentDIBX = 0;
			CurrentDIBY += MaxHeightInCurrentLine + EdgingSpace;
			MaxHeightInCurrentLine = 0;
		}
		// если в текущую строку не влазит уже по высоте - значит это фейл... кричим чтоб дали больше текстуру
		if (CurrentDIBY + NewChar->Height > FontTextureHeight)
		{
			fprintf(stderr, "!!! Can't generate all font chars in one texture. Too many chars or too small texture size!\n");
			delete NewChar;
			break;
		}

		// "вклеиваем" новый символ в массив
		BYTE ColorRGB[3]={255,255,255};
		for (int j=0; j<NewChar->Height; j++)
		for (int i=0; i<NewChar->Width; i++)
		{
			memcpy(DIB + (FontTextureHeight-CurrentDIBY-j-1)*FontTextureWidth*4 + (CurrentDIBX+i)*4,
					ColorRGB,
					3);
			memcpy(DIB + (FontTextureHeight-CurrentDIBY-j-1)*FontTextureWidth*4 + (CurrentDIBX+i)*4 + 3,
					InternalFace->glyph->bitmap.buffer+j*NewChar->Width+i,
					1);
		}

		// устанавливаем параметры текстуры для прорисовки нашему символу
		NewChar->TexturePositionLeft = CurrentDIBX;
		NewChar->TexturePositionRight = CurrentDIBX + NewChar->Width;
		NewChar->TexturePositionTop = CurrentDIBY;
		NewChar->TexturePositionBottom = CurrentDIBY + NewChar->Height;

		// выбираем наибольшую высоту символов
		if (MaxHeightInCurrentLine < NewChar->Height) MaxHeightInCurrentLine = NewChar->Height;
		// смещаем указатель
		CurrentDIBX += NewChar->Width + EdgingSpace;

		// подключаем к менеджеру
		vw_AttachFontChar(NewChar);
	}


/////////////////////////////////
/*
	// выводим в tga файл сгенерированный DIB, если нужно проверить

	SDL_RWops *TgaFile = SDL_RWFromFile("fontgenerationtest.tga", "wb");
	if (TgaFile == NULL)
    {
		fprintf(stderr, "Can't open VFS file for write.\n");
        return;
    }

	unsigned char UselessChar = 0;	// used for useless char.
	short int UselessInt = 0;		// used for useless int.
	unsigned char ImageType = 2;	// Type of image we are saving.
	unsigned char ImageBits = 32;		// Bit depth.
	short int ImageWidth = (short int)FontTextureWidth;
	short int ImageHeight = (short int)FontTextureHeight;

	// пишем неиспользуемые данные
	SDL_RWwrite(TgaFile, &UselessChar, sizeof(unsigned char), 1);
	SDL_RWwrite(TgaFile, &UselessChar, sizeof(unsigned char), 1);
	// тип картинки
	SDL_RWwrite(TgaFile, &ImageType, sizeof(unsigned char), 1);
	// пишем неиспользуемые данные
	SDL_RWwrite(TgaFile, &UselessInt, sizeof(short int), 1);
	SDL_RWwrite(TgaFile, &UselessInt, sizeof(short int), 1);
	SDL_RWwrite(TgaFile, &UselessChar, sizeof(unsigned char), 1);
	SDL_RWwrite(TgaFile, &UselessInt, sizeof(short int), 1);
	SDL_RWwrite(TgaFile, &UselessInt, sizeof(short int), 1);
	// записываем параметры картинки
	SDL_RWwrite(TgaFile, &ImageWidth, sizeof(short int), 1);
	SDL_RWwrite(TgaFile, &ImageHeight, sizeof(short int), 1);
	SDL_RWwrite(TgaFile, &ImageBits, sizeof(unsigned char), 1);
	// пишем неиспользуемые данные
	SDL_RWwrite(TgaFile, &UselessChar, sizeof(unsigned char), 1);
	// пишем данные диб массива
	SDL_RWwrite(TgaFile, DIB, FontTextureWidth*FontTextureHeight*4, 1);

	// закрываем файл
	SDL_RWclose(TgaFile);
*/
/////////////////////////////////


	// создаем текстуру
	vw_SetTextureProp(RI_MAGFILTER_LINEAR | RI_MINFILTER_LINEAR | RI_MIPFILTER_NONE, RI_CLAMP_TO_EDGE, true, TX_ALPHA_GREYSC, false);
	eTexture* FontTexture = vw_CreateTextureFromMemory(TextureName, DIB, FontTextureWidth, FontTextureHeight, 4, false);
	// освобождаем память
	delete [] DIB;
	if (FontTexture == 0)
	{
		fprintf(stderr, "Can't create font texture.\n");
		return;
	}


	// второй проход, всем FontChars из списка, присваиваем сгенерированную текстуру
	while (strlen(CharsList2) > 0)
	{
		unsigned CurrentChar;
		// преобразуем в утф32 и "сдвигаемся" на следующий символ в строке
		CharsList2 = utf8_to_utf32(CharsList2, &CurrentChar);
		// ставим нашу общую текстуру
		eFontChar* TMPChar = vw_FindFontCharByUTF32(CurrentChar);
		if (TMPChar != 0) TMPChar->CharTexture = FontTexture;
	}


	printf("Font characters generation end.\n\n");
}
Ejemplo n.º 16
0
osgText::Glyph3D * FreeTypeFont::getGlyph3D(unsigned int charcode)
{
    OpenThreads::ScopedLock<OpenThreads::Mutex> lock(FreeTypeLibrary::instance()->getMutex());

    //
    // GT: fix for symbol fonts (i.e. the Webdings font) as the wrong character are being
    // returned, for symbol fonts in windows (FT_ENCONDING_MS_SYMBOL in freetype) the correct
    // values are from 0xF000 to 0xF0FF not from 0x000 to 0x00FF (0 to 255) as you would expect.
    // Microsoft uses a private field for its symbol fonts
    //
    unsigned int charindex = charcode;
    if (_face->charmap != NULL)
    {
        if (_face->charmap->encoding == FT_ENCODING_MS_SYMBOL)
        {
            charindex |= 0xF000;
        }
    }

    FT_Error error = FT_Load_Char( _face, charindex, FT_LOAD_DEFAULT|_flags );
    if (error)
    {
        OSG_WARN << "FT_Load_Char(...) error 0x"<<std::hex<<error<<std::dec<<std::endl;
        return 0;
    }
    if (_face->glyph->format != FT_GLYPH_FORMAT_OUTLINE)
    {
        OSG_WARN << "FreeTypeFont3D::getGlyph : not a vector font" << std::endl;
        return 0;
    }

    float coord_scale = _freetype_scale/64.0f;

    // ** init FreeType to describe the glyph
    FreeType::Char3DInfo char3d(_facade->getNumberCurveSamples());
    char3d._coord_scale = coord_scale;

    FT_Outline outline = _face->glyph->outline;
    FT_Outline_Funcs funcs;
    funcs.conic_to = (FT_Outline_ConicToFunc)&FreeType::conicTo;
    funcs.line_to = (FT_Outline_LineToFunc)&FreeType::lineTo;
    funcs.cubic_to = (FT_Outline_CubicToFunc)&FreeType::cubicTo;
    funcs.move_to = (FT_Outline_MoveToFunc)&FreeType::moveTo;
    funcs.shift = 0;
    funcs.delta = 0;

    // ** record description
    FT_Error _error = FT_Outline_Decompose(&outline, &funcs, &char3d);
    if (_error)
    {
        OSG_WARN << "FreeTypeFont3D::getGlyph : - outline decompose failed ..." << std::endl;
        return 0;
    }

    // ** create geometry for each part of the glyph
    osg::ref_ptr<osg::Geometry> frontGeo(new osg::Geometry);

    osg::ref_ptr<osg::Vec3Array> rawVertices = new osg::Vec3Array(*(char3d._verts));
    osg::Geometry::PrimitiveSetList rawPrimitives;
    for(osg::Geometry::PrimitiveSetList::iterator itr = char3d.get()->getPrimitiveSetList().begin();
        itr != char3d.get()->getPrimitiveSetList().end();
        ++itr)
    {
        rawPrimitives.push_back(dynamic_cast<osg::PrimitiveSet*>((*itr)->clone(osg::CopyOp::DEEP_COPY_ALL)));
    }

    // ** save vertices and PrimitiveSetList of each face in the Glyph3D PrimitiveSet face list
    osg::ref_ptr<osgText::Glyph3D> glyph3D = new osgText::Glyph3D(_facade, charcode);

    // copy the raw primitive set list before we tessellate it.
    glyph3D->getRawFacePrimitiveSetList() = rawPrimitives;
    glyph3D->setRawVertexArray(rawVertices.get());


    FT_Glyph_Metrics* metrics = &(_face->glyph->metrics);

    glyph3D->setHorizontalBearing(osg::Vec2((float)metrics->horiBearingX * coord_scale,(float)(metrics->horiBearingY-metrics->height) * coord_scale)); // bottom left.
    glyph3D->setHorizontalAdvance((float)metrics->horiAdvance * coord_scale);
    glyph3D->setVerticalBearing(osg::Vec2((float)metrics->vertBearingX * coord_scale,(float)(metrics->vertBearingY-metrics->height) * coord_scale)); // top middle.
    glyph3D->setVerticalAdvance((float)metrics->vertAdvance * coord_scale);

    glyph3D->setWidth((float)metrics->width * coord_scale);
    glyph3D->setHeight((float)metrics->height * coord_scale);

    FT_BBox ftbb;
    FT_Outline_Get_BBox(&outline, &ftbb);

    long xmin = ft_floor( ftbb.xMin );
    long xmax = ft_ceiling( ftbb.xMax );
    long ymin = ft_floor( ftbb.yMin );
    long ymax = ft_ceiling( ftbb.yMax );

    osg::BoundingBox bb(xmin * coord_scale, ymin * coord_scale, 0.0f, xmax * coord_scale, ymax * coord_scale, 0.0f);

    glyph3D->setBoundingBox(bb);

    return glyph3D.release();
}
Ejemplo n.º 17
0
static bool font_renderer_create_atlas(ft_font_renderer_t *handle)
{
   unsigned i;
   bool ret = true;

   uint8_t *buffer[FT_ATLAS_SIZE] = {NULL};
   unsigned pitches[FT_ATLAS_SIZE] = {0};

   unsigned max_width = 0;
   unsigned max_height = 0;

   for (i = 0; i < FT_ATLAS_SIZE; i++)
   {
      FT_GlyphSlot slot;
      struct font_glyph *glyph = &handle->glyphs[i];

      if (!glyph)
         continue;

      if (FT_Load_Char(handle->face, i, FT_LOAD_RENDER))
      {
         ret = false;
         goto end;
      }

      FT_Render_Glyph(handle->face->glyph, FT_RENDER_MODE_NORMAL);
      slot = handle->face->glyph;

      /* Some glyphs can be blank. */
      buffer[i] = (uint8_t*)calloc(slot->bitmap.rows * slot->bitmap.pitch, 1);

      glyph->width = slot->bitmap.width;
      glyph->height = slot->bitmap.rows;
      pitches[i] = slot->bitmap.pitch;

      glyph->advance_x = slot->advance.x >> 6;
      glyph->advance_y = slot->advance.y >> 6;
      glyph->draw_offset_x = slot->bitmap_left;
      glyph->draw_offset_y = -slot->bitmap_top;

      if (buffer[i])
         memcpy(buffer[i], slot->bitmap.buffer,
               slot->bitmap.rows * pitches[i]);
      max_width  = MAX(max_width, (unsigned)slot->bitmap.width);
      max_height = MAX(max_height, (unsigned)slot->bitmap.rows);
   }

   handle->atlas.width = max_width * FT_ATLAS_COLS;
   handle->atlas.height = max_height * FT_ATLAS_ROWS;

   handle->atlas.buffer = (uint8_t*)
      calloc(handle->atlas.width * handle->atlas.height, 1);

   if (!handle->atlas.buffer)
   {
      ret = false;
      goto end;
   }

   /* Blit our texture atlas. */
   for (i = 0; i < FT_ATLAS_SIZE; i++)
   {
      uint8_t *dst      = NULL;
      unsigned offset_x = (i % FT_ATLAS_COLS) * max_width;
      unsigned offset_y = (i / FT_ATLAS_COLS) * max_height;

      handle->glyphs[i].atlas_offset_x = offset_x;
      handle->glyphs[i].atlas_offset_y = offset_y;

      dst = (uint8_t*)handle->atlas.buffer;
      dst += offset_x + offset_y * handle->atlas.width;

      if (buffer[i])
      {
         unsigned r, c;
         const uint8_t *src = (const uint8_t*)buffer[i];

         for (r = 0; r < handle->glyphs[i].height;
               r++, dst += handle->atlas.width, src += pitches[i])
            for (c = 0; c < handle->glyphs[i].width; c++)
               dst[c] = src[c];
      }
   }

end:
   for (i = 0; i < FT_ATLAS_SIZE; i++)
      free(buffer[i]);
   return ret;
}
Ejemplo n.º 18
0
bool mugg::gui::Font::Load(const std::string& path, unsigned int pixelSize = 48) {
    if(FT_New_Face(this->ft, path.c_str(), 0, &this->face)) {
        std::cout << "ERR: Failed to load font " << path << std::endl;
        return false;
    }

    FT_Set_Pixel_Sizes(this->face, 0, pixelSize);

    this->g = this->face->glyph;
    int w = 0;
    int h = 0;

    for(int i = 32; i < 128; i++) {
        if(FT_Load_Char(this->face, i, FT_LOAD_RENDER)) {
            std::cout << "ERR: Loading character " << i << " from " << path << " failed!\n";
        }

        w += this->g->bitmap.width;
        h = std::max(h, this->g->bitmap.rows);

        this->width = w;
    }

    glGenTextures(1, &this->textureID);
    glBindTexture(GL_TEXTURE_2D, this->textureID);

    glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, w, h, 0, GL_ALPHA, GL_UNSIGNED_BYTE, nullptr);
    
    glPixelStorei(GL_UNPACK_ALIGNMENT, 1);

    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
    
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);

    int x = 0;

    for(int i = 32; i < 128; i++) {
        if(FT_Load_Char(this->face, i, FT_LOAD_RENDER))
            continue;

        glTexSubImage2D(GL_TEXTURE_2D, 0, x, 0, this->g->bitmap.width, this->g->bitmap.rows, GL_ALPHA, GL_UNSIGNED_BYTE, this->g->bitmap.buffer);

        x += this->g->bitmap.width;
        
        const uint8_t *p;

        this->c[*p].ax = this->g->advance.x >> 6;
        this->c[*p].ay = this->g->advance.y >> 6;
        
        this->c[*p].bw = this->g->bitmap.width;
        this->c[*p].bh = this->g->bitmap.rows;
        
        this->c[*p].bl = this->g->bitmap_left;
        this->c[*p].bt = this->g->bitmap_top;
        
        this->c[*p].tx = (float)x / w;
    }

}
Ejemplo n.º 19
0
int init_timecode(p_info_rec* p_info, timecode_data* tc_data,
                  char* font, const int size,
                  const int aspect_ratio_num, const int aspect_ratio_den)
{
    info_rec*		info;
    FT_GlyphSlot	slot;
    char		cset[] = "0123456789:";
    int         bb_t, bb_b, bb_l, bb_r; // bounding box
    BYTE*		dstLine;
    BYTE*		srcPtr;
    BYTE*		dstPtr;
    int			c, j;
    int			result;

    // initialise our data
    if (*p_info == NULL)
    {
        result = allocate_info(p_info);
        if (result < 0)
            return result;
    }
    info = *p_info;
    // create a suitable text image
    result = set_font(info, font, size, aspect_ratio_num, aspect_ratio_den);
    if (result < 0)
        return result;
    // get bounding box for characters
    bb_t =  1000000;
    bb_b = -1000000;
    bb_l =  1000000;
    bb_r = -1000000;
    for (c = 0; c < 11; c++)
    {
        /* load glyph image into the slot (erase previous one) */
        if (FT_Load_Char(info->face, cset[c], FT_LOAD_RENDER))
            return YUV_freetype;
        slot = info->face->glyph;  /* a small shortcut */
        if (bb_t > -slot->bitmap_top)
            bb_t = -slot->bitmap_top;
        if (bb_b < slot->bitmap.rows - slot->bitmap_top)
            bb_b = slot->bitmap.rows - slot->bitmap_top;
        if (bb_l > slot->bitmap_left)
            bb_l = slot->bitmap_left;
        if (bb_r < slot->bitmap_left + slot->bitmap.width)
            bb_r = slot->bitmap_left + slot->bitmap.width;
    }
    // expand bounding box a little
    bb_t -= 1;
    bb_b += 1;
    bb_l -= 1;
    bb_r += 1;
    tc_data->height = bb_b - bb_t;
    // initialise character overlays
    for (c = 0; c < 11; c++)
    {
        tc_data->tc_ovly[c].w = bb_r - bb_l;
        tc_data->tc_ovly[c].h = tc_data->height;
        tc_data->tc_ovly[c].ssx = -1;
        tc_data->tc_ovly[c].ssy = -1;
        tc_data->tc_ovly[c].buff = malloc(tc_data->tc_ovly[c].w *
                                          tc_data->tc_ovly[c].h * 2);
        if (tc_data->tc_ovly[c].buff == NULL)
            return YUV_no_memory;
        memset(tc_data->tc_ovly[c].buff, 0, tc_data->tc_ovly[c].w *
                                            tc_data->tc_ovly[c].h * 2);
        tc_data->tc_ovly[c].Cbuff = NULL;
    }
    // copy bitmaps
    for (c = 0; c < 11; c++)
    {
        /* load glyph image into the slot (erase previous one) */
        if (FT_Load_Char(info->face, cset[c], FT_LOAD_RENDER))
            return YUV_freetype;
        slot = info->face->glyph;  /* a small shortcut */
        if (c == 10)
        {
            // make colon narrower than other characters
            tc_data->tc_ovly[c].w = slot->advance.x / 64;
        }
        srcPtr = slot->bitmap.buffer;
        dstLine = tc_data->tc_ovly[c].buff;
        // add vertical offset
        dstLine += tc_data->tc_ovly[c].w * (-slot->bitmap_top - bb_t);
        // horizontally centre character
        dstLine += (tc_data->tc_ovly[c].w - slot->bitmap.width) / 2;
        for (j = 0; j < slot->bitmap.rows; j++)
        {
            dstPtr = dstLine;
            memcpy(dstLine, srcPtr, slot->bitmap.width);
            srcPtr += slot->bitmap.width;
            dstLine += tc_data->tc_ovly[c].w;
        }
    }
    tc_data->width = (tc_data->tc_ovly[0].w * 8) +
                     (tc_data->tc_ovly[10].w * 3);	// 8 digits and 3 colons
    return YUV_OK;
}
Ejemplo n.º 20
0
euint8*
EFontFT2::RenderString(const char *string, eint32 *width, eint32 *height, bool *is_mono,
		       float size, float spacing, float shear, bool bold, eint32 length)
{
	if(string == NULL || *string == 0 || length == 0 || width == NULL || height == NULL || is_mono == NULL) return NULL;

	EAutolock <ELocker> autolock(&etk_ft2_font_locker);

	if(!IsAttached()) return NULL;

	bool isfixed = IsFixedSize(size);
	if(!fScalable && !isfixed) return NULL;

	float stringWidth;
	e_font_height fontHeight;

	if((stringWidth = StringWidth(string, size, spacing, shear, bold, length)) <= 0) return NULL;
	GetHeight(&fontHeight, size, shear, bold);

	eint32 w, h;
	w = (eint32)ceil(stringWidth) + 1;
	h = (eint32)ceil(fontHeight.ascent + fontHeight.descent) + 1;

	euint8 *bitmap = new euint8[w * h];
	if(!bitmap)
	{
		ETK_WARNING("[FONT]: %s --- Unable to alloc memory for bitmap data.", __PRETTY_FUNCTION__);
		return NULL;
	}
	bzero(bitmap, sizeof(euint8) * (size_t)(w * h));

	eunichar *unicode = e_utf8_convert_to_unicode(string, length);
	if(!unicode)
	{
		delete[] bitmap;
		return NULL;
	}

	const eunichar *ch;
	euint32 x = 0;
	euint32 y = (euint32)ceil(fontHeight.ascent);
	bool do_mono = fForceFontAliasing;
	for(ch = unicode; !(ch == NULL || *ch == 0); ch = e_unicode_next(ch, NULL))
	{
		if(FT_Load_Char(fFace, *ch, (do_mono ? (FT_LOAD_RENDER | FT_LOAD_MONOCHROME) : FT_LOAD_RENDER)))
		{
			ETK_DEBUG("[FONT]: %s --- FT_Load_Char failed.", __PRETTY_FUNCTION__);
			continue;
		}

		FT_Bitmap *ftbitmap = &(fFace->glyph->bitmap);

		eint32 xx = x + (eint32)(fFace->glyph->bitmap_left);
		eint32 yy = y - (eint32)(fFace->glyph->bitmap_top);
		eint32 bitmapWidth = (eint32)(ftbitmap->width);
		eint32 bitmapHeight = (eint32)(ftbitmap->rows);
		eint32 lineBytes = (eint32)(ftbitmap->pitch > 0 ? ftbitmap->pitch : -(ftbitmap->pitch));
		eint32 maxxx = min_c(w, xx + bitmapWidth);
		eint32 maxyy = min_c(h, yy + bitmapHeight);

		for(eint32 i = yy, p = 0; i < maxyy; i++, p++)
		{
			euint8* dest = bitmap;
			dest += i * w + xx;
			unsigned char* src = ftbitmap->buffer;
			src += p * lineBytes;

			switch(ftbitmap->pixel_mode)
			{
				case FT_PIXEL_MODE_GRAY:
					for(eint32 j = xx; j < maxxx; j++) *dest++ = (euint8)(*src++);
					break;

				case FT_PIXEL_MODE_MONO:
					for(eint32 j = xx; j < maxxx; )
					{
						euint8 val = (euint8)(*src++);
						eint32 left = maxxx - j >= 8 ? 8 : maxxx - j;
						euint8 left_offset = 7;

						for(eint32 k = 0; k < left; k++, left_offset--, j++)
							*dest++ = (val & (1 << left_offset)) ? 255 : 0;
					}
					break;

				default:
					ETK_DEBUG("[FONT]: %s --- The mode of freetype bitmap not supported.", __PRETTY_FUNCTION__);
			}
		}

		x += (euint32)((float)(fFace->glyph->metrics.horiAdvance) / 64.f) + (euint32)ceil((double)(spacing * size)); // next x
	}

	free(unicode);

	*width = w;
	*height = h;
	*is_mono = do_mono;

	return bitmap;
}
Ejemplo n.º 21
0
/**
 * Load glyphs corresponding to the UTF-32 codepoint code.
 */
static int load_glyph(AVFilterContext *ctx, Glyph **glyph_ptr, uint32_t code)
{
    DrawTextContext *s = ctx->priv;
    FT_BitmapGlyph bitmapglyph;
    Glyph *glyph;
    struct AVTreeNode *node = NULL;
    int ret;

    /* load glyph into s->face->glyph */
    if (FT_Load_Char(s->face, code, s->ft_load_flags))
        return AVERROR(EINVAL);

    glyph = av_mallocz(sizeof(*glyph));
    if (!glyph) {
        ret = AVERROR(ENOMEM);
        goto error;
    }
    glyph->code  = code;

    if (FT_Get_Glyph(s->face->glyph, &glyph->glyph)) {
        ret = AVERROR(EINVAL);
        goto error;
    }
    if (s->borderw) {
        glyph->border_glyph = glyph->glyph;
        if (FT_Glyph_StrokeBorder(&glyph->border_glyph, s->stroker, 0, 0) ||
            FT_Glyph_To_Bitmap(&glyph->border_glyph, FT_RENDER_MODE_NORMAL, 0, 1)) {
            ret = AVERROR_EXTERNAL;
            goto error;
        }
        bitmapglyph = (FT_BitmapGlyph) glyph->border_glyph;
        glyph->border_bitmap = bitmapglyph->bitmap;
    }
    if (FT_Glyph_To_Bitmap(&glyph->glyph, FT_RENDER_MODE_NORMAL, 0, 1)) {
        ret = AVERROR_EXTERNAL;
        goto error;
    }
    bitmapglyph = (FT_BitmapGlyph) glyph->glyph;

    glyph->bitmap      = bitmapglyph->bitmap;
    glyph->bitmap_left = bitmapglyph->left;
    glyph->bitmap_top  = bitmapglyph->top;
    glyph->advance     = s->face->glyph->advance.x >> 6;

    /* measure text height to calculate text_height (or the maximum text height) */
    FT_Glyph_Get_CBox(glyph->glyph, ft_glyph_bbox_pixels, &glyph->bbox);

    /* cache the newly created glyph */
    if (!(node = av_tree_node_alloc())) {
        ret = AVERROR(ENOMEM);
        goto error;
    }
    av_tree_insert(&s->glyphs, glyph, glyph_cmp, &node);

    if (glyph_ptr)
        *glyph_ptr = glyph;
    return 0;

error:
    if (glyph)
        av_freep(&glyph->glyph);

    av_freep(&glyph);
    av_freep(&node);
    return ret;
}
Ejemplo n.º 22
0
void Font::buildAtlas()
{
	if(FT_New_Face(sLibrary, mPath.c_str(), 0, &face))
	{
		LOG(LogError) << "Error creating font face! (path: " << mPath.c_str();
		return;
	}

	//FT_Set_Char_Size(face, 0, size * 64, getDpiX(), getDpiY());
	FT_Set_Pixel_Sizes(face, 0, mSize);

	//find the size we should use
	FT_GlyphSlot g = face->glyph;
	int w = 0;
	int h = 0;

	/*for(int i = 32; i < 128; i++)
	{
		if(FT_Load_Char(face, i, FT_LOAD_RENDER))
		{
			fprintf(stderr, "Loading character %c failed!\n", i);
			continue;
		}

		w += g->bitmap.width;
		h = std::max(h, g->bitmap.rows);
	}*/

	//the max size (GL_MAX_TEXTURE_SIZE) is like 3300
	w = 2048;
	h = 512;

	textureWidth = w;
	textureHeight = h;

	//create the texture
	glGenTextures(1, &textureID);
	glBindTexture(GL_TEXTURE_2D, textureID);

	glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
	glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);

	glPixelStorei(GL_PACK_ALIGNMENT, 1);
	glPixelStorei(GL_UNPACK_ALIGNMENT, 1);

	glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, w, h, 0, GL_ALPHA, GL_UNSIGNED_BYTE, NULL);

	//copy the glyphs into the texture
	int x = 0;
	int y = 0;
	int maxHeight = 0;
	for(int i = 32; i < 128; i++)
	{
		if(FT_Load_Char(face, i, FT_LOAD_RENDER))
			continue;

		 //prints rendered texture to the console
		/*std::cout << "uploading at x: " << x << ", w: " << g->bitmap.width << " h: " << g->bitmap.rows << "\n";

		for(int k = 0; k < g->bitmap.rows; k++)
		{
			for(int j = 0; j < g->bitmap.width; j++)
			{
				if(g->bitmap.buffer[g->bitmap.width * k + j])
					std::cout << ".";
				else
					std::cout << " ";
			}
			std::cout << "\n";
		}*/

		if(x + g->bitmap.width >= textureWidth)
		{
			x = 0;
			y += maxHeight + 1; //leave one pixel of space between glyphs
			maxHeight = 0;
		}

		if(g->bitmap.rows > maxHeight)
			maxHeight = g->bitmap.rows;

		glTexSubImage2D(GL_TEXTURE_2D, 0, x, y, g->bitmap.width, g->bitmap.rows, GL_ALPHA, GL_UNSIGNED_BYTE, g->bitmap.buffer);


		charData[i].texX = x;
		charData[i].texY = y;
		charData[i].texW = g->bitmap.width;
		charData[i].texH = g->bitmap.rows;
		charData[i].advX = g->metrics.horiAdvance / 64.0f;
		charData[i].advY = g->metrics.vertAdvance / 64.0f;
		charData[i].bearingY = g->metrics.horiBearingY / 64.0f;

		if(charData[i].texH > mMaxGlyphHeight)
			mMaxGlyphHeight = charData[i].texH;

		x += g->bitmap.width + 1; //leave one pixel of space between glyphs
	}

	glBindTexture(GL_TEXTURE_2D, 0);

	FT_Done_Face(face);

	if((y + maxHeight) >= textureHeight)
	{
		//failed to create a proper font texture
		LOG(LogWarning) << "Font with size " << mSize << " exceeded max texture size! Trying again...";
		//try a 3/4th smaller size and redo initialization
		fontScale *= 1.25f;
		mSize = (int)(mSize * (1.0f / fontScale));
		deinit();
		init();
	}
	else {
		LOG(LogInfo) << "Created font with size " << mSize << ".";
	}
}
Ejemplo n.º 23
0
osgText::Glyph* FreeTypeFont::getGlyph(const osgText::FontResolution& fontRes, unsigned int charcode)
{
    OpenThreads::ScopedLock<OpenThreads::Mutex> lock(FreeTypeLibrary::instance()->getMutex());

    setFontResolution(fontRes);

    //
    // GT: fix for symbol fonts (i.e. the Webdings font) as the wrong character are being  
    // returned, for symbol fonts in windows (FT_ENCONDING_MS_SYMBOL in freetype) the correct 
    // values are from 0xF000 to 0xF0FF not from 0x000 to 0x00FF (0 to 255) as you would expect.  
    // Microsoft uses a private field for its symbol fonts
    //
    unsigned int charindex = charcode;
    if (_face->charmap != NULL)
    {
        if (_face->charmap->encoding == FT_ENCODING_MS_SYMBOL)
        {
            charindex |= 0xF000;
        }
    }

    FT_Error error = FT_Load_Char( _face, charindex, FT_LOAD_RENDER|FT_LOAD_NO_BITMAP|_flags );
    if (error)
    {
        OSG_WARN << "FT_Load_Char(...) error 0x"<<std::hex<<error<<std::dec<<std::endl;
        return 0;
    }


    FT_GlyphSlot glyphslot = _face->glyph;

    int pitch = glyphslot->bitmap.pitch;
    unsigned char* buffer = glyphslot->bitmap.buffer;

    unsigned int sourceWidth = glyphslot->bitmap.width;;
    unsigned int sourceHeight = glyphslot->bitmap.rows;
    
    unsigned int width = sourceWidth;
    unsigned int height = sourceHeight;

    osg::ref_ptr<osgText::Glyph> glyph = new osgText::Glyph(_facade, charcode);
    
    unsigned int dataSize = width*height;
    unsigned char* data = new unsigned char[dataSize];
    

    // clear the image to zeros.
    for(unsigned char* p=data;p<data+dataSize;) { *p++ = 0; }

    glyph->setImage(width,height,1,
                    GL_ALPHA,
                    GL_ALPHA,GL_UNSIGNED_BYTE,
                    data,
                    osg::Image::USE_NEW_DELETE,
                    1);

    glyph->setInternalTextureFormat(GL_ALPHA);

    // copy image across to osgText::Glyph image.     
    switch(glyphslot->bitmap.pixel_mode)
    {
        case FT_PIXEL_MODE_MONO:
            for(int r=sourceHeight-1;r>=0;--r)
            {
                unsigned char* ptr = buffer+r*pitch;
                for(unsigned int c=0;c<sourceWidth;++c)
                {
                    (*data++)= (ptr[c >> 3] & (1 << (~c & 7))) ? 255 : 0;
                }
            }
            break;

        
        case FT_PIXEL_MODE_GRAY:
            for(int r=sourceHeight-1;r>=0;--r)
            {
                unsigned char* ptr = buffer+r*pitch;
                for(unsigned int c=0;c<sourceWidth;++c,++ptr)
                {
                    (*data++)=*ptr;
                }
            }
            break;
            
        default:
            OSG_WARN << "FT_Load_Char(...) returned bitmap with unknown pixel_mode " << glyphslot->bitmap.pixel_mode << std::endl;
    }


    FT_Glyph_Metrics* metrics = &(_face->glyph->metrics);

#if 0
    float coord_scale = _freetype_scale/64.0f;
#else
    float coord_scale = 1.0f/64.0f;
#endif

    glyph->setHorizontalBearing(osg::Vec2((float)metrics->horiBearingX * coord_scale,(float)(metrics->horiBearingY-metrics->height) * coord_scale)); // bottom left.
    glyph->setHorizontalAdvance((float)metrics->horiAdvance * coord_scale);
    glyph->setVerticalBearing(osg::Vec2((float)metrics->vertBearingX * coord_scale,(float)(metrics->vertBearingY-metrics->height) * coord_scale)); // top middle.
    glyph->setVerticalAdvance((float)metrics->vertAdvance * coord_scale);

//    cout << "      in getGlyph() implementation="<<this<<"  "<<_filename<<"  facade="<<_facade<<endl;

    return glyph.release();

}
Ejemplo n.º 24
0
/**
* Draws a single character of text
* Called by ::renderText - you probably want that function instead
*
* @param Uint32 character A 32-bit character code
**/
void OpenGLFont::renderCharacter(Uint32 character, float &x, float &y)
{
	FreetypeChar *c = &(this->pmpl->char_tex[character]);

	// If the OpenGL tex does not exist for this character, create it
	if (c->tex == 0) {
		FT_GlyphSlot slot = this->pmpl->face->glyph;

		int error = FT_Load_Char(this->pmpl->face, character, FT_LOAD_DEFAULT);
		if (error) return;

		error = FT_Render_Glyph(this->pmpl->face->glyph, FT_RENDER_MODE_NORMAL);
		if (error) return;

		unsigned int width = MAX(nextPowerOfTwo(slot->bitmap.width), 2);
		unsigned int height = MAX(nextPowerOfTwo(slot->bitmap.rows), 2);

		GLubyte* gl_data = new GLubyte[2 * width * height];

		for (unsigned int j = 0; j < height; j++) {
			for (unsigned int i = 0; i < width; i++) {
				int index = 2 * (i + j * width);
				if (i >= static_cast<unsigned int>(slot->bitmap.width)
				    ||
				    j >= static_cast<unsigned int>(slot->bitmap.rows)
				) {
					gl_data[index] = 0;
					gl_data[index + 1] = 0;
				} else {
					gl_data[index] = slot->bitmap.buffer[i + slot->bitmap.width * j];
					gl_data[index + 1] = slot->bitmap.buffer[i + slot->bitmap.width * j];
				}
			}
		}

		// Create a texture
		glGenTextures(1, &c->tex);
		glBindTexture(GL_TEXTURE_2D, c->tex);
		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
		#ifdef OpenGL
			glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
			glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
		#endif
		glTexImage2D(GL_TEXTURE_2D, 0, GL_RG, width, height, 0, GL_RG, GL_UNSIGNED_BYTE, gl_data);

		delete [] gl_data;

		c->w = slot->bitmap.width;
		c->h = slot->bitmap.rows;
		c->x = slot->bitmap_left;
		c->y = slot->bitmap_top;
		c->advance = slot->advance.x;
		c->tx = (float)slot->bitmap.width / (float)width;
		c->ty = (float)slot->bitmap.rows / (float)height;

	} else {
		glBindTexture(GL_TEXTURE_2D, c->tex);
	}

	GLfloat box[4][4] = {
		{x + c->x,         y + -c->y + c->h,  0.f,    c->ty},
		{x + c->x + c->w,  y + -c->y + c->h,  c->tx,  c->ty},
		{x + c->x,         y + -c->y,         0.f,    0.f},
		{x + c->x + c->w,  y + -c->y,         c->tx,  0.f},
	};

	glBindBuffer(GL_ARRAY_BUFFER, this->pmpl->font_vbo);
	glBufferData(GL_ARRAY_BUFFER, sizeof box, box, GL_DYNAMIC_DRAW);

	glVertexAttribPointer(ATTRIB_TEXTCOORD, 4, GL_FLOAT, GL_FALSE, 0, 0);
	glEnableVertexAttribArray(ATTRIB_TEXTCOORD);

	glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);

	x += (float)(c->advance >> 6);
}
Ejemplo n.º 25
0
/**
* Creates a bitmap representation of the glyph for character 'character'
* in this face
*/
int
STFont::GenerateBitmap(unsigned int character)
{
    
    FT_Load_Char(mImpl->ftFace, character, FT_LOAD_RENDER );

    FT_GlyphSlot glyph = mImpl->ftFace->glyph;
    FT_Bitmap bitmap = glyph->bitmap;

    if (bitmap.width == 0 || bitmap.rows == 0) {
        // failure: the character might not exist in this face, so attempt to
        // use the glyph for character 0, which is usually rendered as the "missing
        // character" glyph
        if (FT_Load_Char(mImpl->ftFace, 0, FT_LOAD_RENDER | FT_LOAD_MONOCHROME )) {
            fprintf(stderr, "Could not load bitmap glyph for char '%c' (value=%d)\n", character, (int)character);
        }

        return -1;
    }
    

    int bitmapIndex = (int)mImpl->glyphBitmaps .size();
    mImpl->charMap[character] = bitmapIndex;
    mImpl->glyphBitmaps .resize(mImpl->glyphBitmaps .size()+1);

    STBitmapGlyph& bitmapGlyph = mImpl->glyphBitmaps [bitmapIndex];

    unsigned int srcWidth = bitmap.width;
    unsigned int srcHeight = bitmap.rows;
    unsigned int srcPitch = bitmap.pitch;

    // Set all the fields in our structure to represent the glyph

    bitmapGlyph.width = srcWidth;
    bitmapGlyph.height = srcHeight;
    bitmapGlyph.pitch = srcPitch;
    bitmapGlyph.offsetX = glyph->bitmap_left;
    bitmapGlyph.offsetY = glyph->bitmap_top - glyph->bitmap.rows;
    bitmapGlyph.advanceX = (float)glyph->advance.x / 64.0f;

    bitmapGlyph.data = new unsigned char[bitmapGlyph.width * bitmapGlyph.height * 2];

    // Like most image formats a rendered bitmap representation of the face's
    // character is going to begin with the top row of the bitmap.  OpenGL 
    // bitmaps begin with the bottom row, so we need to reshuffle the data here

    unsigned char* dest = bitmapGlyph.data + (( bitmapGlyph.height - 1) * bitmapGlyph.width * 2);
    unsigned char* src = bitmap.buffer;
    size_t destStep = bitmapGlyph.width * 2 * 2;

    for( unsigned int y = 0; y < srcHeight; ++y)
    {
        for( unsigned int x = 0; x < srcWidth; ++x)
        {
            *dest++ = static_cast<unsigned char>(255);
            *dest++ = *src++;
        }
        dest -= destStep;
    }

    return bitmapIndex;
}
Ejemplo n.º 26
0
static const struct font_glyph *font_renderer_ft_get_glyph(
      void *data, uint32_t charcode)
{
   unsigned map_id;
   uint8_t *dst;
   FT_GlyphSlot slot;
   freetype_atlas_slot_t* atlas_slot;
   ft_font_renderer_t *handle = (ft_font_renderer_t*)data;

   if (!handle)
      return NULL;

   map_id     = charcode & 0xFF;
   atlas_slot = handle->uc_map[map_id];

   while(atlas_slot)
   {
      if(atlas_slot->charcode == charcode)
      {
         atlas_slot->last_used = handle->usage_counter++;
         return &atlas_slot->glyph;
      }
      atlas_slot = atlas_slot->next;
   }

   if (FT_Load_Char(handle->face, charcode, FT_LOAD_RENDER))
      return NULL;

   FT_Render_Glyph(handle->face->glyph, FT_RENDER_MODE_NORMAL);
   slot = handle->face->glyph;

   atlas_slot             = font_renderer_get_slot(handle);
   atlas_slot->charcode   = charcode;
   atlas_slot->next       = handle->uc_map[map_id];
   handle->uc_map[map_id] = atlas_slot;

   /* Some glyphs can be blank. */
   atlas_slot->glyph.width         = slot->bitmap.width;
   atlas_slot->glyph.height        = slot->bitmap.rows;
   atlas_slot->glyph.advance_x     = slot->advance.x >> 6;
   atlas_slot->glyph.advance_y     = slot->advance.y >> 6;
   atlas_slot->glyph.draw_offset_x = slot->bitmap_left;
   atlas_slot->glyph.draw_offset_y = -slot->bitmap_top;

   dst = (uint8_t*)handle->atlas.buffer + atlas_slot->glyph.atlas_offset_x
         + atlas_slot->glyph.atlas_offset_y * handle->atlas.width;

   if (slot->bitmap.buffer)
   {
      unsigned r, c;
      const uint8_t *src = (const uint8_t*)slot->bitmap.buffer;

      for (r = 0; r < atlas_slot->glyph.height;
            r++, dst += handle->atlas.width, src += slot->bitmap.pitch)
         for (c = 0; c < atlas_slot->glyph.width; c++)
            dst[c] = src[c];
   }

   handle->atlas.dirty = true;
   atlas_slot->last_used = handle->usage_counter++;
   return &atlas_slot->glyph;
}
void TextRenderer::initRenderData()
{
	// FreeType
	FT_Library ft;

	// All functions return a value different than 0 whenever an error occurred
	if (FT_Init_FreeType(&ft))
		std::cout << "ERROR::FREETYPE: Could not init FreeType Library" << std::endl;

	// Load font as face
	FT_Face face;
	if (FT_New_Face(ft, Constants::fontFilePath.c_str(), 0, &face))
		std::cout << "ERROR::FREETYPE: Failed to load font" << std::endl;

	// Set size to load glyphs as
	FT_Set_Pixel_Sizes(face, 0, 48);

	// Disable byte-alignment restriction
	glPixelStorei(GL_UNPACK_ALIGNMENT, 1);

	// Load first 128 characters of ASCII set
	for (GLubyte c = 0; c < 128; c++)
	{
		// Load character glyph 
		if (FT_Load_Char(face, c, FT_LOAD_RENDER))
		{
			std::cout << "ERROR::FREETYTPE: Failed to load Glyph" << std::endl;
			continue;
		}
		// Generate texture
		GLuint texture;
		glGenTextures(1, &texture);
		glBindTexture(GL_TEXTURE_2D, texture);
		glTexImage2D(
			GL_TEXTURE_2D,
			0,
			GL_RED,
			face->glyph->bitmap.width,
			face->glyph->bitmap.rows,
			0,
			GL_RED,
			GL_UNSIGNED_BYTE,
			face->glyph->bitmap.buffer
			);
		// Set texture options
		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
		// Now store character for later use
		Character character = {
			texture,
			glm::ivec2(face->glyph->bitmap.width, face->glyph->bitmap.rows),
			glm::ivec2(face->glyph->bitmap_left, face->glyph->bitmap_top),
			face->glyph->advance.x
		};
		Characters.insert(std::pair<GLchar, Character>(c, character));
	}
	glBindTexture(GL_TEXTURE_2D, 0);
	// Destroy FreeType once we're finished
	FT_Done_Face(face);
	FT_Done_FreeType(ft);


	// Configure VAO/VBO for texture quads
	glGenVertexArrays(1, &VAO);
	glGenBuffers(1, &VBO);
	glBindVertexArray(VAO);
	glBindBuffer(GL_ARRAY_BUFFER, VBO);
	glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat) * 6 * 4, NULL, GL_DYNAMIC_DRAW);
	glEnableVertexAttribArray(0);
	glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, 4 * sizeof(GLfloat), 0);
	glBindBuffer(GL_ARRAY_BUFFER, 0);
	glBindVertexArray(0);
}
Ejemplo n.º 28
0
int
main( int     argc,
      char**  argv )
{
  FT_Library    library;
  FT_Face       face;

  FT_GlyphSlot  slot;
  FT_Matrix     matrix;                 /* transformation matrix */
  FT_Vector     pen;                    /* untransformed origin  */
  FT_Error      error;

  char*         filename;
//  char*         text;

  double        angle;
  int           target_height;
  int           n, num_chars;

  wchar_t *chinese_str = L"ол╣Щ1g";
  unsigned int *p = (unsigned int *)chinese_str;
  int i;

  printf("Uniocde: \n");
  for (i = 0; i < wcslen(chinese_str); i++)
  {
  	printf("0x%x ", p[i]);
  }
  printf("\n");
//  return 0;


  if ( argc != 2 )
  {
    fprintf ( stderr, "usage: %s font\n", argv[0] );
    exit( 1 );
  }

  filename      = argv[1];                           /* first argument     */
//  text          = argv[2];                           /* second argument    */
  num_chars     = wcslen(chinese_str);
  angle         = ( 0.0 / 360 ) * 3.14159 * 2;      /* use 0 degrees     */
  target_height = HEIGHT;

  error = FT_Init_FreeType( &library );              /* initialize library */
  /* error handling omitted */

  error = FT_New_Face( library, argv[1], 0, &face ); /* create face object */
  /* error handling omitted */

  /* use 20pt at 100dpi */
  error = FT_Set_Char_Size( face, 20 * 64, 0,
                            100, 0 );                /* set character size */
  /* error handling omitted */

  slot = face->glyph;

  /* set up matrix */
  matrix.xx = (FT_Fixed)( cos( angle ) * 0x10000L );
  matrix.xy = (FT_Fixed)(-sin( angle ) * 0x10000L );
  matrix.yx = (FT_Fixed)( sin( angle ) * 0x10000L );
  matrix.yy = (FT_Fixed)( cos( angle ) * 0x10000L );

  /* the pen position in 26.6 cartesian space coordinates; */
  /* start at (0,40) relative to the upper left corner  */
  pen.x = 0 * 64;
  pen.y = ( target_height - 40 ) * 64;

  for ( n = 0; n < num_chars; n++ )
  {
    /* set transformation */
    FT_Set_Transform( face, &matrix, &pen );

    /* load glyph image into the slot (erase previous one) */
    error = FT_Load_Char( face, chinese_str[n], FT_LOAD_RENDER );
    if ( error )
      continue;                 /* ignore errors */

    /* now, draw to our target surface (convert position) */
    draw_bitmap( &slot->bitmap,
                 slot->bitmap_left,
                 target_height - slot->bitmap_top );

    /* increment pen position */
    pen.x += slot->advance.x;
    pen.y += slot->advance.y;
  }

  show_image();

  FT_Done_Face    ( face );
  FT_Done_FreeType( library );

  return 0;
}
Ejemplo n.º 29
0
// Create font atlas texture
void create_font_atlas(font_t *state)
{
    glUseProgram(state->program);
    glActiveTexture(GL_TEXTURE0);
    glGenTextures(1, &state->tex_uniform);
    glBindTexture(GL_TEXTURE_2D, state->tex_uniform);
    glUniform1i(state->tex_uniform, 0);

    // Set texture parameters
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);

    // Set single byte alignment
    glPixelStorei(GL_UNPACK_ALIGNMENT, 1);

    // Get atlas dimensions
    FT_GlyphSlot g = state->face->glyph;
    int w = 0; // full texture width
    int h = 0; // full texture height
    int row_w = 0; // current row width
    int row_h = 0; // current row height

    int i;
    for(i=32; i<128; i++) {
        if(FT_Load_Char(state->face, i, FT_LOAD_RENDER)) {
            printf("Loading Character %d failed\n", i);
            exit(EXIT_FAILURE);
        }

        // If the width will be over max texture width
        // Go to next row
        if(row_w + g->bitmap.width+1 >= MAX_WIDTH) {
            w = max(w, row_w);
            h += row_h;
            row_w = 0;
            row_h = 0;
        }
        row_w += g->bitmap.width + 1;
        row_h = max(row_h, g->bitmap.rows);
    }
    
    // final texture dimensions
    w = max(row_w, w);
    h += row_h;

    state->atlas_width = w;
    state->atlas_height = h;

    // Allocate texture
    #ifdef RASPI
    glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, w, h, 0, GL_ALPHA, GL_UNSIGNED_BYTE, 0);
    #else
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RED, w, h, 0, GL_RED, GL_UNSIGNED_BYTE, 0);
    #endif

    // Fill texture with glyph bitmaps and cache placements
    char_info_t *char_info = state->char_info;
    int offset_x = 0;
    int offset_y = 0;
    row_h = 0;

    for(i=32; i<128; i++) {
	    if(FT_Load_Char(state->face, i, FT_LOAD_RENDER)) {
		    printf("Loading Character %d failed\n", i);
		    exit(EXIT_FAILURE);
	    }

	    // Set correct row
	    if(offset_x + g->bitmap.width + 1 >= MAX_WIDTH) {
		    offset_y += row_h;
		    row_h = 0;
		    offset_x = 0;
	    }

	    // fill texture with glyph
            #ifdef RASPI
	    glTexSubImage2D(GL_TEXTURE_2D, 0, offset_x, offset_y, g->bitmap.width, g->bitmap.rows, GL_ALPHA, GL_UNSIGNED_BYTE, g->bitmap.buffer);
            #else
	    glTexSubImage2D(GL_TEXTURE_2D, 0, offset_x, offset_y, g->bitmap.width, g->bitmap.rows, GL_RED, GL_UNSIGNED_BYTE, g->bitmap.buffer);	
            #endif

	    // Cache values
	    char_info[i].ax = g->advance.x >> 6;
	    char_info[i].ay = g->advance.y >> 6;
	    char_info[i].bw = g->bitmap.width;
	    char_info[i].bh = g->bitmap.rows;
	    char_info[i].bl = g->bitmap_left;
	    char_info[i].bt = g->bitmap_top;
	    char_info[i].tx = offset_x/(float)w;
	    char_info[i].ty = offset_y/(float)h;

	    // Update current position
	    row_h = max(row_h, g->bitmap.rows);
	    offset_x += g->bitmap.width + 1;
    }
} 
Ejemplo n.º 30
0
	 Atlas(FT_Face face, int height) {
		FT_Set_Pixel_Sizes(face, 0, height);
		FT_GlyphSlot g = face->glyph;

		int roww = 0;
		int rowh = 0;
		 w = 0;
		 h = 0;

		 memset(c, 0, sizeof c);

		/* Find minimum size for a texture holding all visible ASCII characters */
		for (int i = 32; i < 128; i++) {
			if (FT_Load_Char(face, i, FT_LOAD_RENDER)) {
				fprintf(stderr, "Loading character %c failed!\n", i);
				continue;
			}
			if (roww + g->bitmap.width + 1 >= MAXWIDTH) {
				w = std::max(w, roww);
				h += rowh;
				roww = 0;
				rowh = 0;
			}
			roww += g->bitmap.width + 1;
			rowh = std::max(rowh, (int)g->bitmap.rows);
		}

		w = std::max(w, roww);
		h += rowh;

		/* Create a texture that will be used to hold all ASCII glyphs */
		glActiveTexture(GL_TEXTURE0);
		glGenTextures(1, &tex);
		glBindTexture(GL_TEXTURE_2D, tex);

		glTexImage2D(GL_TEXTURE_2D, 0, monohromeInternalformat, w, h, 0, monohromeformat, GL_UNSIGNED_BYTE, 0);

		/* We require 1 byte alignment when uploading texture data */
		glPixelStorei(GL_UNPACK_ALIGNMENT, 1);

		/* Clamping to edges is important to prevent artifacts when scaling */
		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);

		/* Linear filtering usually looks best for text */
		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);

		/* Paste all glyph bitmaps into the texture, remembering the offset */
		int ox = 0;
		int oy = 0;

		rowh = 0;

		for (int i = 32; i < 128; i++) {
			if (FT_Load_Char(face, i, FT_LOAD_RENDER)) {
				fprintf(stderr, "Loading character %c failed!\n", i);
				continue;
			}

			if (ox + g->bitmap.width + 1 >= MAXWIDTH) {
				oy += rowh;
				rowh = 0;
				ox = 0;
			}

			glTexSubImage2D(GL_TEXTURE_2D, 0, ox, oy, g->bitmap.width, g->bitmap.rows, monohromeformat, GL_UNSIGNED_BYTE, g->bitmap.buffer);
			c[i].ax = _FIXED2FLOAT(g->advance.x, 6);
			c[i].ay = _FIXED2FLOAT(g->advance.y, 6);

			c[i].bw = (float)g->bitmap.width;
			c[i].bh = (float)g->bitmap.rows;

			c[i].bl = (float)g->bitmap_left;
			c[i].bt = (float)g->bitmap_top;

			c[i].tx = ox / (float)w;
			c[i].ty = oy / (float)h;

			rowh = std::max(rowh, (int)g->bitmap.rows);
			ox += g->bitmap.width + 1;
		}

		fprintf(stderr, "Generated a %d x %d (%d kb) texture atlas\n", w, h, w * h / 1024);
	}