LLFontGlyphInfo* LLFontFreetype::addGlyphFromFont(const LLFontFreetype *fontp, llwchar wch, U32 glyph_index) const { if (mFTFace == NULL) return NULL; //llassert(!mIsFallback); fontp->renderGlyph(glyph_index); S32 width = fontp->mFTFace->glyph->bitmap.width; S32 height = fontp->mFTFace->glyph->bitmap.rows; S32 pos_x, pos_y; S32 bitmap_num; mFontBitmapCachep->nextOpenPos(width, pos_x, pos_y, bitmap_num); mAddGlyphCount++; LLFontGlyphInfo* gi = new LLFontGlyphInfo(glyph_index); gi->mXBitmapOffset = pos_x; gi->mYBitmapOffset = pos_y; gi->mBitmapNum = bitmap_num; gi->mWidth = width; gi->mHeight = height; gi->mXBearing = fontp->mFTFace->glyph->bitmap_left; gi->mYBearing = fontp->mFTFace->glyph->bitmap_top; // Convert these from 26.6 units to float pixels. gi->mXAdvance = fontp->mFTFace->glyph->advance.x / 64.f; gi->mYAdvance = fontp->mFTFace->glyph->advance.y / 64.f; insertGlyphInfo(wch, gi); llassert(fontp->mFTFace->glyph->bitmap.pixel_mode == FT_PIXEL_MODE_MONO || fontp->mFTFace->glyph->bitmap.pixel_mode == FT_PIXEL_MODE_GRAY); if (fontp->mFTFace->glyph->bitmap.pixel_mode == FT_PIXEL_MODE_MONO || fontp->mFTFace->glyph->bitmap.pixel_mode == FT_PIXEL_MODE_GRAY) { U8 *buffer_data = fontp->mFTFace->glyph->bitmap.buffer; S32 buffer_row_stride = fontp->mFTFace->glyph->bitmap.pitch; U8 *tmp_graydata = NULL; if (fontp->mFTFace->glyph->bitmap.pixel_mode == FT_PIXEL_MODE_MONO) { // need to expand 1-bit bitmap to 8-bit graymap. tmp_graydata = new U8[width * height]; S32 xpos, ypos; for (ypos = 0; ypos < height; ++ypos) { S32 bm_row_offset = buffer_row_stride * ypos; for (xpos = 0; xpos < width; ++xpos) { U32 bm_col_offsetbyte = xpos / 8; U32 bm_col_offsetbit = 7 - (xpos % 8); U32 bit = !!(buffer_data[bm_row_offset + bm_col_offsetbyte ] & (1 << bm_col_offsetbit) ); tmp_graydata[width*ypos + xpos] = 255 * bit; } } // use newly-built graymap. buffer_data = tmp_graydata; buffer_row_stride = width; } switch (mFontBitmapCachep->getNumComponents()) { case 1: mFontBitmapCachep->getImageRaw(bitmap_num)->setSubImage(pos_x, pos_y, width, height, buffer_data, buffer_row_stride, TRUE); break; case 2: setSubImageLuminanceAlpha(pos_x, pos_y, bitmap_num, width, height, buffer_data, buffer_row_stride); break; default: break; } if (tmp_graydata) delete[] tmp_graydata; } else { // we don't know how to handle this pixel format from FreeType; // omit it from the font-image. } LLImageGL *image_gl = mFontBitmapCachep->getImageGL(bitmap_num); LLImageRaw *image_raw = mFontBitmapCachep->getImageRaw(bitmap_num); image_gl->setSubImage(image_raw, 0, 0, image_gl->getWidth(), image_gl->getHeight()); return gi; }
F32 LLFont::getXAdvance(const llwchar wch) const { if (mFTFace == NULL) return 0.0; llassert(!mIsFallback); U32 glyph_index; // Return existing info only if it is current LLFontGlyphInfo* gi = getGlyphInfo(wch); if (gi && gi->mMetricsValid) { return gi->mXAdvance; } const LLFont* fontp = this; // Initialize char to glyph map glyph_index = FT_Get_Char_Index(mFTFace, wch); if (glyph_index == 0 && mFallbackFontp) { LLFontList::iterator iter; for(iter = mFallbackFontp->begin(); (iter != mFallbackFontp->end()) && (glyph_index == 0); iter++) { glyph_index = FT_Get_Char_Index((*iter)->mFTFace, wch); if(glyph_index) { fontp = *iter; } } } if (glyph_index) { // This font has this glyph fontp->renderGlyph(glyph_index); // Create the entry if it's not there char_glyph_info_map_t::iterator iter2 = mCharGlyphInfoMap.find(wch); if (iter2 == mCharGlyphInfoMap.end()) { gi = new LLFontGlyphInfo(glyph_index); insertGlyphInfo(wch, gi); } else { gi = iter2->second; } gi->mWidth = fontp->mFTFace->glyph->bitmap.width; gi->mHeight = fontp->mFTFace->glyph->bitmap.rows; // Convert these from 26.6 units to float pixels. gi->mXAdvance = fontp->mFTFace->glyph->advance.x / 64.f; gi->mYAdvance = fontp->mFTFace->glyph->advance.y / 64.f; gi->mMetricsValid = TRUE; return gi->mXAdvance; } else { gi = get_if_there(mCharGlyphInfoMap, (llwchar)0, (LLFontGlyphInfo*)NULL); if (gi) { return gi->mXAdvance; } } // Last ditch fallback - no glyphs defined at all. return (F32)mFontBitmapCachep->getMaxCharWidth(); }