From 3442403e6707be66ff133bd4690eb380dcc65dce Mon Sep 17 00:00:00 2001 From: Mike Morris Date: Fri, 30 May 2014 00:07:22 -0400 Subject: [PATCH] parse maxWidth, lineHeight and alignment, pass to FontStack::getShaping --- bin/style.js | 2 ++ include/llmr/style/bucket_description.hpp | 9 +++++++++ include/llmr/text/glyph_store.hpp | 9 ++++++++- include/llmr/text/placement.hpp | 2 -- src/map/tile_parser.cpp | 6 +++++- src/style/style_parser.cpp | 18 +++++++++++++++++ src/text/glyph_store.cpp | 14 ++++++++++++- src/text/placement.cpp | 24 ++++------------------- 8 files changed, 59 insertions(+), 25 deletions(-) diff --git a/bin/style.js b/bin/style.js index c831fd414..931bde011 100644 --- a/bin/style.js +++ b/bin/style.js @@ -765,6 +765,8 @@ module.exports = { "path": "horizontal", "font": "Open Sans Semibold, Arial Unicode MS Bold", "fontSize": 18, + "text-max-width": 2, + "text-line-height": 1.4, "feature_type": "point", "type": "text" }, diff --git a/include/llmr/style/bucket_description.hpp b/include/llmr/style/bucket_description.hpp index 3cdc8ea4d..004932aa4 100644 --- a/include/llmr/style/bucket_description.hpp +++ b/include/llmr/style/bucket_description.hpp @@ -68,6 +68,12 @@ inline TextPathType textPathType(const std::string& path) { else return TextPathType::Horizontal; }; +inline float alignmentType(const std::string& alignment) { + if (alignment == "right") return 1.0f; + else if (alignment == "left") return 0.0f; + else return 0.5; +}; + class BucketGeometryDescription { public: CapType cap = CapType::None; @@ -79,6 +85,9 @@ public: float miter_limit = 2.0f; float round_limit = 1.0f; TextPathType path = TextPathType::Horizontal; + float alignment = 0.5; + float line_height = 1.2 * 24; + float max_width = 15.0f * 24; float padding = 2.0f; float textMinDistance = 250.0f; float rotate = 0.0f; // what is this? diff --git a/include/llmr/text/glyph_store.hpp b/include/llmr/text/glyph_store.hpp index eb5d6038f..74472194b 100644 --- a/include/llmr/text/glyph_store.hpp +++ b/include/llmr/text/glyph_store.hpp @@ -30,7 +30,14 @@ public: void insert(uint32_t id, const SDFGlyph &glyph); const std::map &getMetrics() const; const std::map &getSDFs() const; - const Shaping getShaping(const std::u32string &string) const; + const Shaping getShaping(const std::u32string &string, + const float &maxWidth, + const float &lineHeight, + const float &alignment) const; + Shaping lineWrap(Shaping shaped, + const float &lineHeight, + const float &maxWidth, + const float &alignment) const; private: std::map bitmaps; diff --git a/include/llmr/text/placement.hpp b/include/llmr/text/placement.hpp index 87c47345e..fb3ddaa66 100644 --- a/include/llmr/text/placement.hpp +++ b/include/llmr/text/placement.hpp @@ -20,8 +20,6 @@ public: const BucketGeometryDescription &info, const GlyphPositions &face, const Shaping &shaping); - float measureText(const GlyphPositions &face, - const Shaping &shaping); private: const int8_t zoom; diff --git a/src/map/tile_parser.cpp b/src/map/tile_parser.cpp index ff5d61a5e..431300318 100644 --- a/src/map/tile_parser.cpp +++ b/src/map/tile_parser.cpp @@ -15,6 +15,8 @@ #include #include +#include + using namespace llmr; TileParser::TileParser(const std::string& data, VectorTileData& tile, const Style& style, GlyphAtlas& glyphAtlas, GlyphStore &glyphStore, SpriteAtlas &spriteAtlas) @@ -202,6 +204,8 @@ std::unique_ptr TileParser::createTextBucket(const VectorTileLayer& laye std::map shaping; GlyphPositions face; + // std::cerr << bucket_desc; + // Shape and place all labels. { FilteredVectorTileLayer filtered_layer(layer, bucket_desc); @@ -221,7 +225,7 @@ std::unique_ptr TileParser::createTextBucket(const VectorTileLayer& laye const std::u32string string = ucs4conv.convert(toString(it_prop->second)); // Shape labels. - const Shaping shaped = fontStack.getShaping(string); + const Shaping shaped = fontStack.getShaping(string, bucket_desc.geometry.max_width, bucket_desc.geometry.line_height, bucket_desc.geometry.alignment); shaping.emplace(toString(it_prop->second), shaped); // Place labels. diff --git a/src/style/style_parser.cpp b/src/style/style_parser.cpp index 6276d657d..ba189f76f 100644 --- a/src/style/style_parser.cpp +++ b/src/style/style_parser.cpp @@ -102,6 +102,24 @@ BucketDescription StyleParser::parseBucket(JSVal value) { } else { throw Style::exception("curve must be a string"); } + } else if (name == "alignment") { + if (value.IsString()) { + bucket.geometry.alignment = alignmentType({ value.GetString(), value.GetStringLength() }); + } else { + throw Style::exception("alignment must be a string"); + } + } else if (name == "lineHeight") { + if (value.IsNumber()) { + bucket.geometry.line_height = value.GetDouble() * 24; + } else { + throw Style::exception("line height must be a number"); + } + } else if (name == "maxWidth") { + if (value.IsNumber()) { + bucket.geometry.max_width = value.GetDouble() * 24; + } else { + throw Style::exception("max width must be a number"); + } } else if (name == "miterLimit") { if (value.IsNumber()) { bucket.geometry.miter_limit = value.GetDouble(); diff --git a/src/text/glyph_store.cpp b/src/text/glyph_store.cpp index 3f741236f..a148ac928 100644 --- a/src/text/glyph_store.cpp +++ b/src/text/glyph_store.cpp @@ -7,6 +7,7 @@ #include #include #include +#include namespace llmr { @@ -28,7 +29,7 @@ const std::map &FontStack::getSDFs() const { return sdfs; } -const Shaping FontStack::getShaping(const std::u32string &string) const { +const Shaping FontStack::getShaping(const std::u32string &string, const float &maxWidth, const float &lineHeight, const float &alignment) const { std::lock_guard lock(mtx); uint32_t i = 0; uint32_t x = 0; @@ -40,6 +41,17 @@ const Shaping FontStack::getShaping(const std::u32string &string) const { i++; x += metrics.find(chr)->second.advance; } + + shaped = lineWrap(shaped, lineHeight, maxWidth, alignment); + + return shaped; +} + +Shaping FontStack::lineWrap(Shaping shaped, const float &lineHeight, const float &maxWidth, const float &alignment) const { + std::cerr << "\nlineHeight: " << lineHeight << + "\nmaxWidth: " << maxWidth << + "\nalignment: " << alignment << + "\n"; return shaped; } diff --git a/src/text/placement.cpp b/src/text/placement.cpp index f57436bcb..ed71f881e 100644 --- a/src/text/placement.cpp +++ b/src/text/placement.cpp @@ -137,15 +137,12 @@ void getSegmentGlyphs(std::back_insert_iterator glyphs, } void getGlyphs(PlacedGlyphs &glyphs, GlyphBoxes &boxes, - Anchor &anchor, float advance, const Shaping &shaping, + Anchor &anchor, vec2 origin, const Shaping &shaping, const GlyphPositions &face, float fontScale, bool horizontal, const std::vector &line, float maxAngleDelta, float rotate) { // The total text advance is the width of this label. - // TODO: figure out correct ascender height. - vec2 origin{-advance / 2, -17}; - // TODO: allow setting an alignment // var alignment = 'center'; // if (alignment == 'center') { @@ -261,10 +258,10 @@ void Placement::addFeature(TextBucket& bucket, const float fontScale = (tileExtent / util::tileSize) / (glyphSize / info.size); - const float advance = measureText(face, shaping); Anchors anchors; - // fprintf(stderr, "adding feature with advance %f\n", advance); + // TODO: figure out correct ascender height. + vec2 origin{0, -17}; if (line.size() == 1) { // Point labels @@ -285,7 +282,7 @@ void Placement::addFeature(TextBucket& bucket, PlacedGlyphs glyphs; GlyphBoxes boxes; - getGlyphs(glyphs, boxes, anchor, advance, shaping, face, fontScale, horizontal, + getGlyphs(glyphs, boxes, anchor, origin, shaping, face, fontScale, horizontal, line, maxAngleDelta, rotate); PlacementProperty place = collision.place(boxes, anchor, anchor.scale, maxPlacementScale, @@ -295,16 +292,3 @@ void Placement::addFeature(TextBucket& bucket, } } } - -float Placement::measureText(const GlyphPositions &face, - const Shaping &shaping) { - float advance = 0; - - // TODO: advance is not calculated correctly. we should instead use the - // bounding box of the glyph placement. - for (const GlyphPlacement &shape : shaping) { - advance += getGlyph(shape, face).metrics.advance; - } - - return advance; -}