Merge branch 'master' into label-styles-line-break

This commit is contained in:
Nicki Dlugash
2014-05-30 15:40:40 -04:00
5 changed files with 80 additions and 72 deletions

View File

@@ -266,7 +266,7 @@ module.exports = {
"field": "index",
"value": 10,
"path": "curve",
"text_field": "ele",
"text_field": "{{ele}}m",
"font": "Open Sans Regular, Arial Unicode MS Regular",
"fontSize": 10,
"feature_type": "line",
@@ -647,7 +647,7 @@ module.exports = {
"country_label": {
"source": "outdoors",
"layer": "country_label",
"text_field": "name",
"text_field": "{{name}}",
"path": "horizontal",
"font": "Open Sans Bold, Arial Unicode MS Bold",
"fontSize": 24,
@@ -664,7 +664,7 @@ module.exports = {
"layer": "marine_label",
"feature_type": "line",
"type": "text",
"text_field": "name",
"text_field": "{{name}}",
"path": "curve",
"font": "Open Sans Italic, Arial Unicode MS Regular",
"fontSize": 16
@@ -674,7 +674,7 @@ module.exports = {
"layer": "marine_label",
"feature_type": "point",
"type": "text",
"text_field": "name",
"text_field": "{{name}}",
"path": "horizontal",
"field": "labelrank",
"value": 1,
@@ -686,7 +686,7 @@ module.exports = {
"layer": "marine_label",
"feature_type": "point",
"type": "text",
"text_field": "name",
"text_field": "{{name}}",
"path": "horizontal",
"field": "labelrank",
"value": 2,
@@ -698,7 +698,7 @@ module.exports = {
"layer": "marine_label",
"feature_type": "point",
"type": "text",
"text_field": "name",
"text_field": "{{name}}",
"path": "horizontal",
"field": "labelrank",
"value": [3,4,5,6],
@@ -708,7 +708,7 @@ module.exports = {
"state_label": {
"source": "outdoors",
"layer": "state_label",
"text_field": "name",
"text_field": "{{name}}",
"path": "horizontal",
"font": "Open Sans Regular, Arial Unicode MS Regular",
"fontSize": 16,
@@ -721,7 +721,7 @@ module.exports = {
"layer": "place_label",
"field": "type",
"value": "city",
"text_field": "name",
"text_field": "{{name}}",
"path": "horizontal",
"font": "Open Sans Semibold, Arial Unicode MS Bold",
"fontSize": 20,
@@ -733,7 +733,7 @@ module.exports = {
"layer": "place_label",
"field": "type",
"value": "town",
"text_field": "name",
"text_field": "{{name}}",
"path": "horizontal",
"font": "Open Sans Semibold, Arial Unicode MS Bold",
"fontSize": 24,
@@ -745,7 +745,7 @@ module.exports = {
"layer": "place_label",
"field": "type",
"value": "village",
"text_field": "name",
"text_field": "{{name}}",
"path": "horizontal",
"font": "Open Sans Semibold, Arial Unicode MS Bold",
"fontSize": 22,
@@ -761,7 +761,7 @@ module.exports = {
"suburb",
"neighbourhood"
],
"text_field": "name",
"text_field": "{{name}}",
"path": "horizontal",
"font": "Open Sans Semibold, Arial Unicode MS Bold",
"fontSize": 18,
@@ -774,7 +774,7 @@ module.exports = {
"layer": "road_label",
"field": "class",
"value": ["motorway","main"],
"text_field": "name",
"text_field": "{{name}}",
"path": "curve",
"padding": 2,
"font": "Open Sans Regular, Arial Unicode MS Regular",
@@ -788,7 +788,7 @@ module.exports = {
"layer": "road_label",
"field": "class",
"value": ["street","street_limited"],
"text_field": "name",
"text_field": "{{name}}",
"path": "curve",
"padding": 2,
"font": "Open Sans Regular, Arial Unicode MS Regular",
@@ -802,7 +802,7 @@ module.exports = {
"layer": "road_label",
"field": "class",
"value": ["service","driveway","path"],
"text_field": "name",
"text_field": "{{name}}",
"path": "curve",
"padding": 2,
"font": "Open Sans Regular, Arial Unicode MS Regular",
@@ -814,7 +814,7 @@ module.exports = {
"water_label": {
"source": "outdoors",
"layer": "water_label",
"text_field": "name",
"text_field": "{{name}}",
"path": "horizontal",
"font": "Open Sans Semibold Italic, Arial Unicode MS Bold",
"fontSize": 12,
@@ -824,7 +824,7 @@ module.exports = {
"waterway_label": {
"source": "outdoors",
"layer": "waterway_label",
"text_field": "name",
"text_field": "{{name}}",
"path": "curve",
"font": "Open Sans Semibold Italic, Arial Unicode MS Bold",
"fontSize": 12,
@@ -876,7 +876,7 @@ module.exports = {
1,
2
],
"text_field": "name",
"text_field": "{{name}}",
"path": "horizontal",
"padding": 2,
"maxWidth": 8,
@@ -892,7 +892,7 @@ module.exports = {
"layer": "poi_label",
"field": "scalerank",
"value": 3,
"text_field": "name",
"text_field": "{{name}}",
"path": "horizontal",
"padding": 2,
"maxWidth": 8,
@@ -908,7 +908,7 @@ module.exports = {
"layer": "poi_label",
"field": "scalerank",
"value": 4,
"text_field": "name",
"text_field": "{{name}}",
"path": "horizontal",
"padding": 2,
"maxWidth": 8,

View File

@@ -14,10 +14,10 @@
'cflags_cc': ['-std=c++11', '-Wall', '-Wextra'],
'configurations': {
'Debug': {
'cflags_cc': [ '-g', '-O1', '-fno-omit-frame-pointer','-fwrapv', '-fstack-protector-all', '-fno-common' ],
'cflags_cc': [ '-g', '-O0', '-fno-omit-frame-pointer','-fwrapv', '-fstack-protector-all', '-fno-common' ],
'defines': [ 'DEBUG' ],
'xcode_settings': {
'GCC_OPTIMIZATION_LEVEL': '1',
'GCC_OPTIMIZATION_LEVEL': '0',
'GCC_GENERATE_DEBUGGING_SYMBOLS': 'YES',
'DEAD_CODE_STRIPPING': 'NO',
'GCC_INLINES_ARE_PRIVATE_EXTERN': 'NO',

View File

@@ -36,7 +36,7 @@ public:
const float &alignment,
const float &verticalAlignment,
const float &letterSpacing) const;
Shaping lineWrap(Shaping &shaping,
void lineWrap(Shaping &shaping,
const float &lineHeight,
const float &maxWidth,
const float &alignment,

View File

@@ -16,6 +16,8 @@
#include <llmr/util/std.hpp>
#include <llmr/util/utf.hpp>
#include <regex>
using namespace llmr;
TileParser::TileParser(const std::string &data, VectorTileData &tile,
@@ -182,6 +184,11 @@ std::unique_ptr<Bucket> TileParser::createTextBucket(const VectorTileLayer &laye
tile.textVertexBuffer, tile.triangleElementsBuffer, bucket_desc, placement);
util::utf8_to_utf32 ucs4conv;
std::regex token_regex("\\{\\{(\\w+)\\}\\}");
const auto tokens_end = std::sregex_token_iterator();
std::vector<std::pair<std::u32string, pbf>> labels;
// Determine and load glyph ranges
{
@@ -193,23 +200,41 @@ std::unique_ptr<Bucket> TileParser::createTextBucket(const VectorTileLayer &laye
return nullptr;
VectorTileFeature feature{feature_pbf, layer};
auto it_prop = feature.properties.find(bucket_desc.geometry.field);
if (it_prop == feature.properties.end()) {
// feature does not have the correct property
if (debug::labelTextMissingWarning) {
fprintf(stderr,
"[WARNING] feature doesn't have property '%s' required for labelling\n",
bucket_desc.geometry.field.c_str());
const std::string &field = bucket_desc.geometry.field;
std::string source_string;
source_string.reserve(field.size());
bool token = false;
for (auto token_it = std::sregex_token_iterator(field.begin(), field.end(), token_regex, {-1, 1}); token_it != tokens_end; ++token_it, token = !token) {
if (!token_it->matched) {
continue;
}
if (token) {
auto it_prop = feature.properties.find(token_it->str());
if (it_prop == feature.properties.end()) {
// feature does not have the correct property
if (debug::labelTextMissingWarning) {
fprintf(stderr,
"[WARNING] feature doesn't have property '%s' required for labelling\n",
token_it->str().c_str());
}
continue;
}
source_string += toString(it_prop->second);
} else {
source_string += token_it->str();
}
continue;
}
const std::u32string string = ucs4conv.convert(toString(it_prop->second));
const std::u32string string = ucs4conv.convert(source_string);
// Loop through all characters of this text and collect unique codepoints.
for (uint32_t chr : string) {
ranges.insert(getGlyphRange(chr));
}
labels.emplace_back(string, feature.geometry);
}
glyphStore->waitForGlyphRanges(bucket_desc.geometry.font, ranges);
@@ -220,38 +245,18 @@ std::unique_ptr<Bucket> TileParser::createTextBucket(const VectorTileLayer &laye
GlyphPositions face;
// Shape and place all labels.
{
FilteredVectorTileLayer filtered_layer(layer, bucket_desc);
for (const pbf &feature_pbf : filtered_layer) {
if (obsolete())
return nullptr;
VectorTileFeature feature{feature_pbf, layer};
for (const std::pair<std::u32string, pbf> &label : labels) {
auto it_prop = feature.properties.find(bucket_desc.geometry.field);
if (it_prop == feature.properties.end()) {
// feature does not have the correct property
if (debug::labelTextMissingWarning) {
fprintf(stderr,
"[WARNING] feature doesn't have property '%s' required for labelling\n",
bucket_desc.geometry.field.c_str());
}
continue;
}
// Shape labels.
const Shaping shaping = fontStack.getShaping(label.first, bucket_desc.geometry.max_width,
bucket_desc.geometry.line_height, bucket_desc.geometry.alignment,
bucket_desc.geometry.vertical_alignment, bucket_desc.geometry.letter_spacing);
const std::string source_string = toString(it_prop->second);
const std::u32string string = ucs4conv.convert(source_string);
// Place labels.
addGlyph(tile.id.to_uint64(), bucket_desc.geometry.font, label.first, fontStack, *glyphAtlas,
face);
// Shape labels.
const Shaping shaping = fontStack.getShaping(string, bucket_desc.geometry.max_width,
bucket_desc.geometry.line_height, bucket_desc.geometry.alignment,
bucket_desc.geometry.vertical_alignment, bucket_desc.geometry.letter_spacing);
// Place labels.
addGlyph(tile.id.to_uint64(), bucket_desc.geometry.font, string, fontStack, *glyphAtlas,
face);
bucket->addFeature(feature.geometry, face, shaping);
}
bucket->addFeature(label.second, face, shaping);
}
return std::move(bucket);

View File

@@ -38,8 +38,7 @@ const Shaping FontStack::getShaping(const std::u32string &string, const float &m
Shaping shaping;
// Loop through all characters of this label and shape.
for (uint32_t chr : string) {
GlyphPlacement glyph = GlyphPlacement(0, chr, x, 0);
shaping.push_back(glyph);
shaping.emplace_back(0, chr, x, 0);
i++;
x += metrics.find(chr)->second.advance + letterSpacing;
}
@@ -58,18 +57,24 @@ void alignVertically(Shaping &shaping, const uint32_t &lines, const float &lineH
void alignHorizontally(Shaping &shaping, const std::map<uint32_t, GlyphMetrics> &metrics,
const uint32_t &start, const uint32_t &end, const float &alignment) {
uint32_t lastAdvance = metrics.find(shaping[end].glyph)->second.advance;
int32_t lineIndent = (shaping[end].x + lastAdvance) * alignment;
for (uint32_t j = start; j <= end; j++) {
shaping[j].x -= lineIndent;
auto & shape = shaping.at(end);
auto metric = metrics.find(shape.glyph);
if (metric != metrics.end()) {
uint32_t lastAdvance = metric->second.advance;
int32_t lineIndent = (shape.x + lastAdvance) * alignment;
for (uint32_t j = start; j <= end; j++) {
shaping[j].x -= lineIndent;
}
}
}
Shaping FontStack::lineWrap(Shaping &shaping, const float &lineHeight, const float &maxWidth,
void FontStack::lineWrap(Shaping &shaping, const float &lineHeight, const float &maxWidth,
const float &alignment, const float &verticalAlignment) const {
std::size_t num_shapes = shaping.size();
if (!num_shapes) {
return;
}
uint32_t lastSafeBreak = 0;
uint32_t lengthBeforeCurrentLine = 0;
uint32_t lineStartIndex = 0;
@@ -77,11 +82,10 @@ Shaping FontStack::lineWrap(Shaping &shaping, const float &lineHeight, const flo
for (uint32_t i = 0; i < shaping.size(); i++) {
GlyphPlacement &shape = shaping[i];
shape.x -= lengthBeforeCurrentLine;
shape.y += lineHeight * line;
if (shape.x > maxWidth && lastSafeBreak != 0) {
if (shape.x > maxWidth && lastSafeBreak > 0) {
uint32_t lineLength = shaping[lastSafeBreak + 1].x;
@@ -103,7 +107,6 @@ Shaping FontStack::lineWrap(Shaping &shaping, const float &lineHeight, const flo
lastSafeBreak = i;
}
}
alignHorizontally(shaping, metrics, lineStartIndex, shaping.size() - 1, alignment);
alignVertically(shaping, line + 1, lineHeight, verticalAlignment);
}