enum fastuidraw::return_code
fastuidraw::GlyphRenderDataCoverage::
upload_to_atlas(const GlyphAtlas::handle &atlas,
                GlyphLocation &atlas_location,
                GlyphLocation &secondary_atlas_location,
                int &geometry_offset,
                int &geometry_length) const
{
  GlyphDataPrivate *d;
  d = reinterpret_cast<GlyphDataPrivate*>(m_d);
  atlas_location = atlas->allocate(d->m_resolution, make_c_array(d->m_texels));
  secondary_atlas_location = GlyphLocation();
  geometry_offset = -1;
  geometry_length = 0;

  return atlas_location.valid() ?
    routine_success :
    routine_fail;
}
void
VectorAttributes::SetFromNode(DataNode *parentNode)
{
    if(parentNode == 0)
        return;

    DataNode *searchNode = parentNode->GetNode("VectorAttributes");
    if(searchNode == 0)
        return;

    DataNode *node;
    if((node = searchNode->GetNode("glyphLocation")) != 0)
    {
        // Allow enums to be int or string in the config file
        if(node->GetNodeType() == INT_NODE)
        {
            int ival = node->AsInt();
            if(ival >= 0 && ival < 2)
                SetGlyphLocation(GlyphLocation(ival));
        }
        else if(node->GetNodeType() == STRING_NODE)
        {
            GlyphLocation value;
            if(GlyphLocation_FromString(node->AsString(), value))
                SetGlyphLocation(value);
        }
    }
    if((node = searchNode->GetNode("useStride")) != 0)
        SetUseStride(node->AsBool());
    if((node = searchNode->GetNode("stride")) != 0)
        SetStride(node->AsInt());
    if((node = searchNode->GetNode("nVectors")) != 0)
        SetNVectors(node->AsInt());
    if((node = searchNode->GetNode("lineStyle")) != 0)
        SetLineStyle(node->AsInt());
    if((node = searchNode->GetNode("lineWidth")) != 0)
        SetLineWidth(node->AsInt());
    if((node = searchNode->GetNode("scale")) != 0)
        SetScale(node->AsDouble());
    if((node = searchNode->GetNode("scaleByMagnitude")) != 0)
        SetScaleByMagnitude(node->AsBool());
    if((node = searchNode->GetNode("autoScale")) != 0)
        SetAutoScale(node->AsBool());
    if((node = searchNode->GetNode("headSize")) != 0)
        SetHeadSize(node->AsDouble());
    if((node = searchNode->GetNode("headOn")) != 0)
        SetHeadOn(node->AsBool());
    if((node = searchNode->GetNode("colorByMag")) != 0)
        SetColorByMag(node->AsBool());
    if((node = searchNode->GetNode("useLegend")) != 0)
        SetUseLegend(node->AsBool());
    if((node = searchNode->GetNode("vectorColor")) != 0)
        vectorColor.SetFromNode(node);
    if((node = searchNode->GetNode("colorTableName")) != 0)
        SetColorTableName(node->AsString());
    if((node = searchNode->GetNode("invertColorTable")) != 0)
        SetInvertColorTable(node->AsBool());
    if((node = searchNode->GetNode("vectorOrigin")) != 0)
    {
        // Allow enums to be int or string in the config file
        if(node->GetNodeType() == INT_NODE)
        {
            int ival = node->AsInt();
            if(ival >= 0 && ival < 3)
                SetVectorOrigin(OriginType(ival));
        }
        else if(node->GetNodeType() == STRING_NODE)
        {
            OriginType value;
            if(OriginType_FromString(node->AsString(), value))
                SetVectorOrigin(value);
        }
    }
    if((node = searchNode->GetNode("minFlag")) != 0)
        SetMinFlag(node->AsBool());
    if((node = searchNode->GetNode("maxFlag")) != 0)
        SetMaxFlag(node->AsBool());
    if((node = searchNode->GetNode("limitsMode")) != 0)
    {
        // Allow enums to be int or string in the config file
        if(node->GetNodeType() == INT_NODE)
        {
            int ival = node->AsInt();
            if(ival >= 0 && ival < 2)
                SetLimitsMode(LimitsMode(ival));
        }
        else if(node->GetNodeType() == STRING_NODE)
        {
            LimitsMode value;
            if(LimitsMode_FromString(node->AsString(), value))
                SetLimitsMode(value);
        }
    }
    if((node = searchNode->GetNode("min")) != 0)
        SetMin(node->AsDouble());
    if((node = searchNode->GetNode("max")) != 0)
        SetMax(node->AsDouble());
    if((node = searchNode->GetNode("lineStem")) != 0)
    {
        // Allow enums to be int or string in the config file
        if(node->GetNodeType() == INT_NODE)
        {
            int ival = node->AsInt();
            if(ival >= 0 && ival < 2)
                SetLineStem(LineStem(ival));
        }
        else if(node->GetNodeType() == STRING_NODE)
        {
            LineStem value;
            if(LineStem_FromString(node->AsString(), value))
                SetLineStem(value);
        }
    }
    if((node = searchNode->GetNode("geometryQuality")) != 0)
    {
        // Allow enums to be int or string in the config file
        if(node->GetNodeType() == INT_NODE)
        {
            int ival = node->AsInt();
            if(ival >= 0 && ival < 2)
                SetGeometryQuality(Quality(ival));
        }
        else if(node->GetNodeType() == STRING_NODE)
        {
            Quality value;
            if(Quality_FromString(node->AsString(), value))
                SetGeometryQuality(value);
        }
    }
    if((node = searchNode->GetNode("stemWidth")) != 0)
        SetStemWidth(node->AsDouble());
    if((node = searchNode->GetNode("origOnly")) != 0)
        SetOrigOnly(node->AsBool());
    if((node = searchNode->GetNode("glyphType")) != 0)
    {
        // Allow enums to be int or string in the config file
        if(node->GetNodeType() == INT_NODE)
        {
            int ival = node->AsInt();
            if(ival >= 0 && ival < 2)
                SetGlyphType(GlyphType(ival));
        }
        else if(node->GetNodeType() == STRING_NODE)
        {
            GlyphType value;
            if(GlyphType_FromString(node->AsString(), value))
                SetGlyphType(value);
        }
    }
}
VectorAttributes::GlyphLocation
VectorAttributes::GetGlyphLocation() const
{
    return GlyphLocation(glyphLocation);
}
Exemple #4
0
void Text::UpdateCharLocations()
{
    // Remember the font face to see if it's still valid when it's time to render
    FontFace* face = font_ ? font_->GetFace(fontSize_) : nullptr;
    if (!face)
        return;
    fontFace_ = face;

    auto rowHeight = RoundToInt(rowSpacing_ * rowHeight_);

    // Store position & size of each character, and locations per texture page
    unsigned numChars = unicodeText_.size();
    charLocations_.resize(numChars + 1);
    pageGlyphLocations_.resize(face->GetTextures().size());
    for (unsigned i = 0; i < pageGlyphLocations_.size(); ++i)
        pageGlyphLocations_[i].clear();

    IntVector2 offset = font_->GetTotalGlyphOffset(fontSize_);

    unsigned rowIndex = 0;
    unsigned lastFilled = 0;
    float x = Round(GetRowStartPosition(rowIndex) + offset.x_);
    float y = Round(offset.y_);

    for (unsigned i = 0; i < printText_.size(); ++i)
    {
        CharLocation loc;
        loc.position_ = Vector2(x, y);

        unsigned c = printText_[i];
        if (c != '\n')
        {
            const FontGlyph* glyph = face->GetGlyph(c);
            loc.size_ = Vector2(glyph ? glyph->advanceX_ : 0, rowHeight_);
            if (glyph)
            {
                // Store glyph's location for rendering. Verify that glyph page is valid
                if (glyph->page_ < pageGlyphLocations_.size())
                    pageGlyphLocations_[glyph->page_].push_back(GlyphLocation(x, y, glyph));
                x += glyph->advanceX_;
                if (i < printText_.size() - 1)
                    x += face->GetKerning(c, printText_[i + 1]);
            }
        }
        else
        {
            loc.size_ = Vector2::ZERO;
            x = GetRowStartPosition(++rowIndex);
            y += rowHeight;
        }

        if (lastFilled > printToText_[i])
            lastFilled = printToText_[i];

        // Fill gaps in case characters were skipped from printing
        for (unsigned j = lastFilled; j <= printToText_[i]; ++j)
            charLocations_[j] = loc;
        lastFilled = printToText_[i] + 1;
    }
    // Store the ending position
    charLocations_[numChars].position_ = Vector2(x, y);
    charLocations_[numChars].size_ = Vector2::ZERO;

    charLocationsDirty_ = false;
}
Exemple #5
0
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;
}