Beispiel #1
0
SymbolQuads getIconQuads(Anchor& anchor, const PositionedIcon& shapedIcon,
        const GeometryCoordinates& line, const SymbolLayoutProperties& layout,
        const bool alongLine) {

    auto image = *(shapedIcon.image);

    const float border = 1.0;
    auto left = shapedIcon.left - border;
    auto right = left + image.pos.w / image.relativePixelRatio;
    auto top = shapedIcon.top - border;
    auto bottom = top + image.pos.h / image.relativePixelRatio;
    vec2<float> tl{left, top};
    vec2<float> tr{right, top};
    vec2<float> br{right, bottom};
    vec2<float> bl{left, bottom};


    float angle = layout.icon.rotate * util::DEG2RAD;
    if (alongLine) {
        assert(static_cast<unsigned int>(anchor.segment) < line.size());
        const GeometryCoordinate &prev= line[anchor.segment];
        if (anchor.y == prev.y && anchor.x == prev.x &&
            static_cast<unsigned int>(anchor.segment + 1) < line.size()) {
            const GeometryCoordinate &next= line[anchor.segment + 1];
            angle += std::atan2(anchor.y - next.y, anchor.x - next.x) + M_PI;
        } else {
            angle += std::atan2(anchor.y - prev.y, anchor.x - prev.x);
        }
    }


    if (angle) {
        // Compute the transformation matrix.
        float angle_sin = std::sin(angle);
        float angle_cos = std::cos(angle);
        std::array<float, 4> matrix = {{angle_cos, -angle_sin, angle_sin, angle_cos}};

        tl = tl.matMul(matrix);
        tr = tr.matMul(matrix);
        bl = bl.matMul(matrix);
        br = br.matMul(matrix);
    }

    SymbolQuads quads;
    quads.emplace_back(tl, tr, bl, br, image.pos, 0, anchor, globalMinScale, std::numeric_limits<float>::infinity());
    return quads;
}
SymbolQuads getIconQuads(Anchor &anchor, const PositionedIcon &shapedIcon,
                         const std::vector<Coordinate> &line, const StyleLayoutSymbol &layout,
                         const bool alongLine) {

    const float border = 1.0;
    auto left = shapedIcon.left - border;
    auto right = left + shapedIcon.image.w;
    auto top = shapedIcon.top - border;
    auto bottom = top + shapedIcon.image.h;
    vec2<float> tl{left, top};
    vec2<float> tr{right, top};
    vec2<float> br{right, bottom};
    vec2<float> bl{left, bottom};


    float angle = layout.icon.rotate * M_PI / 180.0f;
    if (alongLine) {
        assert(static_cast<unsigned int>(anchor.segment) < line.size());
        const Coordinate &prev= line[anchor.segment];
        angle += std::atan2(anchor.y - prev.y, anchor.x - prev.x);
    }


    if (angle) {
        // Compute the transformation matrix.
        float angle_sin = std::sin(angle);
        float angle_cos = std::cos(angle);
        std::array<float, 4> matrix = {{angle_cos, -angle_sin, angle_sin, angle_cos}};

        tl = tl.matMul(matrix);
        tr = tr.matMul(matrix);
        bl = bl.matMul(matrix);
        br = br.matMul(matrix);
    }

    SymbolQuads quads;
    quads.emplace_back(tl, tr, bl, br, shapedIcon.image, 0, anchor, globalMinScale, std::numeric_limits<float>::infinity());
    return quads;
}
Beispiel #3
0
SymbolQuads getGlyphQuads(Anchor& anchor, const Shaping& shapedText,
        const float boxScale, const GeometryCoordinates& line, const SymbolLayoutProperties& layout,
        const bool alongLine, const GlyphPositions& face) {

    const float textRotate = layout.text.rotate * util::DEG2RAD;
    const bool keepUpright = layout.text.keepUpright;

    SymbolQuads quads;

    for (const PositionedGlyph &positionedGlyph: shapedText.positionedGlyphs) {
        auto face_it = face.find(positionedGlyph.glyph);
        if (face_it == face.end())
            continue;
        const Glyph &glyph = face_it->second;
        const Rect<uint16_t> &rect = glyph.rect;

        if (!glyph)
            continue;

        if (!rect.hasArea())
            continue;

        const float centerX = (positionedGlyph.x + glyph.metrics.advance / 2.0f) * boxScale;

        GlyphInstances glyphInstances;
        if (alongLine) {
            getSegmentGlyphs(std::back_inserter(glyphInstances), anchor, centerX, line, anchor.segment, true);
            if (keepUpright)
                getSegmentGlyphs(std::back_inserter(glyphInstances), anchor, centerX, line, anchor.segment, false);

        } else {
            glyphInstances.emplace_back(GlyphInstance{anchor});
        }

        // The rects have an addditional buffer that is not included in their size;
        const float glyphPadding = 1.0f;
        const float rectBuffer = 3.0f + glyphPadding;

        const float x1 = positionedGlyph.x + glyph.metrics.left - rectBuffer;
        const float y1 = positionedGlyph.y - glyph.metrics.top - rectBuffer;
        const float x2 = x1 + rect.w;
        const float y2 = y1 + rect.h;

        const vec2<float> otl{x1, y1};
        const vec2<float> otr{x2, y1};
        const vec2<float> obl{x1, y2};
        const vec2<float> obr{x2, y2};

        for (const GlyphInstance &instance : glyphInstances) {

            vec2<float> tl = otl;
            vec2<float> tr = otr;
            vec2<float> bl = obl;
            vec2<float> br = obr;
            const float angle = instance.angle + textRotate;

            if (angle) {
                // Compute the transformation matrix.
                float angle_sin = std::sin(angle);
                float angle_cos = std::cos(angle);
                std::array<float, 4> matrix = {{angle_cos, -angle_sin, angle_sin, angle_cos}};

                tl = tl.matMul(matrix);
                tr = tr.matMul(matrix);
                bl = bl.matMul(matrix);
                br = br.matMul(matrix);
            }

            // Prevent label from extending past the end of the line
            const float glyphMinScale = std::max(instance.minScale, anchor.scale);

            const float glyphAngle = std::fmod((anchor.angle + textRotate + instance.offset + 2 * M_PI), (2 * M_PI));
            quads.emplace_back(tl, tr, bl, br, rect, glyphAngle, instance.anchorPoint, glyphMinScale, instance.maxScale);

        }

    }

    return quads;
}
Beispiel #4
0
SymbolQuads getGlyphQuads(Anchor& anchor,
                          const Shaping& shapedText,
                          const float boxScale,
                          const GeometryCoordinates& line,
                          const SymbolLayoutProperties::Evaluated& layout,
                          const style::SymbolPlacementType placement,
                          const GlyphPositionMap& positions) {
    const float textRotate = layout.get<TextRotate>() * util::DEG2RAD;
    const bool keepUpright = layout.get<TextKeepUpright>();

    SymbolQuads quads;

    for (const PositionedGlyph &positionedGlyph: shapedText.positionedGlyphs) {
        auto positionsIt = positions.find(positionedGlyph.glyph);
        if (positionsIt == positions.end())
            continue;

        const GlyphPosition& glyph = positionsIt->second;
        const Rect<uint16_t>& rect = glyph.rect;
        const float centerX = (positionedGlyph.x + glyph.metrics.advance / 2.0f) * boxScale;

        GlyphInstances glyphInstances;
        if (placement == style::SymbolPlacementType::Line) {
            getLineGlyphs(std::back_inserter(glyphInstances), anchor, centerX, line, anchor.segment, false);
            if (keepUpright)
                getLineGlyphs(std::back_inserter(glyphInstances), anchor, centerX, line, anchor.segment, true);
        } else {
            glyphInstances.emplace_back(GlyphInstance{anchor.point});
        }

        // The rects have an addditional buffer that is not included in their size;
        const float glyphPadding = 1.0f;
        const float rectBuffer = 3.0f + glyphPadding;

        const float x1 = positionedGlyph.x + glyph.metrics.left - rectBuffer;
        const float y1 = positionedGlyph.y - glyph.metrics.top - rectBuffer;
        const float x2 = x1 + rect.w;
        const float y2 = y1 + rect.h;

        const Point<float> center{positionedGlyph.x, static_cast<float>(static_cast<float>(glyph.metrics.advance) / 2.0)};

        Point<float> otl{x1, y1};
        Point<float> otr{x2, y1};
        Point<float> obl{x1, y2};
        Point<float> obr{x2, y2};

        if (positionedGlyph.angle != 0) {
            otl = util::rotate(otl - center, positionedGlyph.angle) + center;
            otr = util::rotate(otr - center, positionedGlyph.angle) + center;
            obl = util::rotate(obl - center, positionedGlyph.angle) + center;
            obr = util::rotate(obr - center, positionedGlyph.angle) + center;
        }

        for (const GlyphInstance &instance : glyphInstances) {
            Point<float> tl = otl;
            Point<float> tr = otr;
            Point<float> bl = obl;
            Point<float> br = obr;

            if (textRotate) {
                // Compute the transformation matrix.
                float angle_sin = std::sin(textRotate);
                float angle_cos = std::cos(textRotate);
                std::array<float, 4> matrix = {{angle_cos, -angle_sin, angle_sin, angle_cos}};

                tl = util::matrixMultiply(matrix, tl);
                tr = util::matrixMultiply(matrix, tr);
                bl = util::matrixMultiply(matrix, bl);
                br = util::matrixMultiply(matrix, br);
            }

            // Prevent label from extending past the end of the line
            const float glyphMinScale = std::max(instance.minScale, anchor.scale);

            // All the glyphs for a label are tagged with either the "right side up" or "upside down" anchor angle,
            //  which is used at placement time to determine which set to show
            const float anchorAngle = std::fmod((anchor.angle + (instance.upsideDown ? M_PI : 0.0) + 2 * M_PI), (2 * M_PI));
            const float glyphAngle = std::fmod((instance.angle + (instance.upsideDown ? M_PI : 0.0) + 2 * M_PI), (2 * M_PI));
            quads.emplace_back(tl, tr, bl, br, rect, anchorAngle, glyphAngle, instance.anchorPoint, glyphMinScale, instance.maxScale, shapedText.writingMode);
        }
    }

    return quads;
}