JNIEXPORT void JNICALL Java_com_badlogic_gdx_graphics_g2d_stbtt_StbTrueType_makeCodepointBitmap(JNIEnv* env, jclass clazz, jlong info, jobject obj_bitmap, jint bitmapWidth, jint bitmapHeight, jint bitmapStride, jfloat scaleX, jfloat scaleY, jint codePoint) { char* bitmap = (char*)env->GetDirectBufferAddress(obj_bitmap); //@line:143 stbtt_MakeCodepointBitmap((stbtt_fontinfo*)info, (unsigned char*)bitmap, bitmapWidth, bitmapHeight, bitmapStride, scaleX, scaleY, codePoint); }
void Font::drawStringUnicode(int x, int y, const std::wstring& str, Color color, bool top_screen, bool side) { if(!isLoaded()) { return; } Image char_render; std::vector<unsigned char> char_raster; int bx, by, bw, bh; int ascent, descent, lineGap; int sx = 0, sy = 0; stbtt_GetFontVMetrics(&m_info, &ascent, &descent, &lineGap); ascent *= m_scale; descent *= m_scale; for (unsigned int i = 0; i < str.length(); i++) { if(str[i + 1] == L'\n') { sy += lineGap * m_scale; sx = 0; continue; } stbtt_GetCodepointBitmapBox(&m_info, str[i], m_scale, m_scale, &bx, &by, &bw, &bh); int width = bw - bx; int height = bh - by; int oy = ascent + by; char_raster.resize(width * height); stbtt_MakeCodepointBitmap(&m_info, &char_raster[0], width, height, width, m_scale, m_scale, str[i]); char_render.create(width, height, Color(0, 0, 0, 0)); for (int ix = 0; ix < width; ix++) { for (int iy = 0; iy < height; iy++) { if (char_raster[ix + iy * width] != 0) char_render.putPixel(ix, iy, Color(color.r, color.g, color.b, char_raster[ix + iy * width])); } } char_render.draw(sx + x, sy + y + oy, top_screen, side); int advance; stbtt_GetCodepointHMetrics(&m_info, str[i], &advance, 0); sx += advance * m_scale; int kerning = stbtt_GetCodepointKernAdvance(&m_info, str[i], str[i + 1]); sx += kerning * m_scale; } }
void Font::drawStringToBuffer(int x, int y, const std::wstring& str, Color color, unsigned char* buffer, int buffer_width, int buffer_height, int bitsperpixel, int max_width) { std::vector<unsigned char> char_raster; int bx, by, bw, bh; int ascent, descent, lineGap; int sx = 0, sy = 0; int width, height; stbtt_GetFontVMetrics(&m_info, &ascent, &descent, &lineGap); ascent *= m_scale; descent *= m_scale; lineGap *= m_scale; this->measureText(str, width, height, max_width); for (unsigned int i = 0; i < str.length(); i++) { if(str[i] == L'\n') { sy += ascent - descent + lineGap; sx = 0; continue; } stbtt_GetCodepointBitmapBox(&m_info, str[i], m_scale, m_scale, &bx, &by, &bw, &bh); int char_width = bw - bx; int char_height = bh - by; int oy = ascent + by; if(max_width > 0 && sx + char_width > max_width) { sy += ascent - descent + lineGap; sx = 0; } char_raster.resize(char_width * char_height); stbtt_MakeCodepointBitmap(&m_info, &char_raster[0], char_width, char_height, char_width, m_scale, m_scale, str[i]); for (int ix = 0; ix < char_width; ix++) { for (int iy = 0; iy < char_height; iy++) { int xpos = x + sx + ix; int ypos = buffer_height - (y + sy + oy + iy) -1; if (char_raster[ix + iy * char_width] != 0 && xpos < buffer_width && ypos < buffer_height) { unsigned int alpha = char_raster[ix + iy * char_width]; unsigned int inv_alpha = 255 - alpha; if (bitsperpixel == 24) { unsigned char bg_r = buffer[3 * (xpos + ypos * buffer_width) + 0]; unsigned char bg_g = buffer[3 * (xpos + ypos * buffer_width) + 1]; unsigned char bg_b = buffer[3 * (xpos + ypos * buffer_width) + 2]; unsigned char r = (unsigned char)((alpha * color.r + inv_alpha * bg_r) >> 8); unsigned char g = (unsigned char)((alpha * color.g + inv_alpha * bg_g) >> 8); unsigned char b = (unsigned char)((alpha * color.b + inv_alpha * bg_b) >> 8); buffer[3 * (xpos + ypos * buffer_width) + 0] = b; buffer[3 * (xpos + ypos * buffer_width) + 1] = g; buffer[3 * (xpos + ypos * buffer_width) + 2] = r; } else { unsigned char bg_r = buffer[4 * (xpos + ypos * buffer_width) + 0]; unsigned char bg_g = buffer[4 * (xpos + ypos * buffer_width) + 1]; unsigned char bg_b = buffer[4 * (xpos + ypos * buffer_width) + 2]; unsigned char bg_a = buffer[4 * (xpos + ypos * buffer_width) + 3]; unsigned char a; if(alpha == 255 || bg_a == 255) { a = 255; } else { a = alpha + (inv_alpha * bg_a) / 256; } unsigned int r,g,b; if(a == 0) { r = 0; g = 0; b = 0; } else { r = (alpha * color.r + (inv_alpha * bg_a * bg_r) / 256) / a; b = (alpha * color.b + (inv_alpha * bg_a * bg_b) / 256) / a; g = (alpha * color.g + (inv_alpha * bg_a * bg_g) / 256) / a; } buffer[4 * (xpos + ypos * buffer_width) + 0] = b > 255 ? 255 : b; buffer[4 * (xpos + ypos * buffer_width) + 1] = g > 255 ? 255 : g; buffer[4 * (xpos + ypos * buffer_width) + 2] = r > 255 ? 255 : r; buffer[4 * (xpos + ypos * buffer_width) + 3] = a; } } }
void Text::setText(const char* text) { int length = strlen(text); if(length > 255) length = 255; memset(pTextBuffer, 0x00, 256); memcpy(pTextBuffer, text, length); const char* p; int width=0,height=0; /* calculate font scaling */ LOCK_ACQUIRE(gFtLock); //float scale = stbtt_ScaleForPixelHeight(gFontInfo, pPixelSize); float scale = stbtt_ScaleForMappingEmToPixels(gFontInfo, pPixelSize); int ascent, descent, lineGap; stbtt_GetFontVMetrics(gFontInfo, &ascent, &descent, &lineGap); ascent *= scale; descent *= scale; height = ascent; // calculate bitmap size for (p = pTextBuffer; *p; p++) { /* how wide is this character */ int ax; stbtt_GetCodepointHMetrics(gFontInfo, p[0], &ax, 0); width += ax * scale; /* add kerning */ int kern; kern = stbtt_GetCodepointKernAdvance(gFontInfo, p[0], p[1]); width += kern * scale; } //check if old bitmap exists, and delete it uint8_t* oldBitmap = pBitmap; pBitmap = (uint8_t*)malloc(width*height); if(oldBitmap) { free(oldBitmap); } memset(pBitmap,0,width*height); pBitmapWidth = width; pBitmapHeight = height; setSizeN( 2.f*((float)pBitmapWidth)/GetCore()->screen_width, 2.f*((float)pBitmapHeight)/GetCore()->screen_width ); int x=0,y=0; // render text to buffer for (p = pTextBuffer; *p; p++) { /* get bounding box for character (may be offset to account for chars that dip above or below the line */ int c_x1, c_y1, c_x2, c_y2; stbtt_GetCodepointBitmapBox(gFontInfo, p[0], scale, scale, &c_x1, &c_y1, &c_x2, &c_y2); /* compute y (different characters have different heights */ y = ascent + c_y1; /* render character (stride and offset is important here) */ int byteOffset = x + (y * width); stbtt_MakeCodepointBitmap(gFontInfo, pBitmap + byteOffset, c_x2 - c_x1, c_y2 - c_y1, width, scale, scale, p[0]); /* how wide is this character */ int ax; stbtt_GetCodepointHMetrics(gFontInfo, p[0], &ax, 0); x += ax * scale; /* add kerning */ int kern; kern = stbtt_GetCodepointKernAdvance(gFontInfo, p[0], p[1]); x += kern * scale; } LOCK_RELEASE(gFtLock); updateBitmap = true; }
Bytes& StbFontRenderer::RenderText( const FontPtr& data, const FontProperties& properties, cstring text, Bytes& output, Size& imageSize) { using irect = rect<int>; auto stb_data = &data->info; auto scale = properties.scale; Bytes stringData = Bytes::CreateString(text); szptr bit_w = 0; int x = 0; /* We use this to find kerning character */ auto shadowChar = stringData.begin(); for(auto c : stringData) { irect bbox = {}; stbtt_GetCodepointBitmapBox( stb_data, c, scale, scale, &bbox.x, &bbox.y, &bbox.w, &bbox.h); int y = properties.ascent + bbox.y, ax = 0, kern = 0; stbtt_GetCodepointHMetrics(stb_data, c, &ax, nullptr); kern = stbtt_GetCodepointKernAdvance(stb_data, c, *shadowChar); x += scale * (ax + kern); imageSize.w = CMath::max<u32>(imageSize.w, x + (bbox.w - bbox.x)); imageSize.h = CMath::max<u32>(imageSize.h, y + (bbox.h - bbox.y)); } bit_w = C_FCAST<szptr>(imageSize.w); output = Bytes::Alloc(imageSize.area()); shadowChar = stringData.begin(); x = 0; for(auto c : stringData) { ++shadowChar; irect bbox = {}; stbtt_GetCodepointBitmapBox( stb_data, c, scale, scale, &bbox.x, &bbox.y, &bbox.w, &bbox.h); int y = properties.ascent + bbox.y, ax = 0, kern = 0; szptr offset = C_FCAST<szptr>(x + y * bit_w); stbtt_MakeCodepointBitmap( stb_data, &output[offset], (bbox.w - bbox.x), (bbox.h - bbox.y), bit_w, scale, scale, c); stbtt_GetCodepointHMetrics(stb_data, c, &ax, nullptr); kern = stbtt_GetCodepointKernAdvance(stb_data, c, *shadowChar); x += scale * (ax + kern); } return output; }