示例#1
0
文件: Text.cpp 项目: jjiezheng/urho3d
void Text::GetBatches(PODVector<UIBatch>& batches, PODVector<float>& vertexData, const IntRect& currentScissor)
{
    // Hovering and/or whole selection batch
    if ((hovering_ && hoverColor_.a_ > 0.0) || (selected_ && selectionColor_.a_ > 0.0f))
    {
        bool both = hovering_ && selected_ && hoverColor_.a_ > 0.0 && selectionColor_.a_ > 0.0f;
        UIBatch batch(this, BLEND_ALPHA, currentScissor, 0, &vertexData);
        batch.AddQuad(0, 0, GetWidth(), GetHeight(), 0, 0, 0, 0, both ? selectionColor_.Lerp(hoverColor_, 0.5f) :
                      (selected_ && selectionColor_.a_ > 0.0f ? selectionColor_ : hoverColor_));
        UIBatch::AddOrMerge(batch, batches);
    }

    // Partial selection batch
    if (!selected_ && selectionLength_ && charSizes_.Size() >= selectionStart_ + selectionLength_ && selectionColor_.a_ > 0.0f)
    {
        UIBatch batch(this, BLEND_ALPHA, currentScissor, 0, &vertexData);

        IntVector2 currentStart = charPositions_[selectionStart_];
        IntVector2 currentEnd = currentStart;
        for (unsigned i = selectionStart_; i < selectionStart_ + selectionLength_; ++i)
        {
            // Check if row changes, and start a new quad in that case
            if (charSizes_[i].x_ && charSizes_[i].y_)
            {
                if (charPositions_[i].y_ != currentStart.y_)
                {
                    batch.AddQuad(currentStart.x_, currentStart.y_, currentEnd.x_ - currentStart.x_, currentEnd.y_ - currentStart.y_,
                                  0, 0, 0, 0, selectionColor_);
                    currentStart = charPositions_[i];
                    currentEnd = currentStart + charSizes_[i];
                }
                else
                {
                    currentEnd.x_ += charSizes_[i].x_;
                    currentEnd.y_ = Max(currentStart.y_ + charSizes_[i].y_, currentEnd.y_);
                }
            }
        }
        if (currentEnd != currentStart)
        {
            batch.AddQuad(currentStart.x_, currentStart.y_, currentEnd.x_ - currentStart.x_, currentEnd.y_ - currentStart.y_,
                          0, 0, 0, 0, selectionColor_);
        }

        UIBatch::AddOrMerge(batch, batches);
    }

    // Text batch
    if (font_)
    {
        const FontFace* face = font_->GetFace(fontSize_);
        if (!face)
            return;

        if (face->textures_.Size() > 1)
        {
            // Only traversing thru the printText once regardless of number of textures/pages in the font
            Vector<PODVector<GlyphLocation> > pageGlyphLocations(face->textures_.Size());

            unsigned rowIndex = 0;
            int x = GetRowStartPosition(rowIndex);
            int y = 0;

            for (unsigned i = 0; i < printText_.Size(); ++i)
            {
                unsigned c = printText_[i];

                if (c != '\n')
                {
                    const FontGlyph* p = face->GetGlyph(c);
                    if (!p)
                        continue;

                    pageGlyphLocations[p->page_].Push(GlyphLocation(x, y, p));

                    x += p->advanceX_;
                    if (i < printText_.Size() - 1)
                        x += face->GetKerning(c, printText_[i + 1]);
                }
                else
                {
                    x = GetRowStartPosition(++rowIndex);
                    y += rowHeight_;
                }
            }

            for (unsigned n = 0; n < face->textures_.Size(); ++n)
            {
                // One batch per texture/page
                UIBatch pageBatch(this, BLEND_ALPHA, currentScissor, face->textures_[n], &vertexData);

                const PODVector<GlyphLocation>& pageGlyphLocation = pageGlyphLocations[n];
                for (unsigned i = 0; i < pageGlyphLocation.Size(); ++i)
                {
                    const GlyphLocation& glyphLocation = pageGlyphLocation[i];
                    const FontGlyph& glyph = *glyphLocation.glyph_;
                    pageBatch.AddQuad(glyphLocation.x_ + glyph.offsetX_, glyphLocation.y_ + glyph.offsetY_, glyph.width_, glyph.height_, glyph.x_, glyph.y_);
                }

                batches.Push(pageBatch);
            }
        }
        else
        {
            // If only one texture page, construct the UI batch directly
            unsigned rowIndex = 0;
            int x = GetRowStartPosition(rowIndex);
            int y = 0;

            UIBatch batch(this, BLEND_ALPHA, currentScissor, face->textures_[0], &vertexData);

            for (unsigned i = 0; i < printText_.Size(); ++i)
            {
                unsigned c = printText_[i];

                if (c != '\n')
                {
                    const FontGlyph* p = face->GetGlyph(c);
                    if (!p)
                        continue;

                    batch.AddQuad(x + p->offsetX_, y + p->offsetY_, p->width_, p->height_, p->x_, p->y_);

                    x += p->advanceX_;
                    if (i < printText_.Size() - 1)
                        x += face->GetKerning(c, printText_[i + 1]);
                }
                else
                {
                    x = GetRowStartPosition(++rowIndex);
                    y += rowHeight_;
                }
            }

            UIBatch::AddOrMerge(batch, batches);
        }
    }

    // Reset hovering for next frame
    hovering_ = false;
}
示例#2
0
文件: Text.cpp 项目: rokups/Urho3D
void Text::GetBatches(ea::vector<UIBatch>& batches, ea::vector<float>& vertexData, const IntRect& currentScissor)
{
    FontFace* face = font_ ? font_->GetFace(fontSize_) : nullptr;
    if (!face)
    {
        hovering_ = false;
        return;
    }

    // If face has changed or char locations are not valid anymore, update before rendering
    if (charLocationsDirty_ || !fontFace_ || face != fontFace_)
        UpdateCharLocations();
    // If face uses mutable glyphs mechanism, reacquire glyphs before rendering to make sure they are in the texture
    else if (face->HasMutableGlyphs())
    {
        for (unsigned i = 0; i < printText_.size(); ++i)
            face->GetGlyph(printText_[i]);
    }

    // Hovering and/or whole selection batch
    UISelectable::GetBatches(batches, vertexData, currentScissor);

    // Partial selection batch
    if (!selected_ && selectionLength_ && charLocations_.size() >= selectionStart_ + selectionLength_ && selectionColor_.a_ > 0.0f)
    {
        UIBatch batch(this, BLEND_ALPHA, currentScissor, nullptr, &vertexData);
        batch.SetColor(selectionColor_);

        Vector2 currentStart = charLocations_[selectionStart_].position_;
        Vector2 currentEnd = currentStart;
        for (unsigned i = selectionStart_; i < selectionStart_ + selectionLength_; ++i)
        {
            // Check if row changes, and start a new quad in that case
            if (charLocations_[i].size_ != Vector2::ZERO)
            {
                if (charLocations_[i].position_.y_ != currentStart.y_)
                {
                    batch.AddQuad(currentStart.x_, currentStart.y_, currentEnd.x_ - currentStart.x_,
                        currentEnd.y_ - currentStart.y_, 0, 0);
                    currentStart = charLocations_[i].position_;
                    currentEnd = currentStart + charLocations_[i].size_;
                }
                else
                {
                    currentEnd.x_ += charLocations_[i].size_.x_;
                    currentEnd.y_ = Max(currentStart.y_ + charLocations_[i].size_.y_, currentEnd.y_);
                }
            }
        }
        if (currentEnd != currentStart)
        {
            batch.AddQuad(currentStart.x_, currentStart.y_, currentEnd.x_ - currentStart.x_, currentEnd.y_ - currentStart.y_, 0, 0);
        }

        UIBatch::AddOrMerge(batch, batches);
    }

    // Text batch
    TextEffect textEffect = font_->IsSDFFont() ? TE_NONE : textEffect_;
    const ea::vector<ea::shared_ptr<Texture2D> >& textures = face->GetTextures();
    for (unsigned n = 0; n < textures.size() && n < pageGlyphLocations_.size(); ++n)
    {
        // One batch per texture/page
        UIBatch pageBatch(this, BLEND_ALPHA, currentScissor, textures[n], &vertexData);

        const ea::vector<GlyphLocation>& pageGlyphLocation = pageGlyphLocations_[n];

        switch (textEffect)
        {
        case TE_NONE:
            ConstructBatch(pageBatch, pageGlyphLocation, 0, 0);
            break;

        case TE_SHADOW:
            ConstructBatch(pageBatch, pageGlyphLocation, shadowOffset_.x_, shadowOffset_.y_, &effectColor_, effectDepthBias_);
            ConstructBatch(pageBatch, pageGlyphLocation, 0, 0);
            break;

        case TE_STROKE:
            if (roundStroke_)
            {
                // Samples should be even or glyph may be redrawn in wrong x y pos making stroke corners rough
                // Adding to thickness helps with thickness of 1 not having enought samples for this formula
                // or certain fonts with reflex corners requiring more glyph samples for a smooth stroke when large
                int thickness = Min(strokeThickness_, fontSize_);
                int samples = thickness * thickness + (thickness % 2 == 0 ? 4 : 3);
                float angle = 360.f / samples;
                auto floatThickness = (float)thickness;
                for (int i = 0; i < samples; ++i)
                {
                    float x = Cos(angle * i) * floatThickness;
                    float y = Sin(angle * i) * floatThickness;
                    ConstructBatch(pageBatch, pageGlyphLocation, x, y, &effectColor_, effectDepthBias_);
                }
            }
            else
            {
                int thickness = Min(strokeThickness_, fontSize_);
                int x, y;
                for (x = -thickness; x <= thickness; ++x)
                {
                    for (y = -thickness; y <= thickness; ++y)
                    {
                        // Don't draw glyphs that aren't on the edges
                        if (x > -thickness && x < thickness &&
                            y > -thickness && y < thickness)
                            continue;

                        ConstructBatch(pageBatch, pageGlyphLocation, x, y, &effectColor_, effectDepthBias_);
                    }
                }
            }
            ConstructBatch(pageBatch, pageGlyphLocation, 0, 0);
            break;
        }

        UIBatch::AddOrMerge(pageBatch, batches);
    }
}
示例#3
0
文件: Text.cpp 项目: mrsaleh/Urho3D
void Text::GetBatches(PODVector<UIBatch>& batches, PODVector<float>& vertexData, const IntRect& currentScissor)
{
    FontFace* face = font_ ? font_->GetFace(fontSize_) : (FontFace*)0;
    if (!face)
    {
        hovering_ = false;
        return;
    }

    // If face has changed or char locations are not valid anymore, update before rendering
    if (charLocationsDirty_ || !fontFace_ || face != fontFace_)
        UpdateCharLocations();
    // If face uses mutable glyphs mechanism, reacquire glyphs before rendering to make sure they are in the texture
    else if (face->HasMutableGlyphs())
    {
        for (unsigned i = 0; i < printText_.Size(); ++i)
            face->GetGlyph(printText_[i]);
    }

    // Hovering and/or whole selection batch
    if ((hovering_ && hoverColor_.a_ > 0.0) || (selected_ && selectionColor_.a_ > 0.0f))
    {
        bool both = hovering_ && selected_ && hoverColor_.a_ > 0.0 && selectionColor_.a_ > 0.0f;
        UIBatch batch(this, BLEND_ALPHA, currentScissor, 0, &vertexData);
        batch.SetColor(both ? selectionColor_.Lerp(hoverColor_, 0.5f) :
            (selected_ && selectionColor_.a_ > 0.0f ? selectionColor_ : hoverColor_));
        batch.AddQuad(0, 0, GetWidth(), GetHeight(), 0, 0);
        UIBatch::AddOrMerge(batch, batches);
    }

    // Partial selection batch
    if (!selected_ && selectionLength_ && charLocations_.Size() >= selectionStart_ + selectionLength_ && selectionColor_.a_ > 0.0f)
    {
        UIBatch batch(this, BLEND_ALPHA, currentScissor, 0, &vertexData);
        batch.SetColor(selectionColor_);

        IntVector2 currentStart = charLocations_[selectionStart_].position_;
        IntVector2 currentEnd = currentStart;
        for (unsigned i = selectionStart_; i < selectionStart_ + selectionLength_; ++i)
        {
            // Check if row changes, and start a new quad in that case
            if (charLocations_[i].size_ != IntVector2::ZERO)
            {
                if (charLocations_[i].position_.y_ != currentStart.y_)
                {
                    batch.AddQuad(currentStart.x_, currentStart.y_, currentEnd.x_ - currentStart.x_,
                        currentEnd.y_ - currentStart.y_, 0, 0);
                    currentStart = charLocations_[i].position_;
                    currentEnd = currentStart + charLocations_[i].size_;
                }
                else
                {
                    currentEnd.x_ += charLocations_[i].size_.x_;
                    currentEnd.y_ = Max(currentStart.y_ + charLocations_[i].size_.y_, currentEnd.y_);
                }
            }
        }
        if (currentEnd != currentStart)
        {
            batch.AddQuad(currentStart.x_, currentStart.y_, currentEnd.x_ - currentStart.x_, currentEnd.y_ - currentStart.y_, 0, 0);
        }

        UIBatch::AddOrMerge(batch, batches);
    }

    // Text batch
    TextEffect textEffect = font_->IsSDFFont() ? TE_NONE : textEffect_;
    const Vector<SharedPtr<Texture2D> >& textures = face->GetTextures();
    for (unsigned n = 0; n < textures.Size() && n < pageGlyphLocations_.Size(); ++n)
    {
        // One batch per texture/page
        UIBatch pageBatch(this, BLEND_ALPHA, currentScissor, textures[n], &vertexData);

        const PODVector<GlyphLocation>& pageGlyphLocation = pageGlyphLocations_[n];

        switch (textEffect)
        {
        case TE_NONE:
            ConstructBatch(pageBatch, pageGlyphLocation, 0, 0);
            break;

        case TE_SHADOW:
            ConstructBatch(pageBatch, pageGlyphLocation, 1, 1, &effectColor_, effectDepthBias_);
            ConstructBatch(pageBatch, pageGlyphLocation, 0, 0);
            break;

        case TE_STROKE:
            ConstructBatch(pageBatch, pageGlyphLocation, -1, -1, &effectColor_, effectDepthBias_);
            ConstructBatch(pageBatch, pageGlyphLocation, 0, -1, &effectColor_, effectDepthBias_);
            ConstructBatch(pageBatch, pageGlyphLocation, 1, -1, &effectColor_, effectDepthBias_);
            ConstructBatch(pageBatch, pageGlyphLocation, -1, 0, &effectColor_, effectDepthBias_);
            ConstructBatch(pageBatch, pageGlyphLocation, 1, 0, &effectColor_, effectDepthBias_);
            ConstructBatch(pageBatch, pageGlyphLocation, -1, 1, &effectColor_, effectDepthBias_);
            ConstructBatch(pageBatch, pageGlyphLocation, 0, 1, &effectColor_, effectDepthBias_);
            ConstructBatch(pageBatch, pageGlyphLocation, 1, 1, &effectColor_, effectDepthBias_);
            ConstructBatch(pageBatch, pageGlyphLocation, 0, 0);
            break;
        }

        UIBatch::AddOrMerge(pageBatch, batches);
    }

    // Reset hovering for next frame
    hovering_ = false;
}