예제 #1
0
 int pack_begin(int width, int height, int stride_in_bytes, int padding) {
     
     pack_pixels = new unsigned char[width * height];
     spc = new stbtt_pack_context();
     
     int r = stbtt_PackBegin(spc, pack_pixels, width, height, stride_in_bytes, padding, NULL);
     
     return r;
 }
예제 #2
0
파일: stb.c 프로젝트: rglass01/RetroArch
static bool font_renderer_stb_create_atlas(stb_font_renderer_t *self,
      uint8_t *font_data, float font_size)
{
   int i;
   stbtt_pack_context pc = {NULL};
   stbtt_packedchar   chardata[256];

   self->atlas.width  = self->atlas.height = 512;

alloc_atlas:
   self->atlas.buffer = (uint8_t*)calloc(self->atlas.height, self->atlas.width);

   if (!self->atlas.buffer)
      return false;

   stbtt_PackBegin(&pc, self->atlas.buffer,
         self->atlas.width, self->atlas.height,
         self->atlas.width, 1, NULL);

   stbtt_PackFontRange(&pc, font_data, 0, font_size, 0, 256, chardata);
   stbtt_PackEnd(&pc);

   for (i = 0; i < 256; ++i)
   {
      struct font_glyph *g = &self->glyphs[i];
      stbtt_packedchar  *c = &chardata[i];

      g->advance_x = c->xadvance;
      g->atlas_offset_x = c->x0;
      g->atlas_offset_y = c->y0;
      g->draw_offset_x  = c->xoff;
      g->draw_offset_y  = c->yoff;
      g->width          = c->x1 - c->x0;
      g->height         = c->y1 - c->y0;

      /* make sure important characters fit */
      if (isprint(i) && !isspace(i) && (!g->width || !g->height))
      {
         /* increase atlas by 20% in all directions */
         self->atlas.width  *= 1.2;
         self->atlas.height *= 1.2;

         free(self->atlas.buffer);
         goto alloc_atlas;
         break;
      }
   }

   return true;
}
예제 #3
0
파일: main.c 프로젝트: Afinostux/stb
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);
}
예제 #4
0
FontAtlas::FontAtlas(int bitmapSize, FontRangeMap &map, unsigned char *fontData)
   : bitmapSize(bitmapSize), fontRangeMap(std::move(map)) {
   ASSERT(bitmapSize > 0, "Invalid bitmap size");

   UPtr<unsigned char[]> bitmap(new unsigned char[bitmapSize * bitmapSize]);
   stbtt_pack_context packContext;

   int res = stbtt_PackBegin(&packContext, bitmap.get(), bitmapSize, bitmapSize, 0, 1, nullptr);
   ASSERT(res, "stbtt_PackBegin failed");

   std::vector<stbtt_pack_range> packRanges;
   for (std::pair<const FontType, FontRange> &item : fontRangeMap) {
      FontRange &fontRange = item.second;
      stbtt_pack_range packRange;
      fontRange.charData.resize(fontRange.numGlyphs);

      packRange.font_size = fontRange.fontSize;
      packRange.first_unicode_char_in_range = fontRange.firstGlyph;
      packRange.num_chars_in_range = fontRange.numGlyphs;
      packRange.chardata_for_range = fontRange.charData.data();

      packRanges.push_back(packRange);
   }

   res = stbtt_PackFontRanges(&packContext, fontData, 0, packRanges.data(), packRanges.size());
   ASSERT(res, "stbtt_PackFontRanges failed");

   stbtt_PackEnd(&packContext);

   texture = std::make_shared<Texture>(GL_TEXTURE_2D);
   texture->bind();

   glTexImage2D(GL_TEXTURE_2D, 0, GL_RED, bitmapSize, bitmapSize, 0, GL_RED, GL_UNSIGNED_BYTE, bitmap.get());
   glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);

   texture->unbind();
}
예제 #5
0
파일: test_truetype.c 프로젝트: BSVino/stb
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;
}
예제 #6
0
	bool Font::load(std::string path, AssetManager& manager)
	{
		mName = getFileNameFromPath(path);
		mPath = getPathFromFilePath(path);

		FILE* file = fopen(path.c_str(), "rb");
		size_t fSize = 0;
		U8* buffer = nullptr;
		
		if (!file)
			return false;

		fseek(file, 0, SEEK_END);
		fSize = ftell(file);
		rewind(file);

		buffer = new U8[fSize];
		
		const U32 TATLAS_SIZE = 512;
		size_t result = fread(buffer, sizeof(U8), fSize, file);
		if (result != fSize)
			return false;

		stbtt_fontinfo fontInfo;
		stbtt_InitFont(&fontInfo, buffer, stbtt_GetFontOffsetForIndex(buffer, 0));
		
		U8* img = new U8[TATLAS_SIZE * TATLAS_SIZE];
		U8* rgbaImg = new U8[TATLAS_SIZE * TATLAS_SIZE * 4];
		
		stbtt_pack_context pack;
		stbtt_packedchar pcdata[96];
		stbtt_packedchar tabData;

		int packSuccess = stbtt_PackBegin(&pack, img, TATLAS_SIZE, TATLAS_SIZE, 0, 1, NULL);
		int rangeSuc = stbtt_PackFontRange(&pack, buffer, 0, mSize, 32, 95, pcdata);
		int tabSuc = stbtt_PackFontRange(&pack, buffer, 0, mSize, '\t', 1, &tabData);

		stbtt_PackEnd(&pack);
		I32 largestY = 0;
		I32 tabSize = 0;
		
		mTabWidth = tabData.xadvance;
		
		for (int i = 0; i < 96; ++i)
		{
			mGlyphs[i].x0 = pcdata[i].x0;
			mGlyphs[i].y0 = pcdata[i].y0;
			mGlyphs[i].x1 = pcdata[i].x1;
			mGlyphs[i].y1 = pcdata[i].y1;
			mGlyphs[i].xoff = pcdata[i].xoff;
			mGlyphs[i].yoff = pcdata[i].yoff;
			mGlyphs[i].xoff2 = pcdata[i].xoff2;
			mGlyphs[i].yoff2 = pcdata[i].yoff2;
			mGlyphs[i].xadvance = pcdata[i].xadvance;
			vec2 tl = GET_UV(mGlyphs[i].x0, TATLAS_SIZE, mGlyphs[i].y0, TATLAS_SIZE);
			vec2 br = GET_UV(mGlyphs[i].x1, TATLAS_SIZE, mGlyphs[i].y1, TATLAS_SIZE);
			mGlyphs[i].u0 = tl.x();
			mGlyphs[i].v0 = tl.y();
			mGlyphs[i].u1 = br.x();
			mGlyphs[i].v1 = br.y();
			mGlyphs[i].w = mGlyphs[i].x1 - mGlyphs[i].x0;
			mGlyphs[i].h = abs(mGlyphs[i].y1 - mGlyphs[i].y0);

			if (mGlyphs[i].y1 - mGlyphs[i].y0 > largestY)
				largestY = (mGlyphs[i].y1 - mGlyphs[i].y0);
		}

		mMaxGlyphHeight = largestY;

		for (int i = 0; i < TATLAS_SIZE * TATLAS_SIZE; ++i)
		{
			rgbaImg[(i * 4) + 0] = 255; //r
			rgbaImg[(i * 4) + 1] = 255; //g
			rgbaImg[(i * 4) + 2] = 255; //b
			rgbaImg[(i * 4) + 3] = img[i]; //a
		}

		glGenTextures(1, &glTex);
		glActiveTexture(GL_TEXTURE0);
		glBindTexture(GL_TEXTURE_2D, glTex);
		glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, TATLAS_SIZE, TATLAS_SIZE, 0, GL_RGBA, GL_UNSIGNED_BYTE, rgbaImg);
		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);

		glBindTexture(GL_TEXTURE_2D, 0);
		
		fclose(file);
		delete[] buffer;
		delete[] img;
		delete[] rgbaImg;
		return true;
	}
