Beispiel #1
0
void load_fonts(void)
{
   stbtt_pack_context pc;
   int i;
   FILE *f;
   char filename[256];
   char *win = getenv("windir");
   if (win == NULL) win = getenv("SystemRoot");

   f = fopen(stb_wingraph_commandline, "rb");
   if (!f) {
      if (win == NULL)
         sprintf(filename, "arial.ttf", win);
      else
         sprintf(filename, "%s/fonts/arial.ttf", win);
      f = fopen(filename, "rb");
      if (!f) exit(0);
   }

   fread(ttf_buffer, 1, 1<<25, f);

   stbtt_PackBegin(&pc, temp_bitmap[0], BITMAP_W, BITMAP_H, 0, 1, NULL);
   for (i=0; i < 2; ++i) {
      stbtt_PackSetOversampling(&pc, 1, 1);
      stbtt_PackFontRange(&pc, ttf_buffer, 0, scale[i], 32, 95, chardata[i*3+0]+32);
      stbtt_PackSetOversampling(&pc, 2, 2);
      stbtt_PackFontRange(&pc, ttf_buffer, 0, scale[i], 32, 95, chardata[i*3+1]+32);
      stbtt_PackSetOversampling(&pc, 3, 1);
      stbtt_PackFontRange(&pc, ttf_buffer, 0, scale[i], 32, 95, chardata[i*3+2]+32);
   }
   stbtt_PackEnd(&pc);

   glGenTextures(1, &font_tex);
   glBindTexture(GL_TEXTURE_2D, font_tex);
   glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, BITMAP_W, BITMAP_H, 0, GL_ALPHA, GL_UNSIGNED_BYTE, temp_bitmap);
   glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
   glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
}
Beispiel #2
0
		void addGlyphsToTexture(const std::vector<char32_t>& codepoints) override
		{
			if(codepoints.empty()) {
				LOG_WARN("stb_impl::addGlyphsToTexture: no codepoints.");
				return;
			}
			int old_size = packed_char_.size();
			auto ttf_buffer = reinterpret_cast<const unsigned char*>(font_data_.c_str());
			if(font_size_ < 20.0f) {
				stbtt_PackSetOversampling(&pc_, 2, 2);
			}
			
			std::vector<stbtt_pack_range> ranges;
			char32_t last_cp = codepoints.front();
			char32_t first_cp = codepoints.front();
			int num_chars = 1;
			for(auto it = codepoints.begin() + 1; it != codepoints.end(); ++it) {
				char32_t cp = *it;
				if(cp == last_cp+1) {
					++num_chars;
				} else {
					auto& packed_data = packed_char_[UnicodeRange(first_cp, first_cp+num_chars-1)];
					packed_data.resize(num_chars);

					stbtt_pack_range range;
					range.num_chars_in_range          = num_chars;
					range.chardata_for_range          = packed_data.data();
					range.font_size                   = font_size_;
					range.first_unicode_char_in_range = first_cp;
					ranges.emplace_back(range);

					num_chars = 1;
					first_cp = cp;					
				}
				last_cp = cp;
			}
			auto& packed_data = packed_char_[UnicodeRange(first_cp, first_cp+num_chars-1)];
			packed_data.resize(num_chars);

			stbtt_pack_range range;
			range.num_chars_in_range          = num_chars;
			range.chardata_for_range          = packed_data.data();
			range.font_size                   = font_size_;
			range.first_unicode_char_in_range = first_cp;
			ranges.emplace_back(range);

			stbtt_PackFontRanges(&pc_, ttf_buffer, 0, ranges.data(), ranges.size());

			font_texture_->update2D(0, 0, 0, surface_width, surface_height, surface_width, pixels_.data());
		}
