Beispiel #1
0
// ----------------------------------------------------------------------------
void FontWithFace::init()
{
    setDPI();
    m_page = irr_driver->getVideoDriver()->createImage(video::ECF_A8R8G8B8,
        core::dimension2du(getGlyphPageSize(), getGlyphPageSize()));

    // Get the max height for this face
    assert(m_face_ttf->getTotalFaces() > 0);
    FT_Face cur_face = m_face_ttf->getFace(0);
    font_manager->checkFTError(FT_Set_Pixel_Sizes(cur_face, 0, getDPI()),
        "setting DPI");

    for (int i = 32; i < 128; i++)
    {
        // Test all basic latin characters
        const int idx = FT_Get_Char_Index(cur_face, (wchar_t)i);
        if (idx == 0) continue;
        font_manager->checkFTError(FT_Load_Glyph(cur_face, idx,
            FT_LOAD_DEFAULT), "setting max height");

        const int height = cur_face->glyph->metrics.height / BEARING;
        if (height > m_glyph_max_height)
            m_glyph_max_height = height;
    }

    reset();
}   // init
Beispiel #2
0
void WebEntityItem::appendSubclassData(OctreePacketData* packetData, EncodeBitstreamParams& params,
                                    EntityTreeElementExtraEncodeDataPointer entityTreeElementExtraEncodeData,
                                    EntityPropertyFlags& requestedProperties,
                                    EntityPropertyFlags& propertyFlags,
                                    EntityPropertyFlags& propertiesDidntFit,
                                    int& propertyCount,
                                    OctreeElement::AppendState& appendState) const {

    bool successPropertyFits = true;
    APPEND_ENTITY_PROPERTY(PROP_COLOR, getColor());
    APPEND_ENTITY_PROPERTY(PROP_ALPHA, getAlpha());
    withReadLock([&] {
        _pulseProperties.appendSubclassData(packetData, params, entityTreeElementExtraEncodeData, requestedProperties,
            propertyFlags, propertiesDidntFit, propertyCount, appendState);
    });
    APPEND_ENTITY_PROPERTY(PROP_BILLBOARD_MODE, (uint32_t)getBillboardMode());

    APPEND_ENTITY_PROPERTY(PROP_SOURCE_URL, getSourceUrl());
    APPEND_ENTITY_PROPERTY(PROP_DPI, getDPI());
    APPEND_ENTITY_PROPERTY(PROP_SCRIPT_URL, getScriptURL());
    APPEND_ENTITY_PROPERTY(PROP_MAX_FPS, getMaxFPS());
    APPEND_ENTITY_PROPERTY(PROP_INPUT_MODE, (uint32_t)getInputMode());
    APPEND_ENTITY_PROPERTY(PROP_SHOW_KEYBOARD_FOCUS_HIGHLIGHT, getShowKeyboardFocusHighlight());
}
Beispiel #3
0
// ----------------------------------------------------------------------------
void FontWithFace::insertGlyph(wchar_t c, const GlyphInfo& gi)
{
    assert(gi.glyph_index > 0);
    assert(gi.font_number < m_face_ttf->getTotalFaces());
    FT_Face cur_face = m_face_ttf->getFace(gi.font_number);
    FT_GlyphSlot slot = cur_face->glyph;

    // Faces may be shared across regular and bold,
    // so reset dpi each time
    font_manager->checkFTError(FT_Set_Pixel_Sizes(cur_face, 0, getDPI()),
        "setting DPI");

    font_manager->checkFTError(FT_Load_Glyph(cur_face, gi.glyph_index,
        FT_LOAD_DEFAULT), "loading a glyph");

    if (dynamic_cast<BoldFace*>(this))
    {
        // Embolden the outline of the glyph
        FT_Outline_Embolden(&(slot->outline), getDPI() * 2);
    }

    font_manager->checkFTError(FT_Render_Glyph(slot, FT_RENDER_MODE_NORMAL),
        "render a glyph to bitmap");

    // Convert to an anti-aliased bitmap
    FT_Bitmap bits = slot->bitmap;

    core::dimension2du d(bits.width + 1, bits.rows + 1);
    core::dimension2du texture_size;
    texture_size = d.getOptimalSize(!(irr_driver->getVideoDriver()
        ->queryFeature(video::EVDF_TEXTURE_NPOT)), !(irr_driver
        ->getVideoDriver()->queryFeature(video::EVDF_TEXTURE_NSQUARE)),
        true, 0);

    if ((m_used_width + texture_size.Width > getGlyphPageSize() &&
        m_used_height + m_temp_height + texture_size.Height >
        getGlyphPageSize())                                     ||
        m_used_height + texture_size.Height > getGlyphPageSize())
    {
        // Current glyph page is full:
        // Save the old glyph page
        video::ITexture* page_texture = irr_driver->getVideoDriver()
            ->addTexture("Glyph_page", m_page);
        m_spritebank->setTexture(m_spritebank->getTextureCount() - 1,
            page_texture);
        irr_driver->getVideoDriver()->removeTexture(page_texture);
        assert(page_texture->getReferenceCount() == 1);

        // Clear and add a new one
        createNewGlyphPage();
    }

    video::IImage* glyph = NULL;
    switch (bits.pixel_mode)
    {
        case FT_PIXEL_MODE_GRAY:
        {
            // Create our blank image.
            glyph = irr_driver->getVideoDriver()
                ->createImage(video::ECF_A8R8G8B8, texture_size);
            glyph->fill(video::SColor(0, 255, 255, 255));

            // Load the grayscale data in.
            const float gray_count = static_cast<float>(bits.num_grays);
            const unsigned int image_pitch =
                glyph->getPitch() / sizeof(unsigned int);
            unsigned int* image_data = (unsigned int*)glyph->lock();
            unsigned char* glyph_data = bits.buffer;

            for (unsigned int y = 0; y < (unsigned int)bits.rows; y++)
            {
                unsigned char* row = glyph_data;
                for (unsigned int x = 0; x < (unsigned)bits.width; x++)
                {
                    image_data[y * image_pitch + x] |=
                        static_cast<unsigned int>(255.0f *
                        (static_cast<float>(*row++) / gray_count)) << 24;
                }
                glyph_data += bits.pitch;
            }
            glyph->unlock();
            break;
        }
        default:
            assert(false);
    }
    if (!glyph)
        Log::fatal("FontWithFace", "Failed to load a glyph");

    // Done creating a single glyph, now copy to the glyph page...
    // Determine the linebreak location
    if (m_used_width + texture_size.Width > getGlyphPageSize())
    {
        m_used_width  = 0;
        m_used_height += m_temp_height;
        m_temp_height = 0;
    }

    // Copy to the full glyph page
    glyph->copyTo(m_page, core::position2di(m_used_width, m_used_height));

    // Store the rectangle of current glyph
    gui::SGUISpriteFrame f;
    gui::SGUISprite s;
    core::rect<s32> rectangle(m_used_width, m_used_height,
        m_used_width + bits.width, m_used_height + bits.rows);
    f.rectNumber = m_spritebank->getPositions().size();
    f.textureNumber = m_spritebank->getTextureCount() - 1;

    // Add frame to sprite
    s.Frames.push_back(f);
    s.frameTime = 0;
    m_spritebank->getPositions().push_back(rectangle);
    m_spritebank->getSprites().push_back(s);

    // Save glyph metrics
    FontArea a;
    a.advance_x = cur_face->glyph->advance.x / BEARING;
    a.bearing_x = cur_face->glyph->metrics.horiBearingX / BEARING;
    const int cur_height = (cur_face->glyph->metrics.height / BEARING);
    const int cur_offset_y = cur_height -
        (cur_face->glyph->metrics.horiBearingY / BEARING);
    a.offset_y = m_glyph_max_height - cur_height + cur_offset_y;
    a.offset_y_bt = -cur_offset_y;
    a.spriteno = f.rectNumber;
    m_character_area_map[c] = a;

    // Clean the temporary glyph
    glyph->drop();
    glyph = NULL;

    // Store used area
    m_used_width += texture_size.Width;
    if (m_temp_height < texture_size.Height)
        m_temp_height = texture_size.Height;
}   // insertGlyph
Beispiel #4
0
/** Render a glyph for a character into bitmap and save it into the glyph page.
 *  \param c The character to be loaded.
 *  \param c \ref GlyphInfo for the character.
 */