예제 #7
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;
}
예제 #8
0
파일: stb.c 프로젝트: KitoHo/RetroArch
static bool font_renderer_stb_create_atlas(stb_font_renderer_t *self,
      uint8_t *font_data, float font_size, unsigned width, unsigned height)
{
   int i;
   stbtt_pack_context pc = {NULL};
   stbtt_packedchar   chardata[256];

   if (width > 2048 || height > 2048)
   {
      RARCH_WARN("[stb] Font atlas too big: %ux%u\n", width, height);
      goto error;
   }

   if (self->atlas.buffer)
      free(self->atlas.buffer);

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

   if (!self->atlas.buffer)
      goto error;

   stbtt_PackBegin(&pc, self->atlas.buffer,
         self->atlas.width, self->atlas.height,
         self->atlas.width, 1, NULL);

   stbtt_PackFontRange(&pc, font_data, 0, font_size, 0, 256, chardata);
   stbtt_PackEnd(&pc);

   for (i = 0; i < 256; ++i)
   {
      struct font_glyph *g = &self->glyphs[i];
      stbtt_packedchar  *c = &chardata[i];

      g->advance_x = c->xadvance;
      g->atlas_offset_x = c->x0;
      g->atlas_offset_y = c->y0;
      g->draw_offset_x  = c->xoff;
      g->draw_offset_y  = c->yoff;
      g->width          = c->x1 - c->x0;
      g->height         = c->y1 - c->y0;

      /* Make sure important characters fit */
      if (isalnum(i) && (!g->width || !g->height))
      {
         int new_width  = width  * 1.2;
         int new_height = height * 1.2;

         /* Limit growth to 2048x2048 unless we already reached that */
         if (width < 2048 || height < 2048)
         {
            new_width  = MIN(new_width,  2048);
            new_height = MIN(new_height, 2048);
         }

         return font_renderer_stb_create_atlas(self, font_data, font_size,
               new_width, new_height);
      }
   }

   return true;

error:
   self->atlas.width = self->atlas.height = 0;

   if (self->atlas.buffer)
      free(self->atlas.buffer);

   self->atlas.buffer = NULL;

   return false;
}