Beispiel #3
0
int main(int argc, char **argv)
{
   stbtt_fontinfo font;
   unsigned char *bitmap;
   int w,h,i,j,c = (argc > 1 ? atoi(argv[1]) : 34807), s = (argc > 2 ? atoi(argv[2]) : 32);

   //debug();

   // @TODO: why is minglui.ttc failing? 
   fread(ttf_buffer, 1, 1<<25, fopen(argc > 3 ? argv[3] : "c:/windows/fonts/mingliu.ttc", "rb"));

   //fread(ttf_buffer, 1, 1<<25, fopen(argc > 3 ? argv[3] : "c:/x/DroidSansMono.ttf", "rb"));
   {
      static stbtt_pack_context pc;
      static stbtt_packedchar cd[256];
      static unsigned char atlas[1024*1024];

      stbtt_PackBegin(&pc, atlas, 1024,1024,1024,1,NULL);
      stbtt_PackFontRange(&pc, ttf_buffer, 0, 32.0, 0, 256, cd);
      stbtt_PackEnd(&pc);
   }

#if 0
   stbtt_BakeFontBitmap(ttf_buffer,stbtt_GetFontOffsetForIndex(ttf_buffer,0), 40.0, temp_bitmap[0],BITMAP_W,BITMAP_H, 32,96, cdata); // no guarantee this fits!
   stbi_write_png("fonttest1.png", BITMAP_W, BITMAP_H, 1, temp_bitmap, 0);

   {
      stbtt_pack_context pc;
      stbtt_PackBegin(&pc, temp_bitmap[0], BITMAP_W, BITMAP_H, 0, 1, NULL);
      stbtt_PackFontRange(&pc, ttf_buffer, 0, 20.0, 32, 95, pdata);
      stbtt_PackFontRange(&pc, ttf_buffer, 0, 20.0, 0xa0, 0x100-0xa0, pdata);
      stbtt_PackEnd(&pc);
      stbi_write_png("fonttest2.png", BITMAP_W, BITMAP_H, 1, temp_bitmap, 0);
   }

   {
      stbtt_pack_context pc;
      stbtt_pack_range pr[2];
      stbtt_PackBegin(&pc, temp_bitmap[0], BITMAP_W, BITMAP_H, 0, 1, NULL);

      pr[0].chardata_for_range = pdata;
      pr[0].first_unicode_char_in_range = 32;
      pr[0].num_chars_in_range = 95;
      pr[0].font_size = 20.0f;
      pr[1].chardata_for_range = pdata+256;
      pr[1].first_unicode_char_in_range = 0xa0;
      pr[1].num_chars_in_range = 0x100 - 0xa0;
      pr[1].font_size = 20.0f;

      stbtt_PackSetOversampling(&pc, 2, 2);
      stbtt_PackFontRanges(&pc, ttf_buffer, 0, pr, 2);
      stbtt_PackEnd(&pc);
      stbi_write_png("fonttest3.png", BITMAP_W, BITMAP_H, 1, temp_bitmap, 0);
   }
   return 0;
#endif

   stbtt_InitFont(&font, ttf_buffer, stbtt_GetFontOffsetForIndex(ttf_buffer,0));
   bitmap = stbtt_GetCodepointBitmap(&font, 0,stbtt_ScaleForPixelHeight(&font, (float)s), c, &w, &h, 0,0);

   for (j=0; j < h; ++j) {
      for (i=0; i < w; ++i)
         putchar(" .:ioVM@"[bitmap[j*w+i]>>5]);
      putchar('\n');
   }
   return 0;
}
FontRenderer::FontRenderer(const string& fontPath, uint32_t texWidth, uint32_t texHeight,
	                       float fontSize, size_t numCharsPerBatch, TextureFiltering filtering) noexcept
:
	mFontSize{fontSize},
	mPackedChars{new (std::nothrow) stbtt_packedchar[CHAR_COUNT]},
	mSpriteBatch{numCharsPerBatch, FONT_RENDERER_FRAGMENT_SHADER_SRC}
{
	// This should be const, but MSVC12 doesn't support ini lists in constructor's ini list
	mPixelToUV = vec2{1.0f/static_cast<float>(texWidth), 1.0f/static_cast<float>(texHeight)};

	uint8_t* tempBitmap = new uint8_t[texWidth*texHeight];

	stbtt_pack_context packContext;
	if(stbtt_PackBegin(&packContext, tempBitmap, texWidth, texHeight, 0, 1, NULL) == 0) {
		std::cerr << "FontRenderer: Couldn't stbtt_PackBegin()" << std::endl;
		std::terminate();
	}

	stbtt_PackSetOversampling(&packContext, 2, 2);

	std::vector<uint8_t> ttfBuffer = sfz::readBinaryFile(fontPath.c_str());
	if (ttfBuffer.size() == 0) {
		std::cerr << "Couldn't open TTF file at: " << fontPath << std::endl;
		std::terminate();
	}

	if (stbtt_PackFontRange(&packContext, ttfBuffer.data(), 0, mFontSize, FIRST_CHAR, CHAR_COUNT,
	                    reinterpret_cast<stbtt_packedchar*>(mPackedChars)) == 0) {
		std::cerr << "FontRenderer: Couldn't pack font, texture likely too small." << std::endl;
		std::terminate();
	}

	stbtt_PackEnd(&packContext);

	glGenTextures(1, &mFontTexture);
	glBindTexture(GL_TEXTURE_2D, mFontTexture);
	glTexImage2D(GL_TEXTURE_2D, 0, GL_R8, texWidth, texHeight, 0, GL_RED, GL_UNSIGNED_BYTE,
	             tempBitmap);

	// Sets specified texture filtering, generating mipmaps if needed.
	switch (filtering) {
	case TextureFiltering::NEAREST:
		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
		break;
	case TextureFiltering::BILINEAR:
		glGenerateMipmap(GL_TEXTURE_2D);
		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
		break;
	case TextureFiltering::TRILINEAR:
		glGenerateMipmap(GL_TEXTURE_2D);
		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
		break;
	case TextureFiltering::ANISOTROPIC_1:
	case TextureFiltering::ANISOTROPIC_2:
	case TextureFiltering::ANISOTROPIC_4:
	case TextureFiltering::ANISOTROPIC_8:
	case TextureFiltering::ANISOTROPIC_16:
		glGenerateMipmap(GL_TEXTURE_2D);
		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
		glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, anisotropicFactor(filtering));
		break;
	}

	delete[] tempBitmap;
}