void FontWithFace::insertGlyph(wchar_t c, const GlyphInfo& gi)
{
    assert(gi.glyph_index > 0);
    assert(gi.font_number < m_face_ttf->getTotalFaces());
    FT_Face cur_face = m_face_ttf->getFace(gi.font_number);
    FT_GlyphSlot slot = cur_face->glyph;

    // Same face may be shared across the different FontWithFace,
    // so reset dpi each time
    font_manager->checkFTError(FT_Set_Pixel_Sizes(cur_face, 0, getDPI()),
        "setting DPI");

    font_manager->checkFTError(FT_Load_Glyph(cur_face, gi.glyph_index,
        FT_LOAD_DEFAULT), "loading a glyph");

    font_manager->checkFTError(shapeOutline(&(slot->outline)),
        "shaping outline");

    font_manager->checkFTError(FT_Render_Glyph(slot, FT_RENDER_MODE_NORMAL),
        "rendering a glyph to bitmap");

    // Convert to an anti-aliased bitmap
    FT_Bitmap* bits = &(slot->bitmap);
    core::dimension2du texture_size(bits->width + 1, bits->rows + 1);
    if ((m_used_width + texture_size.Width > getGlyphPageSize() &&
        m_used_height + m_current_height + texture_size.Height >
        getGlyphPageSize())                                     ||
        m_used_height + texture_size.Height > getGlyphPageSize())
    {
        // Add a new glyph page if current one is full
        createNewGlyphPage();
    }

    // Determine the linebreak location
    if (m_used_width + texture_size.Width > getGlyphPageSize())
    {
        m_used_width  = 0;
        m_used_height += m_current_height;
        m_current_height = 0;
    }

    const unsigned int cur_tex = m_spritebank->getTextureCount() -1;
#ifndef SERVER_ONLY
    video::ITexture* tex = m_spritebank->getTexture(cur_tex);
    glBindTexture(GL_TEXTURE_2D, tex->getOpenGLTextureName());
    assert(bits->pixel_mode == FT_PIXEL_MODE_GRAY);
    if (CVS->isARBTextureSwizzleUsable())
    {
        glTexSubImage2D(GL_TEXTURE_2D, 0, m_used_width, m_used_height,
            bits->width, bits->rows, GL_RED, GL_UNSIGNED_BYTE, bits->buffer);
    }
    else
    {
        const unsigned int size = bits->width * bits->rows;
        uint8_t* image_data = new uint8_t[size * 4];
        memset(image_data, 255, size * 4);
        for (unsigned int i = 0; i < size; i++)
            image_data[4 * i + 3] = bits->buffer[i];
        glTexSubImage2D(GL_TEXTURE_2D, 0, m_used_width, m_used_height,
            bits->width, bits->rows, GL_BGRA, GL_UNSIGNED_BYTE, image_data);
        delete[] image_data;
    }
    if (tex->hasMipMaps())
        glGenerateMipmap(GL_TEXTURE_2D);
    glBindTexture(GL_TEXTURE_2D, 0);
#endif

    // Store the rectangle of current glyph
    gui::SGUISpriteFrame f;
    gui::SGUISprite s;
    core::rect<s32> rectangle(m_used_width, m_used_height,
        m_used_width + bits->width, m_used_height + bits->rows);
    f.rectNumber = m_spritebank->getPositions().size();
    f.textureNumber = cur_tex;

    // Add frame to sprite
    s.Frames.push_back(f);
    s.frameTime = 0;
    m_spritebank->getPositions().push_back(rectangle);
    m_spritebank->getSprites().push_back(s);

    // Save glyph metrics
    FontArea a;
    a.advance_x = cur_face->glyph->advance.x / BEARING;
    a.bearing_x = cur_face->glyph->metrics.horiBearingX / BEARING;
    const int cur_height = (cur_face->glyph->metrics.height / BEARING);
    const int cur_offset_y = cur_height -
        (cur_face->glyph->metrics.horiBearingY / BEARING);
    a.offset_y = m_glyph_max_height - cur_height + cur_offset_y;
    a.offset_y_bt = -cur_offset_y;
    a.spriteno = f.rectNumber;
    m_character_area_map[c] = a;

    // Store used area
    m_used_width += texture_size.Width;
    if (m_current_height < texture_size.Height)
        m_current_height = texture_size.Height;
}   // insertGlyph
Beispiel #5
0
float Utils::getRealSizeInMM(float size)
{
    return size / getDPI() * 25.4;
}