Add textFitWidth and textFitHeight Properties to Sprites (#2780)
Co-authored-by: Xiaolian Qin <xiaoq@microsoft.com>
@@ -14,6 +14,12 @@ namespace style {
|
|||||||
using ImageStretch = std::pair<float, float>;
|
using ImageStretch = std::pair<float, float>;
|
||||||
using ImageStretches = std::vector<ImageStretch>;
|
using ImageStretches = std::vector<ImageStretch>;
|
||||||
|
|
||||||
|
enum class TextFit {
|
||||||
|
stretchOrShrink,
|
||||||
|
stretchOnly,
|
||||||
|
proportional
|
||||||
|
};
|
||||||
|
|
||||||
class ImageContent {
|
class ImageContent {
|
||||||
public:
|
public:
|
||||||
float left;
|
float left;
|
||||||
@@ -34,15 +40,26 @@ public:
|
|||||||
bool sdf,
|
bool sdf,
|
||||||
ImageStretches stretchX = {},
|
ImageStretches stretchX = {},
|
||||||
ImageStretches stretchY = {},
|
ImageStretches stretchY = {},
|
||||||
const std::optional<ImageContent>& content = std::nullopt);
|
const std::optional<ImageContent>& content = std::nullopt,
|
||||||
|
const std::optional<TextFit>& textFitWidth = std::nullopt,
|
||||||
|
const std::optional<TextFit>& textFitHeight = std::nullopt);
|
||||||
Image(std::string id,
|
Image(std::string id,
|
||||||
PremultipliedImage&& image,
|
PremultipliedImage&& image,
|
||||||
float pixelRatio,
|
float pixelRatio,
|
||||||
ImageStretches stretchX = {},
|
ImageStretches stretchX = {},
|
||||||
ImageStretches stretchY = {},
|
ImageStretches stretchY = {},
|
||||||
const std::optional<ImageContent>& content = std::nullopt)
|
const std::optional<ImageContent>& content = std::nullopt,
|
||||||
: Image(std::move(id), std::move(image), pixelRatio, false, std::move(stretchX), std::move(stretchY), content) {
|
const std::optional<TextFit>& textFitWidth = std::nullopt,
|
||||||
}
|
const std::optional<TextFit>& textFitHeight = std::nullopt)
|
||||||
|
: Image(std::move(id),
|
||||||
|
std::move(image),
|
||||||
|
pixelRatio,
|
||||||
|
false,
|
||||||
|
std::move(stretchX),
|
||||||
|
std::move(stretchY),
|
||||||
|
content,
|
||||||
|
textFitWidth,
|
||||||
|
textFitHeight) {}
|
||||||
Image(const Image&);
|
Image(const Image&);
|
||||||
|
|
||||||
std::string getID() const;
|
std::string getID() const;
|
||||||
@@ -63,6 +80,12 @@ public:
|
|||||||
/// The space where text can be fit into this image.
|
/// The space where text can be fit into this image.
|
||||||
const std::optional<ImageContent>& getContent() const;
|
const std::optional<ImageContent>& getContent() const;
|
||||||
|
|
||||||
|
/// The constraints on the horizontal scaling of the image when `icon-text-fit` is used
|
||||||
|
const std::optional<TextFit>& getTextFitWidth() const;
|
||||||
|
|
||||||
|
/// The constraints on the vertical scaling of the image when `icon-text-fit` is used
|
||||||
|
const std::optional<TextFit>& getTextFitHeight() const;
|
||||||
|
|
||||||
class Impl;
|
class Impl;
|
||||||
Immutable<Impl> baseImpl;
|
Immutable<Impl> baseImpl;
|
||||||
explicit Image(Immutable<Impl> baseImpl_)
|
explicit Image(Immutable<Impl> baseImpl_)
|
||||||
|
|||||||
@@ -85,6 +85,7 @@
|
|||||||
"render-tests/fill-pattern/update-feature-state": "https://github.com/mapbox/mapbox-gl-native/issues/15895",
|
"render-tests/fill-pattern/update-feature-state": "https://github.com/mapbox/mapbox-gl-native/issues/15895",
|
||||||
"render-tests/geojson/inline-linestring-fill": "current behavior is arbitrary",
|
"render-tests/geojson/inline-linestring-fill": "current behavior is arbitrary",
|
||||||
"render-tests/icon-text-fit/text-variable-anchor-overlap": "https://github.com/mapbox/mapbox-gl-native/issues/15809",
|
"render-tests/icon-text-fit/text-variable-anchor-overlap": "https://github.com/mapbox/mapbox-gl-native/issues/15809",
|
||||||
|
"render-tests/icon-text-fit/textFit-grid-long": "Needs to be investigated and fixed.",
|
||||||
"render-tests/mixed-zoom/z10-z11": "https://github.com/mapbox/mapbox-gl-native/issues/10397",
|
"render-tests/mixed-zoom/z10-z11": "https://github.com/mapbox/mapbox-gl-native/issues/10397",
|
||||||
"render-tests/raster-masking/overlapping-zoom": "https://github.com/mapbox/mapbox-gl-native/issues/10195",
|
"render-tests/raster-masking/overlapping-zoom": "https://github.com/mapbox/mapbox-gl-native/issues/10195",
|
||||||
"render-tests/real-world/bangkok": "https://github.com/mapbox/mapbox-gl-native/issues/10412",
|
"render-tests/real-world/bangkok": "https://github.com/mapbox/mapbox-gl-native/issues/10412",
|
||||||
|
|||||||
85
metrics/integration/geojson/grid-tall.json
Normal file
@@ -0,0 +1,85 @@
|
|||||||
|
{
|
||||||
|
"type": "FeatureCollection",
|
||||||
|
"features": [{
|
||||||
|
"type": "Feature",
|
||||||
|
"properties": {
|
||||||
|
"cell": "top-left"
|
||||||
|
},
|
||||||
|
"geometry": {
|
||||||
|
"type": "Point",
|
||||||
|
"coordinates": [ -70, 60 ]
|
||||||
|
}
|
||||||
|
}, {
|
||||||
|
"type": "Feature",
|
||||||
|
"properties": {
|
||||||
|
"cell": "top-middle"
|
||||||
|
},
|
||||||
|
"geometry": {
|
||||||
|
"type": "Point",
|
||||||
|
"coordinates": [ 0, 60 ]
|
||||||
|
}
|
||||||
|
}, {
|
||||||
|
"type": "Feature",
|
||||||
|
"properties": {
|
||||||
|
"cell": "top-right"
|
||||||
|
},
|
||||||
|
"geometry": {
|
||||||
|
"type": "Point",
|
||||||
|
"coordinates": [ 70, 60 ]
|
||||||
|
}
|
||||||
|
}, {
|
||||||
|
"type": "Feature",
|
||||||
|
"properties": {
|
||||||
|
"cell": "middle-left"
|
||||||
|
},
|
||||||
|
"geometry": {
|
||||||
|
"type": "Point",
|
||||||
|
"coordinates": [ -70, 0 ]
|
||||||
|
}
|
||||||
|
}, {
|
||||||
|
"type": "Feature",
|
||||||
|
"properties": {
|
||||||
|
"cell": "middle-middle"
|
||||||
|
},
|
||||||
|
"geometry": {
|
||||||
|
"type": "Point",
|
||||||
|
"coordinates": [ 0, 0 ]
|
||||||
|
}
|
||||||
|
}, {
|
||||||
|
"type": "Feature",
|
||||||
|
"properties": {
|
||||||
|
"cell": "middle-right"
|
||||||
|
},
|
||||||
|
"geometry": {
|
||||||
|
"type": "Point",
|
||||||
|
"coordinates": [ 70, 0 ]
|
||||||
|
}
|
||||||
|
}, {
|
||||||
|
"type": "Feature",
|
||||||
|
"properties": {
|
||||||
|
"cell": "bottom-left"
|
||||||
|
},
|
||||||
|
"geometry": {
|
||||||
|
"type": "Point",
|
||||||
|
"coordinates": [ -70, -60 ]
|
||||||
|
}
|
||||||
|
}, {
|
||||||
|
"type": "Feature",
|
||||||
|
"properties": {
|
||||||
|
"cell": "bottom-middle"
|
||||||
|
},
|
||||||
|
"geometry": {
|
||||||
|
"type": "Point",
|
||||||
|
"coordinates": [ 0, -60 ]
|
||||||
|
}
|
||||||
|
}, {
|
||||||
|
"type": "Feature",
|
||||||
|
"properties": {
|
||||||
|
"cell": "bottom-right"
|
||||||
|
},
|
||||||
|
"geometry": {
|
||||||
|
"type": "Point",
|
||||||
|
"coordinates": [ 70, -60 ]
|
||||||
|
}
|
||||||
|
}]
|
||||||
|
}
|
||||||
85
metrics/integration/geojson/grid.json
Normal file
@@ -0,0 +1,85 @@
|
|||||||
|
{
|
||||||
|
"type": "FeatureCollection",
|
||||||
|
"features": [{
|
||||||
|
"type": "Feature",
|
||||||
|
"properties": {
|
||||||
|
"cell": "top-left"
|
||||||
|
},
|
||||||
|
"geometry": {
|
||||||
|
"type": "Point",
|
||||||
|
"coordinates": [ -70, 35 ]
|
||||||
|
}
|
||||||
|
}, {
|
||||||
|
"type": "Feature",
|
||||||
|
"properties": {
|
||||||
|
"cell": "top-middle"
|
||||||
|
},
|
||||||
|
"geometry": {
|
||||||
|
"type": "Point",
|
||||||
|
"coordinates": [ 0, 35 ]
|
||||||
|
}
|
||||||
|
}, {
|
||||||
|
"type": "Feature",
|
||||||
|
"properties": {
|
||||||
|
"cell": "top-right"
|
||||||
|
},
|
||||||
|
"geometry": {
|
||||||
|
"type": "Point",
|
||||||
|
"coordinates": [ 70, 35 ]
|
||||||
|
}
|
||||||
|
}, {
|
||||||
|
"type": "Feature",
|
||||||
|
"properties": {
|
||||||
|
"cell": "middle-left"
|
||||||
|
},
|
||||||
|
"geometry": {
|
||||||
|
"type": "Point",
|
||||||
|
"coordinates": [ -70, 0 ]
|
||||||
|
}
|
||||||
|
}, {
|
||||||
|
"type": "Feature",
|
||||||
|
"properties": {
|
||||||
|
"cell": "middle-middle"
|
||||||
|
},
|
||||||
|
"geometry": {
|
||||||
|
"type": "Point",
|
||||||
|
"coordinates": [ 0, 0 ]
|
||||||
|
}
|
||||||
|
}, {
|
||||||
|
"type": "Feature",
|
||||||
|
"properties": {
|
||||||
|
"cell": "middle-right"
|
||||||
|
},
|
||||||
|
"geometry": {
|
||||||
|
"type": "Point",
|
||||||
|
"coordinates": [ 70, 0 ]
|
||||||
|
}
|
||||||
|
}, {
|
||||||
|
"type": "Feature",
|
||||||
|
"properties": {
|
||||||
|
"cell": "bottom-left"
|
||||||
|
},
|
||||||
|
"geometry": {
|
||||||
|
"type": "Point",
|
||||||
|
"coordinates": [ -70, -35 ]
|
||||||
|
}
|
||||||
|
}, {
|
||||||
|
"type": "Feature",
|
||||||
|
"properties": {
|
||||||
|
"cell": "bottom-middle"
|
||||||
|
},
|
||||||
|
"geometry": {
|
||||||
|
"type": "Point",
|
||||||
|
"coordinates": [ 0, -35 ]
|
||||||
|
}
|
||||||
|
}, {
|
||||||
|
"type": "Feature",
|
||||||
|
"properties": {
|
||||||
|
"cell": "bottom-right"
|
||||||
|
},
|
||||||
|
"geometry": {
|
||||||
|
"type": "Point",
|
||||||
|
"coordinates": [ 70, -35 ]
|
||||||
|
}
|
||||||
|
}]
|
||||||
|
}
|
||||||
|
After Width: | Height: | Size: 22 KiB |
@@ -0,0 +1,193 @@
|
|||||||
|
{
|
||||||
|
"version": 8,
|
||||||
|
"metadata": {
|
||||||
|
"test": {
|
||||||
|
"width": 200,
|
||||||
|
"height": 150,
|
||||||
|
"description": "This an adaptation of stretch-nine-part-content but with a long enough text content to stretch beyond aspect ratio."
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"sources": {
|
||||||
|
"geojson": {
|
||||||
|
"type": "geojson",
|
||||||
|
"data": "local://geojson/anchors.json"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"sprite": "local://sprites/stretch",
|
||||||
|
"glyphs": "local://glyphs/{fontstack}/{range}.pbf",
|
||||||
|
"layers": [
|
||||||
|
{
|
||||||
|
"id": "anchor-center",
|
||||||
|
"type": "symbol",
|
||||||
|
"source": "geojson",
|
||||||
|
"filter": ["==", "anchor", "center"],
|
||||||
|
"layout": {
|
||||||
|
"text-field": "123456",
|
||||||
|
"text-size": 20,
|
||||||
|
"text-anchor": "center",
|
||||||
|
"text-font": [ "Open Sans Semibold", "Arial Unicode MS Bold" ],
|
||||||
|
"text-allow-overlap": true,
|
||||||
|
"text-ignore-placement": true,
|
||||||
|
"icon-image": "nine-part-textfit-wh-stretchOnly-proportional",
|
||||||
|
"icon-text-fit": "both",
|
||||||
|
"icon-allow-overlap": true,
|
||||||
|
"icon-ignore-placement": true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "anchor-left",
|
||||||
|
"type": "symbol",
|
||||||
|
"source": "geojson",
|
||||||
|
"filter": ["==", "anchor", "left"],
|
||||||
|
"layout": {
|
||||||
|
"text-field": "123456",
|
||||||
|
"text-size": 20,
|
||||||
|
"text-anchor": "left",
|
||||||
|
"text-font": [ "Open Sans Semibold", "Arial Unicode MS Bold" ],
|
||||||
|
"text-allow-overlap": true,
|
||||||
|
"text-ignore-placement": true,
|
||||||
|
"icon-image": "nine-part-textfit-wh-stretchOnly-proportional",
|
||||||
|
"icon-text-fit": "both",
|
||||||
|
"icon-allow-overlap": true,
|
||||||
|
"icon-ignore-placement": true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "anchor-top-left",
|
||||||
|
"type": "symbol",
|
||||||
|
"source": "geojson",
|
||||||
|
"filter": ["==", "anchor", "top-left"],
|
||||||
|
"layout": {
|
||||||
|
"text-field": "123456",
|
||||||
|
"text-size": 20,
|
||||||
|
"text-anchor": "top-left",
|
||||||
|
"text-font": [ "Open Sans Semibold", "Arial Unicode MS Bold" ],
|
||||||
|
"text-allow-overlap": true,
|
||||||
|
"text-ignore-placement": true,
|
||||||
|
"icon-image": "nine-part-textfit-wh-stretchOnly-proportional",
|
||||||
|
"icon-text-fit": "both",
|
||||||
|
"icon-allow-overlap": true,
|
||||||
|
"icon-ignore-placement": true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "anchor-top",
|
||||||
|
"type": "symbol",
|
||||||
|
"source": "geojson",
|
||||||
|
"filter": ["==", "anchor", "top"],
|
||||||
|
"layout": {
|
||||||
|
"text-field": "123456",
|
||||||
|
"text-size": 20,
|
||||||
|
"text-anchor": "top",
|
||||||
|
"text-font": [ "Open Sans Semibold", "Arial Unicode MS Bold" ],
|
||||||
|
"text-allow-overlap": true,
|
||||||
|
"text-ignore-placement": true,
|
||||||
|
"icon-image": "nine-part-textfit-wh-stretchOnly-proportional",
|
||||||
|
"icon-text-fit": "both",
|
||||||
|
"icon-allow-overlap": true,
|
||||||
|
"icon-ignore-placement": true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "anchor-top-right",
|
||||||
|
"type": "symbol",
|
||||||
|
"source": "geojson",
|
||||||
|
"filter": ["==", "anchor", "top-right"],
|
||||||
|
"layout": {
|
||||||
|
"text-field": "123456",
|
||||||
|
"text-size": 20,
|
||||||
|
"text-anchor": "top-right",
|
||||||
|
"text-font": [ "Open Sans Semibold", "Arial Unicode MS Bold" ],
|
||||||
|
"text-allow-overlap": true,
|
||||||
|
"text-ignore-placement": true,
|
||||||
|
"icon-image": "nine-part-textfit-wh-stretchOnly-proportional",
|
||||||
|
"icon-text-fit": "both",
|
||||||
|
"icon-allow-overlap": true,
|
||||||
|
"icon-ignore-placement": true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "anchor-right",
|
||||||
|
"type": "symbol",
|
||||||
|
"source": "geojson",
|
||||||
|
"filter": ["==", "anchor", "right"],
|
||||||
|
"layout": {
|
||||||
|
"text-field": "123456",
|
||||||
|
"text-size": 20,
|
||||||
|
"text-anchor": "right",
|
||||||
|
"text-font": [ "Open Sans Semibold", "Arial Unicode MS Bold" ],
|
||||||
|
"text-allow-overlap": true,
|
||||||
|
"text-ignore-placement": true,
|
||||||
|
"icon-image": "nine-part-textfit-wh-stretchOnly-proportional",
|
||||||
|
"icon-text-fit": "both",
|
||||||
|
"icon-allow-overlap": true,
|
||||||
|
"icon-ignore-placement": true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "anchor-bottom-left",
|
||||||
|
"type": "symbol",
|
||||||
|
"source": "geojson",
|
||||||
|
"filter": ["==", "anchor", "bottom-left"],
|
||||||
|
"layout": {
|
||||||
|
"text-field": "123456",
|
||||||
|
"text-size": 20,
|
||||||
|
"text-anchor": "bottom-left",
|
||||||
|
"text-font": [ "Open Sans Semibold", "Arial Unicode MS Bold" ],
|
||||||
|
"text-allow-overlap": true,
|
||||||
|
"text-ignore-placement": true,
|
||||||
|
"icon-image": "nine-part-textfit-wh-stretchOnly-proportional",
|
||||||
|
"icon-text-fit": "both",
|
||||||
|
"icon-allow-overlap": true,
|
||||||
|
"icon-ignore-placement": true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "anchor-bottom",
|
||||||
|
"type": "symbol",
|
||||||
|
"source": "geojson",
|
||||||
|
"filter": ["==", "anchor", "bottom"],
|
||||||
|
"layout": {
|
||||||
|
"text-field": "123456",
|
||||||
|
"text-size": 20,
|
||||||
|
"text-anchor": "bottom",
|
||||||
|
"text-font": [ "Open Sans Semibold", "Arial Unicode MS Bold" ],
|
||||||
|
"text-allow-overlap": true,
|
||||||
|
"text-ignore-placement": true,
|
||||||
|
"icon-image": "nine-part-textfit-wh-stretchOnly-proportional",
|
||||||
|
"icon-text-fit": "both",
|
||||||
|
"icon-allow-overlap": true,
|
||||||
|
"icon-ignore-placement": true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "anchor-bottom-right",
|
||||||
|
"type": "symbol",
|
||||||
|
"source": "geojson",
|
||||||
|
"filter": ["==", "anchor", "bottom-right"],
|
||||||
|
"layout": {
|
||||||
|
"text-field": "123456",
|
||||||
|
"text-size": 20,
|
||||||
|
"text-anchor": "bottom-right",
|
||||||
|
"text-font": [ "Open Sans Semibold", "Arial Unicode MS Bold" ],
|
||||||
|
"text-allow-overlap": true,
|
||||||
|
"text-ignore-placement": true,
|
||||||
|
"icon-image": "nine-part-textfit-wh-stretchOnly-proportional",
|
||||||
|
"icon-text-fit": "both",
|
||||||
|
"icon-allow-overlap": true,
|
||||||
|
"icon-ignore-placement": true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "anchors",
|
||||||
|
"type": "circle",
|
||||||
|
"source": "geojson",
|
||||||
|
"paint": {
|
||||||
|
"circle-radius": 2,
|
||||||
|
"circle-color": "green",
|
||||||
|
"circle-stroke-color": "white",
|
||||||
|
"circle-stroke-width": 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
After Width: | Height: | Size: 4.5 KiB |
@@ -0,0 +1,193 @@
|
|||||||
|
{
|
||||||
|
"version": 8,
|
||||||
|
"metadata": {
|
||||||
|
"test": {
|
||||||
|
"width": 200,
|
||||||
|
"height": 150,
|
||||||
|
"description": "This an adaptation of stretch-nine-part-content but with '1' as the text and textFitWidth=stretchOnly and textFitHeight=proportional. Because of this, the aspect ratio of the content won't get more narrow than the starting content aspect ratio."
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"sources": {
|
||||||
|
"geojson": {
|
||||||
|
"type": "geojson",
|
||||||
|
"data": "local://geojson/anchors.json"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"sprite": "local://sprites/stretch",
|
||||||
|
"glyphs": "local://glyphs/{fontstack}/{range}.pbf",
|
||||||
|
"layers": [
|
||||||
|
{
|
||||||
|
"id": "anchor-center",
|
||||||
|
"type": "symbol",
|
||||||
|
"source": "geojson",
|
||||||
|
"filter": ["==", "anchor", "center"],
|
||||||
|
"layout": {
|
||||||
|
"text-field": "1",
|
||||||
|
"text-size": 20,
|
||||||
|
"text-anchor": "center",
|
||||||
|
"text-font": [ "Open Sans Semibold", "Arial Unicode MS Bold" ],
|
||||||
|
"text-allow-overlap": true,
|
||||||
|
"text-ignore-placement": true,
|
||||||
|
"icon-image": "nine-part-textfit-wh-stretchOnly-proportional",
|
||||||
|
"icon-text-fit": "both",
|
||||||
|
"icon-allow-overlap": true,
|
||||||
|
"icon-ignore-placement": true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "anchor-left",
|
||||||
|
"type": "symbol",
|
||||||
|
"source": "geojson",
|
||||||
|
"filter": ["==", "anchor", "left"],
|
||||||
|
"layout": {
|
||||||
|
"text-field": "1",
|
||||||
|
"text-size": 20,
|
||||||
|
"text-anchor": "left",
|
||||||
|
"text-font": [ "Open Sans Semibold", "Arial Unicode MS Bold" ],
|
||||||
|
"text-allow-overlap": true,
|
||||||
|
"text-ignore-placement": true,
|
||||||
|
"icon-image": "nine-part-textfit-wh-stretchOnly-proportional",
|
||||||
|
"icon-text-fit": "both",
|
||||||
|
"icon-allow-overlap": true,
|
||||||
|
"icon-ignore-placement": true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "anchor-top-left",
|
||||||
|
"type": "symbol",
|
||||||
|
"source": "geojson",
|
||||||
|
"filter": ["==", "anchor", "top-left"],
|
||||||
|
"layout": {
|
||||||
|
"text-field": "1",
|
||||||
|
"text-size": 20,
|
||||||
|
"text-anchor": "top-left",
|
||||||
|
"text-font": [ "Open Sans Semibold", "Arial Unicode MS Bold" ],
|
||||||
|
"text-allow-overlap": true,
|
||||||
|
"text-ignore-placement": true,
|
||||||
|
"icon-image": "nine-part-textfit-wh-stretchOnly-proportional",
|
||||||
|
"icon-text-fit": "both",
|
||||||
|
"icon-allow-overlap": true,
|
||||||
|
"icon-ignore-placement": true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "anchor-top",
|
||||||
|
"type": "symbol",
|
||||||
|
"source": "geojson",
|
||||||
|
"filter": ["==", "anchor", "top"],
|
||||||
|
"layout": {
|
||||||
|
"text-field": "1",
|
||||||
|
"text-size": 20,
|
||||||
|
"text-anchor": "top",
|
||||||
|
"text-font": [ "Open Sans Semibold", "Arial Unicode MS Bold" ],
|
||||||
|
"text-allow-overlap": true,
|
||||||
|
"text-ignore-placement": true,
|
||||||
|
"icon-image": "nine-part-textfit-wh-stretchOnly-proportional",
|
||||||
|
"icon-text-fit": "both",
|
||||||
|
"icon-allow-overlap": true,
|
||||||
|
"icon-ignore-placement": true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "anchor-top-right",
|
||||||
|
"type": "symbol",
|
||||||
|
"source": "geojson",
|
||||||
|
"filter": ["==", "anchor", "top-right"],
|
||||||
|
"layout": {
|
||||||
|
"text-field": "1",
|
||||||
|
"text-size": 20,
|
||||||
|
"text-anchor": "top-right",
|
||||||
|
"text-font": [ "Open Sans Semibold", "Arial Unicode MS Bold" ],
|
||||||
|
"text-allow-overlap": true,
|
||||||
|
"text-ignore-placement": true,
|
||||||
|
"icon-image": "nine-part-textfit-wh-stretchOnly-proportional",
|
||||||
|
"icon-text-fit": "both",
|
||||||
|
"icon-allow-overlap": true,
|
||||||
|
"icon-ignore-placement": true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "anchor-right",
|
||||||
|
"type": "symbol",
|
||||||
|
"source": "geojson",
|
||||||
|
"filter": ["==", "anchor", "right"],
|
||||||
|
"layout": {
|
||||||
|
"text-field": "1",
|
||||||
|
"text-size": 20,
|
||||||
|
"text-anchor": "right",
|
||||||
|
"text-font": [ "Open Sans Semibold", "Arial Unicode MS Bold" ],
|
||||||
|
"text-allow-overlap": true,
|
||||||
|
"text-ignore-placement": true,
|
||||||
|
"icon-image": "nine-part-textfit-wh-stretchOnly-proportional",
|
||||||
|
"icon-text-fit": "both",
|
||||||
|
"icon-allow-overlap": true,
|
||||||
|
"icon-ignore-placement": true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "anchor-bottom-left",
|
||||||
|
"type": "symbol",
|
||||||
|
"source": "geojson",
|
||||||
|
"filter": ["==", "anchor", "bottom-left"],
|
||||||
|
"layout": {
|
||||||
|
"text-field": "1",
|
||||||
|
"text-size": 20,
|
||||||
|
"text-anchor": "bottom-left",
|
||||||
|
"text-font": [ "Open Sans Semibold", "Arial Unicode MS Bold" ],
|
||||||
|
"text-allow-overlap": true,
|
||||||
|
"text-ignore-placement": true,
|
||||||
|
"icon-image": "nine-part-textfit-wh-stretchOnly-proportional",
|
||||||
|
"icon-text-fit": "both",
|
||||||
|
"icon-allow-overlap": true,
|
||||||
|
"icon-ignore-placement": true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "anchor-bottom",
|
||||||
|
"type": "symbol",
|
||||||
|
"source": "geojson",
|
||||||
|
"filter": ["==", "anchor", "bottom"],
|
||||||
|
"layout": {
|
||||||
|
"text-field": "1",
|
||||||
|
"text-size": 20,
|
||||||
|
"text-anchor": "bottom",
|
||||||
|
"text-font": [ "Open Sans Semibold", "Arial Unicode MS Bold" ],
|
||||||
|
"text-allow-overlap": true,
|
||||||
|
"text-ignore-placement": true,
|
||||||
|
"icon-image": "nine-part-textfit-wh-stretchOnly-proportional",
|
||||||
|
"icon-text-fit": "both",
|
||||||
|
"icon-allow-overlap": true,
|
||||||
|
"icon-ignore-placement": true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "anchor-bottom-right",
|
||||||
|
"type": "symbol",
|
||||||
|
"source": "geojson",
|
||||||
|
"filter": ["==", "anchor", "bottom-right"],
|
||||||
|
"layout": {
|
||||||
|
"text-field": "1",
|
||||||
|
"text-size": 20,
|
||||||
|
"text-anchor": "bottom-right",
|
||||||
|
"text-font": [ "Open Sans Semibold", "Arial Unicode MS Bold" ],
|
||||||
|
"text-allow-overlap": true,
|
||||||
|
"text-ignore-placement": true,
|
||||||
|
"icon-image": "nine-part-textfit-wh-stretchOnly-proportional",
|
||||||
|
"icon-text-fit": "both",
|
||||||
|
"icon-allow-overlap": true,
|
||||||
|
"icon-ignore-placement": true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "anchors",
|
||||||
|
"type": "circle",
|
||||||
|
"source": "geojson",
|
||||||
|
"paint": {
|
||||||
|
"circle-radius": 2,
|
||||||
|
"circle-color": "green",
|
||||||
|
"circle-stroke-color": "white",
|
||||||
|
"circle-stroke-width": 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
After Width: | Height: | Size: 1.2 KiB |
@@ -0,0 +1,99 @@
|
|||||||
|
{
|
||||||
|
"version": 8,
|
||||||
|
"metadata": {
|
||||||
|
"test": {
|
||||||
|
"width": 64,
|
||||||
|
"height": 64
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"sources": {
|
||||||
|
"geojson": {
|
||||||
|
"type": "geojson",
|
||||||
|
"data": {
|
||||||
|
"type": "FeatureCollection",
|
||||||
|
"features": [{
|
||||||
|
"type": "Feature",
|
||||||
|
"properties": {
|
||||||
|
"order": "no-match"
|
||||||
|
},
|
||||||
|
"geometry": {
|
||||||
|
"type": "Point",
|
||||||
|
"coordinates": [-6.6, 12]
|
||||||
|
}
|
||||||
|
}, {
|
||||||
|
"type": "Feature",
|
||||||
|
"properties": {
|
||||||
|
"order": "no-match"
|
||||||
|
},
|
||||||
|
"geometry": {
|
||||||
|
"type": "Point",
|
||||||
|
"coordinates": [6.6, 12]
|
||||||
|
}
|
||||||
|
}, {
|
||||||
|
"type": "Feature",
|
||||||
|
"properties": {
|
||||||
|
"order": "match"
|
||||||
|
},
|
||||||
|
"geometry": {
|
||||||
|
"type": "Point",
|
||||||
|
"coordinates": [-6.6, -11.5]
|
||||||
|
}
|
||||||
|
}, {
|
||||||
|
"type": "Feature",
|
||||||
|
"properties": {
|
||||||
|
"order": "match"
|
||||||
|
},
|
||||||
|
"geometry": {
|
||||||
|
"type": "Point",
|
||||||
|
"coordinates": [6.6, -11.5]
|
||||||
|
}
|
||||||
|
}]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"sprite": "local://sprites/stretch",
|
||||||
|
"glyphs": "local://glyphs/{fontstack}/{range}.pbf",
|
||||||
|
"layers": [
|
||||||
|
{
|
||||||
|
"id": "symbol",
|
||||||
|
"type": "symbol",
|
||||||
|
"source": "geojson",
|
||||||
|
"filter": ["==", "order", "no-match"],
|
||||||
|
"layout": {
|
||||||
|
"text-field": "I",
|
||||||
|
"text-font": [
|
||||||
|
"Open Sans Semibold",
|
||||||
|
"Arial Unicode MS Bold"
|
||||||
|
],
|
||||||
|
"icon-image": "nine-part-content",
|
||||||
|
"icon-text-fit": "both"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "symbol_with_offset",
|
||||||
|
"type": "symbol",
|
||||||
|
"source": "geojson",
|
||||||
|
"filter": ["==", "order", "match"],
|
||||||
|
"layout": {
|
||||||
|
"text-field": "I",
|
||||||
|
"text-font": [
|
||||||
|
"Open Sans Semibold",
|
||||||
|
"Arial Unicode MS Bold"
|
||||||
|
],
|
||||||
|
"icon-image": "nine-part-textfit-wh-stretchOnly-proportional",
|
||||||
|
"icon-text-fit": "both"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "anchors",
|
||||||
|
"type": "circle",
|
||||||
|
"source": "geojson",
|
||||||
|
"paint": {
|
||||||
|
"circle-radius": 2,
|
||||||
|
"circle-color": "green",
|
||||||
|
"circle-stroke-color": "white",
|
||||||
|
"circle-stroke-width": 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
After Width: | Height: | Size: 7.5 KiB |
@@ -0,0 +1,191 @@
|
|||||||
|
{
|
||||||
|
"version": 8,
|
||||||
|
"metadata": {
|
||||||
|
"test": {
|
||||||
|
"width": 360,
|
||||||
|
"height": 360,
|
||||||
|
"description": "This draws the matrix of all possible combinations of textFitWidth (columns) and textFitHeight (rows) where they proceed from the top-left in the order stretchOrShrink, stretchOnly, and proportional. This version shows the effect of a long string with a wider aspect ratio than the source image."
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"sources": {
|
||||||
|
"geojson": {
|
||||||
|
"type": "geojson",
|
||||||
|
"data": "local://geojson/grid-tall.json"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"sprite": "local://sprites/textFit",
|
||||||
|
"glyphs": "local://glyphs/{fontstack}/{range}.pbf",
|
||||||
|
"layers": [
|
||||||
|
{
|
||||||
|
"id": "wh-stretchOrShrink-stretchOrShrink",
|
||||||
|
"type": "symbol",
|
||||||
|
"source": "geojson",
|
||||||
|
"filter": ["==", "cell", "top-left"],
|
||||||
|
"layout": {
|
||||||
|
"text-field": "一二三四",
|
||||||
|
"text-size": 20,
|
||||||
|
"text-anchor": "center",
|
||||||
|
"text-writing-mode": ["vertical"],
|
||||||
|
"text-font": [ "NotoCJK" ],
|
||||||
|
"text-allow-overlap": true,
|
||||||
|
"text-ignore-placement": true,
|
||||||
|
"icon-image": "textFit-wh-stretchOrShrink-stretchOrShrink",
|
||||||
|
"icon-text-fit": "both",
|
||||||
|
"icon-allow-overlap": true,
|
||||||
|
"icon-ignore-placement": true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "wh-stretchOnly-stretchOrShrink",
|
||||||
|
"type": "symbol",
|
||||||
|
"source": "geojson",
|
||||||
|
"filter": ["==", "cell", "top-middle"],
|
||||||
|
"layout": {
|
||||||
|
"text-field": "一二三四",
|
||||||
|
"text-size": 20,
|
||||||
|
"text-anchor": "center",
|
||||||
|
"text-writing-mode": ["vertical"],
|
||||||
|
"text-font": [ "NotoCJK" ],
|
||||||
|
"text-allow-overlap": true,
|
||||||
|
"text-ignore-placement": true,
|
||||||
|
"icon-image": "textFit-wh-stretchOnly-stretchOrShrink",
|
||||||
|
"icon-text-fit": "both",
|
||||||
|
"icon-allow-overlap": true,
|
||||||
|
"icon-ignore-placement": true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "wh-proportional-stretchOrShrink",
|
||||||
|
"type": "symbol",
|
||||||
|
"source": "geojson",
|
||||||
|
"filter": ["==", "cell", "top-right"],
|
||||||
|
"layout": {
|
||||||
|
"text-field": "一二三四",
|
||||||
|
"text-size": 20,
|
||||||
|
"text-anchor": "center",
|
||||||
|
"text-writing-mode": ["vertical"],
|
||||||
|
"text-font": [ "NotoCJK" ],
|
||||||
|
"text-allow-overlap": true,
|
||||||
|
"text-ignore-placement": true,
|
||||||
|
"icon-image": "textFit-wh-proportional-stretchOrShrink",
|
||||||
|
"icon-text-fit": "both",
|
||||||
|
"icon-allow-overlap": true,
|
||||||
|
"icon-ignore-placement": true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "wh-stretchOrShrink-stretchOnly",
|
||||||
|
"type": "symbol",
|
||||||
|
"source": "geojson",
|
||||||
|
"filter": ["==", "cell", "middle-left"],
|
||||||
|
"layout": {
|
||||||
|
"text-field": "一二三四",
|
||||||
|
"text-size": 20,
|
||||||
|
"text-anchor": "center",
|
||||||
|
"text-writing-mode": ["vertical"],
|
||||||
|
"text-font": [ "NotoCJK" ],
|
||||||
|
"text-allow-overlap": true,
|
||||||
|
"text-ignore-placement": true,
|
||||||
|
"icon-image": "textFit-wh-stretchOrShrink-stretchOnly",
|
||||||
|
"icon-text-fit": "both",
|
||||||
|
"icon-allow-overlap": true,
|
||||||
|
"icon-ignore-placement": true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "wh-stretchOnly-stretchOnly",
|
||||||
|
"type": "symbol",
|
||||||
|
"source": "geojson",
|
||||||
|
"filter": ["==", "cell", "middle-middle"],
|
||||||
|
"layout": {
|
||||||
|
"text-field": "一二三四",
|
||||||
|
"text-size": 20,
|
||||||
|
"text-anchor": "center",
|
||||||
|
"text-writing-mode": ["vertical"],
|
||||||
|
"text-font": [ "NotoCJK" ],
|
||||||
|
"text-allow-overlap": true,
|
||||||
|
"text-ignore-placement": true,
|
||||||
|
"icon-image": "textFit-wh-stretchOnly-stretchOnly",
|
||||||
|
"icon-text-fit": "both",
|
||||||
|
"icon-allow-overlap": true,
|
||||||
|
"icon-ignore-placement": true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "wh-proportional-stretchOnly",
|
||||||
|
"type": "symbol",
|
||||||
|
"source": "geojson",
|
||||||
|
"filter": ["==", "cell", "middle-right"],
|
||||||
|
"layout": {
|
||||||
|
"text-field": "一二三四",
|
||||||
|
"text-size": 20,
|
||||||
|
"text-anchor": "center",
|
||||||
|
"text-writing-mode": ["vertical"],
|
||||||
|
"text-font": [ "NotoCJK" ],
|
||||||
|
"text-allow-overlap": true,
|
||||||
|
"text-ignore-placement": true,
|
||||||
|
"icon-image": "textFit-wh-proportional-stretchOnly",
|
||||||
|
"icon-text-fit": "both",
|
||||||
|
"icon-allow-overlap": true,
|
||||||
|
"icon-ignore-placement": true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "wh-stretchOrShrink-proportional",
|
||||||
|
"type": "symbol",
|
||||||
|
"source": "geojson",
|
||||||
|
"filter": ["==", "cell", "bottom-left"],
|
||||||
|
"layout": {
|
||||||
|
"text-field": "一二三四",
|
||||||
|
"text-size": 20,
|
||||||
|
"text-anchor": "center",
|
||||||
|
"text-writing-mode": ["vertical"],
|
||||||
|
"text-font": [ "NotoCJK" ],
|
||||||
|
"text-allow-overlap": true,
|
||||||
|
"text-ignore-placement": true,
|
||||||
|
"icon-image": "textFit-wh-stretchOrShrink-proportional",
|
||||||
|
"icon-text-fit": "both",
|
||||||
|
"icon-allow-overlap": true,
|
||||||
|
"icon-ignore-placement": true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "wh-stretchOnly-proportional",
|
||||||
|
"type": "symbol",
|
||||||
|
"source": "geojson",
|
||||||
|
"filter": ["==", "cell", "bottom-middle"],
|
||||||
|
"layout": {
|
||||||
|
"text-field": "一二三四",
|
||||||
|
"text-size": 20,
|
||||||
|
"text-anchor": "center",
|
||||||
|
"text-writing-mode": ["vertical"],
|
||||||
|
"text-font": [ "NotoCJK" ],
|
||||||
|
"text-allow-overlap": true,
|
||||||
|
"text-ignore-placement": true,
|
||||||
|
"icon-image": "textFit-wh-stretchOnly-proportional",
|
||||||
|
"icon-text-fit": "both",
|
||||||
|
"icon-allow-overlap": true,
|
||||||
|
"icon-ignore-placement": true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "wh-proportional-proportional",
|
||||||
|
"type": "symbol",
|
||||||
|
"source": "geojson",
|
||||||
|
"filter": ["==", "cell", "bottom-right"],
|
||||||
|
"layout": {
|
||||||
|
"text-field": "一二三四",
|
||||||
|
"text-size": 20,
|
||||||
|
"text-anchor": "center",
|
||||||
|
"text-writing-mode": ["vertical"],
|
||||||
|
"text-font": [ "NotoCJK" ],
|
||||||
|
"text-allow-overlap": true,
|
||||||
|
"text-ignore-placement": true,
|
||||||
|
"icon-image": "textFit-wh-proportional-proportional",
|
||||||
|
"icon-text-fit": "both",
|
||||||
|
"icon-allow-overlap": true,
|
||||||
|
"icon-ignore-placement": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
After Width: | Height: | Size: 16 KiB |
|
After Width: | Height: | Size: 16 KiB |
|
After Width: | Height: | Size: 16 KiB |
@@ -0,0 +1,182 @@
|
|||||||
|
{
|
||||||
|
"version": 8,
|
||||||
|
"metadata": {
|
||||||
|
"test": {
|
||||||
|
"width": 360,
|
||||||
|
"height": 180,
|
||||||
|
"description": "This draws the matrix of all possible combinations of textFitWidth (columns) and textFitHeight (rows) where they proceed from the top-left in the order stretchOrShrink, stretchOnly, and proportional. This version shows the effect of a long string with a wider aspect ratio than the source image."
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"sources": {
|
||||||
|
"geojson": {
|
||||||
|
"type": "geojson",
|
||||||
|
"data": "local://geojson/grid.json"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"sprite": "local://sprites/textFit",
|
||||||
|
"glyphs": "local://glyphs/{fontstack}/{range}.pbf",
|
||||||
|
"layers": [
|
||||||
|
{
|
||||||
|
"id": "wh-stretchOrShrink-stretchOrShrink",
|
||||||
|
"type": "symbol",
|
||||||
|
"source": "geojson",
|
||||||
|
"filter": ["==", "cell", "top-left"],
|
||||||
|
"layout": {
|
||||||
|
"text-field": "12345",
|
||||||
|
"text-size": 20,
|
||||||
|
"text-anchor": "center",
|
||||||
|
"text-font": [ "Open Sans Semibold", "Arial Unicode MS Bold" ],
|
||||||
|
"text-allow-overlap": true,
|
||||||
|
"text-ignore-placement": true,
|
||||||
|
"icon-image": "textFit-wh-stretchOrShrink-stretchOrShrink",
|
||||||
|
"icon-text-fit": "both",
|
||||||
|
"icon-allow-overlap": true,
|
||||||
|
"icon-ignore-placement": true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "wh-stretchOnly-stretchOrShrink",
|
||||||
|
"type": "symbol",
|
||||||
|
"source": "geojson",
|
||||||
|
"filter": ["==", "cell", "top-middle"],
|
||||||
|
"layout": {
|
||||||
|
"text-field": "12345",
|
||||||
|
"text-size": 20,
|
||||||
|
"text-anchor": "center",
|
||||||
|
"text-font": [ "Open Sans Semibold", "Arial Unicode MS Bold" ],
|
||||||
|
"text-allow-overlap": true,
|
||||||
|
"text-ignore-placement": true,
|
||||||
|
"icon-image": "textFit-wh-stretchOnly-stretchOrShrink",
|
||||||
|
"icon-text-fit": "both",
|
||||||
|
"icon-allow-overlap": true,
|
||||||
|
"icon-ignore-placement": true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "wh-proportional-stretchOrShrink",
|
||||||
|
"type": "symbol",
|
||||||
|
"source": "geojson",
|
||||||
|
"filter": ["==", "cell", "top-right"],
|
||||||
|
"layout": {
|
||||||
|
"text-field": "12345",
|
||||||
|
"text-size": 20,
|
||||||
|
"text-anchor": "center",
|
||||||
|
"text-font": [ "Open Sans Semibold", "Arial Unicode MS Bold" ],
|
||||||
|
"text-allow-overlap": true,
|
||||||
|
"text-ignore-placement": true,
|
||||||
|
"icon-image": "textFit-wh-proportional-stretchOrShrink",
|
||||||
|
"icon-text-fit": "both",
|
||||||
|
"icon-allow-overlap": true,
|
||||||
|
"icon-ignore-placement": true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "wh-stretchOrShrink-stretchOnly",
|
||||||
|
"type": "symbol",
|
||||||
|
"source": "geojson",
|
||||||
|
"filter": ["==", "cell", "middle-left"],
|
||||||
|
"layout": {
|
||||||
|
"text-field": "12345",
|
||||||
|
"text-size": 20,
|
||||||
|
"text-anchor": "center",
|
||||||
|
"text-font": [ "Open Sans Semibold", "Arial Unicode MS Bold" ],
|
||||||
|
"text-allow-overlap": true,
|
||||||
|
"text-ignore-placement": true,
|
||||||
|
"icon-image": "textFit-wh-stretchOrShrink-stretchOnly",
|
||||||
|
"icon-text-fit": "both",
|
||||||
|
"icon-allow-overlap": true,
|
||||||
|
"icon-ignore-placement": true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "wh-stretchOnly-stretchOnly",
|
||||||
|
"type": "symbol",
|
||||||
|
"source": "geojson",
|
||||||
|
"filter": ["==", "cell", "middle-middle"],
|
||||||
|
"layout": {
|
||||||
|
"text-field": "12345",
|
||||||
|
"text-size": 20,
|
||||||
|
"text-anchor": "center",
|
||||||
|
"text-font": [ "Open Sans Semibold", "Arial Unicode MS Bold" ],
|
||||||
|
"text-allow-overlap": true,
|
||||||
|
"text-ignore-placement": true,
|
||||||
|
"icon-image": "textFit-wh-stretchOnly-stretchOnly",
|
||||||
|
"icon-text-fit": "both",
|
||||||
|
"icon-allow-overlap": true,
|
||||||
|
"icon-ignore-placement": true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "wh-proportional-stretchOnly",
|
||||||
|
"type": "symbol",
|
||||||
|
"source": "geojson",
|
||||||
|
"filter": ["==", "cell", "middle-right"],
|
||||||
|
"layout": {
|
||||||
|
"text-field": "12345",
|
||||||
|
"text-size": 20,
|
||||||
|
"text-anchor": "center",
|
||||||
|
"text-font": [ "Open Sans Semibold", "Arial Unicode MS Bold" ],
|
||||||
|
"text-allow-overlap": true,
|
||||||
|
"text-ignore-placement": true,
|
||||||
|
"icon-image": "textFit-wh-proportional-stretchOnly",
|
||||||
|
"icon-text-fit": "both",
|
||||||
|
"icon-allow-overlap": true,
|
||||||
|
"icon-ignore-placement": true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "wh-stretchOrShrink-proportional",
|
||||||
|
"type": "symbol",
|
||||||
|
"source": "geojson",
|
||||||
|
"filter": ["==", "cell", "bottom-left"],
|
||||||
|
"layout": {
|
||||||
|
"text-field": "12345",
|
||||||
|
"text-size": 20,
|
||||||
|
"text-anchor": "center",
|
||||||
|
"text-font": [ "Open Sans Semibold", "Arial Unicode MS Bold" ],
|
||||||
|
"text-allow-overlap": true,
|
||||||
|
"text-ignore-placement": true,
|
||||||
|
"icon-image": "textFit-wh-stretchOrShrink-proportional",
|
||||||
|
"icon-text-fit": "both",
|
||||||
|
"icon-allow-overlap": true,
|
||||||
|
"icon-ignore-placement": true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "wh-stretchOnly-proportional",
|
||||||
|
"type": "symbol",
|
||||||
|
"source": "geojson",
|
||||||
|
"filter": ["==", "cell", "bottom-middle"],
|
||||||
|
"layout": {
|
||||||
|
"text-field": "12345",
|
||||||
|
"text-size": 20,
|
||||||
|
"text-anchor": "center",
|
||||||
|
"text-font": [ "Open Sans Semibold", "Arial Unicode MS Bold" ],
|
||||||
|
"text-allow-overlap": true,
|
||||||
|
"text-ignore-placement": true,
|
||||||
|
"icon-image": "textFit-wh-stretchOnly-proportional",
|
||||||
|
"icon-text-fit": "both",
|
||||||
|
"icon-allow-overlap": true,
|
||||||
|
"icon-ignore-placement": true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "wh-proportional-proportional",
|
||||||
|
"type": "symbol",
|
||||||
|
"source": "geojson",
|
||||||
|
"filter": ["==", "cell", "bottom-right"],
|
||||||
|
"layout": {
|
||||||
|
"text-field": "12345",
|
||||||
|
"text-size": 20,
|
||||||
|
"text-anchor": "center",
|
||||||
|
"text-font": [ "Open Sans Semibold", "Arial Unicode MS Bold" ],
|
||||||
|
"text-allow-overlap": true,
|
||||||
|
"text-ignore-placement": true,
|
||||||
|
"icon-image": "textFit-wh-proportional-proportional",
|
||||||
|
"icon-text-fit": "both",
|
||||||
|
"icon-allow-overlap": true,
|
||||||
|
"icon-ignore-placement": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
After Width: | Height: | Size: 5.6 KiB |
@@ -0,0 +1,191 @@
|
|||||||
|
{
|
||||||
|
"version": 8,
|
||||||
|
"metadata": {
|
||||||
|
"test": {
|
||||||
|
"width": 360,
|
||||||
|
"height": 360,
|
||||||
|
"description": "This draws the matrix of all possible combinations of textFitWidth (columns) and textFitHeight (rows) where they proceed from the top-left in the order stretchOrShrink, stretchOnly, and proportional. This version shows the effect of a long string with a wider aspect ratio than the source image."
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"sources": {
|
||||||
|
"geojson": {
|
||||||
|
"type": "geojson",
|
||||||
|
"data": "local://geojson/grid-tall.json"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"sprite": "local://sprites/textFit",
|
||||||
|
"glyphs": "local://glyphs/{fontstack}/{range}.pbf",
|
||||||
|
"layers": [
|
||||||
|
{
|
||||||
|
"id": "wh-stretchOrShrink-stretchOrShrink",
|
||||||
|
"type": "symbol",
|
||||||
|
"source": "geojson",
|
||||||
|
"filter": ["==", "cell", "top-left"],
|
||||||
|
"layout": {
|
||||||
|
"text-field": "四",
|
||||||
|
"text-size": 20,
|
||||||
|
"text-anchor": "center",
|
||||||
|
"text-writing-mode": ["vertical"],
|
||||||
|
"text-font": [ "NotoCJK" ],
|
||||||
|
"text-allow-overlap": true,
|
||||||
|
"text-ignore-placement": true,
|
||||||
|
"icon-image": "textFit-wh-stretchOrShrink-stretchOrShrink",
|
||||||
|
"icon-text-fit": "both",
|
||||||
|
"icon-allow-overlap": true,
|
||||||
|
"icon-ignore-placement": true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "wh-stretchOnly-stretchOrShrink",
|
||||||
|
"type": "symbol",
|
||||||
|
"source": "geojson",
|
||||||
|
"filter": ["==", "cell", "top-middle"],
|
||||||
|
"layout": {
|
||||||
|
"text-field": "四",
|
||||||
|
"text-size": 20,
|
||||||
|
"text-anchor": "center",
|
||||||
|
"text-writing-mode": ["vertical"],
|
||||||
|
"text-font": [ "NotoCJK" ],
|
||||||
|
"text-allow-overlap": true,
|
||||||
|
"text-ignore-placement": true,
|
||||||
|
"icon-image": "textFit-wh-stretchOnly-stretchOrShrink",
|
||||||
|
"icon-text-fit": "both",
|
||||||
|
"icon-allow-overlap": true,
|
||||||
|
"icon-ignore-placement": true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "wh-proportional-stretchOrShrink",
|
||||||
|
"type": "symbol",
|
||||||
|
"source": "geojson",
|
||||||
|
"filter": ["==", "cell", "top-right"],
|
||||||
|
"layout": {
|
||||||
|
"text-field": "四",
|
||||||
|
"text-size": 20,
|
||||||
|
"text-anchor": "center",
|
||||||
|
"text-writing-mode": ["vertical"],
|
||||||
|
"text-font": [ "NotoCJK" ],
|
||||||
|
"text-allow-overlap": true,
|
||||||
|
"text-ignore-placement": true,
|
||||||
|
"icon-image": "textFit-wh-proportional-stretchOrShrink",
|
||||||
|
"icon-text-fit": "both",
|
||||||
|
"icon-allow-overlap": true,
|
||||||
|
"icon-ignore-placement": true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "wh-stretchOrShrink-stretchOnly",
|
||||||
|
"type": "symbol",
|
||||||
|
"source": "geojson",
|
||||||
|
"filter": ["==", "cell", "middle-left"],
|
||||||
|
"layout": {
|
||||||
|
"text-field": "四",
|
||||||
|
"text-size": 20,
|
||||||
|
"text-anchor": "center",
|
||||||
|
"text-writing-mode": ["vertical"],
|
||||||
|
"text-font": [ "NotoCJK" ],
|
||||||
|
"text-allow-overlap": true,
|
||||||
|
"text-ignore-placement": true,
|
||||||
|
"icon-image": "textFit-wh-stretchOrShrink-stretchOnly",
|
||||||
|
"icon-text-fit": "both",
|
||||||
|
"icon-allow-overlap": true,
|
||||||
|
"icon-ignore-placement": true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "wh-stretchOnly-stretchOnly",
|
||||||
|
"type": "symbol",
|
||||||
|
"source": "geojson",
|
||||||
|
"filter": ["==", "cell", "middle-middle"],
|
||||||
|
"layout": {
|
||||||
|
"text-field": "四",
|
||||||
|
"text-size": 20,
|
||||||
|
"text-anchor": "center",
|
||||||
|
"text-writing-mode": ["vertical"],
|
||||||
|
"text-font": [ "NotoCJK" ],
|
||||||
|
"text-allow-overlap": true,
|
||||||
|
"text-ignore-placement": true,
|
||||||
|
"icon-image": "textFit-wh-stretchOnly-stretchOnly",
|
||||||
|
"icon-text-fit": "both",
|
||||||
|
"icon-allow-overlap": true,
|
||||||
|
"icon-ignore-placement": true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "wh-proportional-stretchOnly",
|
||||||
|
"type": "symbol",
|
||||||
|
"source": "geojson",
|
||||||
|
"filter": ["==", "cell", "middle-right"],
|
||||||
|
"layout": {
|
||||||
|
"text-field": "四",
|
||||||
|
"text-size": 20,
|
||||||
|
"text-anchor": "center",
|
||||||
|
"text-writing-mode": ["vertical"],
|
||||||
|
"text-font": [ "NotoCJK" ],
|
||||||
|
"text-allow-overlap": true,
|
||||||
|
"text-ignore-placement": true,
|
||||||
|
"icon-image": "textFit-wh-proportional-stretchOnly",
|
||||||
|
"icon-text-fit": "both",
|
||||||
|
"icon-allow-overlap": true,
|
||||||
|
"icon-ignore-placement": true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "wh-stretchOrShrink-proportional",
|
||||||
|
"type": "symbol",
|
||||||
|
"source": "geojson",
|
||||||
|
"filter": ["==", "cell", "bottom-left"],
|
||||||
|
"layout": {
|
||||||
|
"text-field": "四",
|
||||||
|
"text-size": 20,
|
||||||
|
"text-anchor": "center",
|
||||||
|
"text-writing-mode": ["vertical"],
|
||||||
|
"text-font": [ "NotoCJK" ],
|
||||||
|
"text-allow-overlap": true,
|
||||||
|
"text-ignore-placement": true,
|
||||||
|
"icon-image": "textFit-wh-stretchOrShrink-proportional",
|
||||||
|
"icon-text-fit": "both",
|
||||||
|
"icon-allow-overlap": true,
|
||||||
|
"icon-ignore-placement": true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "wh-stretchOnly-proportional",
|
||||||
|
"type": "symbol",
|
||||||
|
"source": "geojson",
|
||||||
|
"filter": ["==", "cell", "bottom-middle"],
|
||||||
|
"layout": {
|
||||||
|
"text-field": "四",
|
||||||
|
"text-size": 20,
|
||||||
|
"text-anchor": "center",
|
||||||
|
"text-writing-mode": ["vertical"],
|
||||||
|
"text-font": [ "NotoCJK" ],
|
||||||
|
"text-allow-overlap": true,
|
||||||
|
"text-ignore-placement": true,
|
||||||
|
"icon-image": "textFit-wh-stretchOnly-proportional",
|
||||||
|
"icon-text-fit": "both",
|
||||||
|
"icon-allow-overlap": true,
|
||||||
|
"icon-ignore-placement": true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "wh-proportional-proportional",
|
||||||
|
"type": "symbol",
|
||||||
|
"source": "geojson",
|
||||||
|
"filter": ["==", "cell", "bottom-right"],
|
||||||
|
"layout": {
|
||||||
|
"text-field": "四",
|
||||||
|
"text-size": 20,
|
||||||
|
"text-anchor": "center",
|
||||||
|
"text-writing-mode": ["vertical"],
|
||||||
|
"text-font": [ "NotoCJK" ],
|
||||||
|
"text-allow-overlap": true,
|
||||||
|
"text-ignore-placement": true,
|
||||||
|
"icon-image": "textFit-wh-proportional-proportional",
|
||||||
|
"icon-text-fit": "both",
|
||||||
|
"icon-allow-overlap": true,
|
||||||
|
"icon-ignore-placement": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
After Width: | Height: | Size: 2.7 KiB |
@@ -0,0 +1,182 @@
|
|||||||
|
{
|
||||||
|
"version": 8,
|
||||||
|
"metadata": {
|
||||||
|
"test": {
|
||||||
|
"width": 360,
|
||||||
|
"height": 180,
|
||||||
|
"description": "This draws the matrix of all possible combinations of textFitWidth (columns) and textFitHeight (rows) where they proceed from the top-left in the order stretchOrShrink, stretchOnly, and proportional. This version shows the effect of a short string with a narrower aspect ratio than the source image."
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"sources": {
|
||||||
|
"geojson": {
|
||||||
|
"type": "geojson",
|
||||||
|
"data": "local://geojson/grid.json"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"sprite": "local://sprites/textFit",
|
||||||
|
"glyphs": "local://glyphs/{fontstack}/{range}.pbf",
|
||||||
|
"layers": [
|
||||||
|
{
|
||||||
|
"id": "wh-stretchOrShrink-stretchOrShrink",
|
||||||
|
"type": "symbol",
|
||||||
|
"source": "geojson",
|
||||||
|
"filter": ["==", "cell", "top-left"],
|
||||||
|
"layout": {
|
||||||
|
"text-field": "1",
|
||||||
|
"text-size": 20,
|
||||||
|
"text-anchor": "center",
|
||||||
|
"text-font": [ "Open Sans Semibold", "Arial Unicode MS Bold" ],
|
||||||
|
"text-allow-overlap": true,
|
||||||
|
"text-ignore-placement": true,
|
||||||
|
"icon-image": "textFit-wh-stretchOrShrink-stretchOrShrink",
|
||||||
|
"icon-text-fit": "both",
|
||||||
|
"icon-allow-overlap": true,
|
||||||
|
"icon-ignore-placement": true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "wh-stretchOnly-stretchOrShrink",
|
||||||
|
"type": "symbol",
|
||||||
|
"source": "geojson",
|
||||||
|
"filter": ["==", "cell", "top-middle"],
|
||||||
|
"layout": {
|
||||||
|
"text-field": "1",
|
||||||
|
"text-size": 20,
|
||||||
|
"text-anchor": "center",
|
||||||
|
"text-font": [ "Open Sans Semibold", "Arial Unicode MS Bold" ],
|
||||||
|
"text-allow-overlap": true,
|
||||||
|
"text-ignore-placement": true,
|
||||||
|
"icon-image": "textFit-wh-stretchOnly-stretchOrShrink",
|
||||||
|
"icon-text-fit": "both",
|
||||||
|
"icon-allow-overlap": true,
|
||||||
|
"icon-ignore-placement": true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "wh-proportional-stretchOrShrink",
|
||||||
|
"type": "symbol",
|
||||||
|
"source": "geojson",
|
||||||
|
"filter": ["==", "cell", "top-right"],
|
||||||
|
"layout": {
|
||||||
|
"text-field": "1",
|
||||||
|
"text-size": 20,
|
||||||
|
"text-anchor": "center",
|
||||||
|
"text-font": [ "Open Sans Semibold", "Arial Unicode MS Bold" ],
|
||||||
|
"text-allow-overlap": true,
|
||||||
|
"text-ignore-placement": true,
|
||||||
|
"icon-image": "textFit-wh-proportional-stretchOrShrink",
|
||||||
|
"icon-text-fit": "both",
|
||||||
|
"icon-allow-overlap": true,
|
||||||
|
"icon-ignore-placement": true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "wh-stretchOrShrink-stretchOnly",
|
||||||
|
"type": "symbol",
|
||||||
|
"source": "geojson",
|
||||||
|
"filter": ["==", "cell", "middle-left"],
|
||||||
|
"layout": {
|
||||||
|
"text-field": "1",
|
||||||
|
"text-size": 20,
|
||||||
|
"text-anchor": "center",
|
||||||
|
"text-font": [ "Open Sans Semibold", "Arial Unicode MS Bold" ],
|
||||||
|
"text-allow-overlap": true,
|
||||||
|
"text-ignore-placement": true,
|
||||||
|
"icon-image": "textFit-wh-stretchOrShrink-stretchOnly",
|
||||||
|
"icon-text-fit": "both",
|
||||||
|
"icon-allow-overlap": true,
|
||||||
|
"icon-ignore-placement": true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "wh-stretchOnly-stretchOnly",
|
||||||
|
"type": "symbol",
|
||||||
|
"source": "geojson",
|
||||||
|
"filter": ["==", "cell", "middle-middle"],
|
||||||
|
"layout": {
|
||||||
|
"text-field": "1",
|
||||||
|
"text-size": 20,
|
||||||
|
"text-anchor": "center",
|
||||||
|
"text-font": [ "Open Sans Semibold", "Arial Unicode MS Bold" ],
|
||||||
|
"text-allow-overlap": true,
|
||||||
|
"text-ignore-placement": true,
|
||||||
|
"icon-image": "textFit-wh-stretchOnly-stretchOnly",
|
||||||
|
"icon-text-fit": "both",
|
||||||
|
"icon-allow-overlap": true,
|
||||||
|
"icon-ignore-placement": true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "wh-proportional-stretchOnly",
|
||||||
|
"type": "symbol",
|
||||||
|
"source": "geojson",
|
||||||
|
"filter": ["==", "cell", "middle-right"],
|
||||||
|
"layout": {
|
||||||
|
"text-field": "1",
|
||||||
|
"text-size": 20,
|
||||||
|
"text-anchor": "center",
|
||||||
|
"text-font": [ "Open Sans Semibold", "Arial Unicode MS Bold" ],
|
||||||
|
"text-allow-overlap": true,
|
||||||
|
"text-ignore-placement": true,
|
||||||
|
"icon-image": "textFit-wh-proportional-stretchOnly",
|
||||||
|
"icon-text-fit": "both",
|
||||||
|
"icon-allow-overlap": true,
|
||||||
|
"icon-ignore-placement": true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "wh-stretchOrShrink-proportional",
|
||||||
|
"type": "symbol",
|
||||||
|
"source": "geojson",
|
||||||
|
"filter": ["==", "cell", "bottom-left"],
|
||||||
|
"layout": {
|
||||||
|
"text-field": "1",
|
||||||
|
"text-size": 20,
|
||||||
|
"text-anchor": "center",
|
||||||
|
"text-font": [ "Open Sans Semibold", "Arial Unicode MS Bold" ],
|
||||||
|
"text-allow-overlap": true,
|
||||||
|
"text-ignore-placement": true,
|
||||||
|
"icon-image": "textFit-wh-stretchOrShrink-proportional",
|
||||||
|
"icon-text-fit": "both",
|
||||||
|
"icon-allow-overlap": true,
|
||||||
|
"icon-ignore-placement": true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "wh-stretchOnly-proportional",
|
||||||
|
"type": "symbol",
|
||||||
|
"source": "geojson",
|
||||||
|
"filter": ["==", "cell", "bottom-middle"],
|
||||||
|
"layout": {
|
||||||
|
"text-field": "1",
|
||||||
|
"text-size": 20,
|
||||||
|
"text-anchor": "center",
|
||||||
|
"text-font": [ "Open Sans Semibold", "Arial Unicode MS Bold" ],
|
||||||
|
"text-allow-overlap": true,
|
||||||
|
"text-ignore-placement": true,
|
||||||
|
"icon-image": "textFit-wh-stretchOnly-proportional",
|
||||||
|
"icon-text-fit": "both",
|
||||||
|
"icon-allow-overlap": true,
|
||||||
|
"icon-ignore-placement": true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "wh-proportional-proportional",
|
||||||
|
"type": "symbol",
|
||||||
|
"source": "geojson",
|
||||||
|
"filter": ["==", "cell", "bottom-right"],
|
||||||
|
"layout": {
|
||||||
|
"text-field": "1",
|
||||||
|
"text-size": 20,
|
||||||
|
"text-anchor": "center",
|
||||||
|
"text-font": [ "Open Sans Semibold", "Arial Unicode MS Bold" ],
|
||||||
|
"text-allow-overlap": true,
|
||||||
|
"text-ignore-placement": true,
|
||||||
|
"icon-image": "textFit-wh-proportional-proportional",
|
||||||
|
"icon-text-fit": "both",
|
||||||
|
"icon-allow-overlap": true,
|
||||||
|
"icon-ignore-placement": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
@@ -20,6 +20,19 @@
|
|||||||
"sdf": false,
|
"sdf": false,
|
||||||
"content": [10, 10, 30, 30]
|
"content": [10, 10, 30, 30]
|
||||||
},
|
},
|
||||||
|
"nine-part-textfit-wh-stretchOnly-proportional": {
|
||||||
|
"x": 0,
|
||||||
|
"y": 0,
|
||||||
|
"width": 40,
|
||||||
|
"height": 40,
|
||||||
|
"pixelRatio": 2,
|
||||||
|
"stretchX": [[10, 30]],
|
||||||
|
"stretchY": [[10, 30]],
|
||||||
|
"sdf": false,
|
||||||
|
"content": [10, 10, 30, 30],
|
||||||
|
"textFitWidth": "stretchOnly",
|
||||||
|
"textFitHeight": "proportional"
|
||||||
|
},
|
||||||
"fifteen-part": {
|
"fifteen-part": {
|
||||||
"x": 50,
|
"x": 50,
|
||||||
"y": 0,
|
"y": 0,
|
||||||
|
|||||||
119
metrics/integration/sprites/textFit.json
Normal file
@@ -0,0 +1,119 @@
|
|||||||
|
{
|
||||||
|
"textFit-wh-stretchOrShrink-stretchOrShrink": {
|
||||||
|
"x": 0,
|
||||||
|
"y": 0,
|
||||||
|
"width": 100,
|
||||||
|
"height": 70,
|
||||||
|
"pixelRatio": 1,
|
||||||
|
"stretchX": [[9, 91]],
|
||||||
|
"stretchY": [[9, 61]],
|
||||||
|
"sdf": false,
|
||||||
|
"content": [9, 9, 91, 61],
|
||||||
|
"textFitWidth": "stretchOrShrink",
|
||||||
|
"textFitHeight": "stretchOrShrink"
|
||||||
|
},
|
||||||
|
"textFit-wh-stretchOnly-stretchOrShrink": {
|
||||||
|
"x": 0,
|
||||||
|
"y": 0,
|
||||||
|
"width": 100,
|
||||||
|
"height": 70,
|
||||||
|
"pixelRatio": 1,
|
||||||
|
"stretchX": [[9, 91]],
|
||||||
|
"stretchY": [[9, 61]],
|
||||||
|
"sdf": false,
|
||||||
|
"content": [9, 9, 91, 61],
|
||||||
|
"textFitWidth": "stretchOnly",
|
||||||
|
"textFitHeight": "stretchOrShrink"
|
||||||
|
},
|
||||||
|
"textFit-wh-proportional-stretchOrShrink": {
|
||||||
|
"x": 0,
|
||||||
|
"y": 0,
|
||||||
|
"width": 100,
|
||||||
|
"height": 70,
|
||||||
|
"pixelRatio": 1,
|
||||||
|
"stretchX": [[9, 91]],
|
||||||
|
"stretchY": [[9, 61]],
|
||||||
|
"sdf": false,
|
||||||
|
"content": [9, 9, 91, 61],
|
||||||
|
"textFitWidth": "proportional",
|
||||||
|
"textFitHeight": "stretchOrShrink"
|
||||||
|
},
|
||||||
|
"textFit-wh-stretchOrShrink-stretchOnly": {
|
||||||
|
"x": 0,
|
||||||
|
"y": 0,
|
||||||
|
"width": 100,
|
||||||
|
"height": 70,
|
||||||
|
"pixelRatio": 1,
|
||||||
|
"stretchX": [[9, 91]],
|
||||||
|
"stretchY": [[9, 61]],
|
||||||
|
"sdf": false,
|
||||||
|
"content": [9, 9, 91, 61],
|
||||||
|
"textFitWidth": "stretchOrShrink",
|
||||||
|
"textFitHeight": "stretchOnly"
|
||||||
|
},
|
||||||
|
"textFit-wh-stretchOnly-stretchOnly": {
|
||||||
|
"x": 0,
|
||||||
|
"y": 0,
|
||||||
|
"width": 100,
|
||||||
|
"height": 70,
|
||||||
|
"pixelRatio": 1,
|
||||||
|
"stretchX": [[9, 91]],
|
||||||
|
"stretchY": [[9, 61]],
|
||||||
|
"sdf": false,
|
||||||
|
"content": [9, 9, 91, 61],
|
||||||
|
"textFitWidth": "stretchOnly",
|
||||||
|
"textFitHeight": "stretchOnly"
|
||||||
|
},
|
||||||
|
"textFit-wh-proportional-stretchOnly": {
|
||||||
|
"x": 0,
|
||||||
|
"y": 0,
|
||||||
|
"width": 100,
|
||||||
|
"height": 70,
|
||||||
|
"pixelRatio": 1,
|
||||||
|
"stretchX": [[9, 91]],
|
||||||
|
"stretchY": [[9, 61]],
|
||||||
|
"sdf": false,
|
||||||
|
"content": [9, 9, 91, 61],
|
||||||
|
"textFitWidth": "proportional",
|
||||||
|
"textFitHeight": "stretchOnly"
|
||||||
|
},
|
||||||
|
"textFit-wh-stretchOrShrink-proportional": {
|
||||||
|
"x": 0,
|
||||||
|
"y": 0,
|
||||||
|
"width": 100,
|
||||||
|
"height": 70,
|
||||||
|
"pixelRatio": 1,
|
||||||
|
"stretchX": [[9, 91]],
|
||||||
|
"stretchY": [[9, 61]],
|
||||||
|
"sdf": false,
|
||||||
|
"content": [9, 9, 91, 61],
|
||||||
|
"textFitWidth": "stretchOrShrink",
|
||||||
|
"textFitHeight": "proportional"
|
||||||
|
},
|
||||||
|
"textFit-wh-stretchOnly-proportional": {
|
||||||
|
"x": 0,
|
||||||
|
"y": 0,
|
||||||
|
"width": 100,
|
||||||
|
"height": 70,
|
||||||
|
"pixelRatio": 1,
|
||||||
|
"stretchX": [[9, 91]],
|
||||||
|
"stretchY": [[9, 61]],
|
||||||
|
"sdf": false,
|
||||||
|
"content": [9, 9, 91, 61],
|
||||||
|
"textFitWidth": "stretchOnly",
|
||||||
|
"textFitHeight": "proportional"
|
||||||
|
},
|
||||||
|
"textFit-wh-proportional-proportional": {
|
||||||
|
"x": 0,
|
||||||
|
"y": 0,
|
||||||
|
"width": 100,
|
||||||
|
"height": 70,
|
||||||
|
"pixelRatio": 1,
|
||||||
|
"stretchX": [[9, 91]],
|
||||||
|
"stretchY": [[9, 61]],
|
||||||
|
"sdf": false,
|
||||||
|
"content": [9, 9, 91, 61],
|
||||||
|
"textFitWidth": "proportional",
|
||||||
|
"textFitHeight": "proportional"
|
||||||
|
}
|
||||||
|
}
|
||||||
BIN
metrics/integration/sprites/textFit.png
Normal file
|
After Width: | Height: | Size: 421 B |
@@ -14,4 +14,4 @@
|
|||||||
"probeGFX",
|
"probeGFX",
|
||||||
"probeNetwork"
|
"probeNetwork"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
[
|
[
|
||||||
"probeNetwork - default - end",
|
"probeNetwork - default - end",
|
||||||
3,
|
3,
|
||||||
3380
|
3696
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
"probeNetwork - default - start",
|
"probeNetwork - default - start",
|
||||||
@@ -32,4 +32,4 @@
|
|||||||
]
|
]
|
||||||
]
|
]
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
[
|
[
|
||||||
"probeNetwork - default - end",
|
"probeNetwork - default - end",
|
||||||
3,
|
3,
|
||||||
3380
|
3696
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
"probeNetwork - default - start",
|
"probeNetwork - default - start",
|
||||||
@@ -32,4 +32,4 @@
|
|||||||
]
|
]
|
||||||
]
|
]
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
[
|
[
|
||||||
"probeNetwork - default - end",
|
"probeNetwork - default - end",
|
||||||
4,
|
4,
|
||||||
88322
|
88638
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
"probeNetwork - default - start",
|
"probeNetwork - default - start",
|
||||||
@@ -32,4 +32,4 @@
|
|||||||
]
|
]
|
||||||
]
|
]
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
[
|
[
|
||||||
"probeNetwork - default - end",
|
"probeNetwork - default - end",
|
||||||
4,
|
4,
|
||||||
88322
|
88638
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
"probeNetwork - default - start",
|
"probeNetwork - default - start",
|
||||||
@@ -32,4 +32,4 @@
|
|||||||
]
|
]
|
||||||
]
|
]
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
[
|
[
|
||||||
"probeNetwork - default - end",
|
"probeNetwork - default - end",
|
||||||
4,
|
4,
|
||||||
88322
|
88638
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
"probeNetwork - default - start",
|
"probeNetwork - default - start",
|
||||||
@@ -32,4 +32,4 @@
|
|||||||
]
|
]
|
||||||
]
|
]
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
[
|
[
|
||||||
"probeNetwork - default - end",
|
"probeNetwork - default - end",
|
||||||
4,
|
4,
|
||||||
88322
|
88638
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
"probeNetwork - default - start",
|
"probeNetwork - default - start",
|
||||||
@@ -32,4 +32,4 @@
|
|||||||
]
|
]
|
||||||
]
|
]
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
[
|
[
|
||||||
"probeNetwork - default - end",
|
"probeNetwork - default - end",
|
||||||
4,
|
4,
|
||||||
88322
|
88638
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
"probeNetwork - default - start",
|
"probeNetwork - default - start",
|
||||||
@@ -32,4 +32,4 @@
|
|||||||
]
|
]
|
||||||
]
|
]
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
[
|
[
|
||||||
"probeNetwork - default - end",
|
"probeNetwork - default - end",
|
||||||
4,
|
4,
|
||||||
88322
|
88638
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
"probeNetwork - default - start",
|
"probeNetwork - default - start",
|
||||||
@@ -32,4 +32,4 @@
|
|||||||
]
|
]
|
||||||
]
|
]
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
[
|
[
|
||||||
"probeNetwork - default - end",
|
"probeNetwork - default - end",
|
||||||
4,
|
4,
|
||||||
88322
|
88638
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
"probeNetwork - default - start",
|
"probeNetwork - default - start",
|
||||||
@@ -32,4 +32,4 @@
|
|||||||
]
|
]
|
||||||
]
|
]
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
[
|
[
|
||||||
"probeNetwork - default - end",
|
"probeNetwork - default - end",
|
||||||
4,
|
4,
|
||||||
88322
|
88638
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
"probeNetwork - default - start",
|
"probeNetwork - default - start",
|
||||||
@@ -32,4 +32,4 @@
|
|||||||
]
|
]
|
||||||
]
|
]
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
[
|
[
|
||||||
"probeNetwork - default - end",
|
"probeNetwork - default - end",
|
||||||
4,
|
4,
|
||||||
88322
|
88638
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
"probeNetwork - default - start",
|
"probeNetwork - default - start",
|
||||||
@@ -32,4 +32,4 @@
|
|||||||
]
|
]
|
||||||
]
|
]
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
[
|
[
|
||||||
"probeNetwork - default - end",
|
"probeNetwork - default - end",
|
||||||
4,
|
4,
|
||||||
88322
|
88638
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
"probeNetwork - default - start",
|
"probeNetwork - default - start",
|
||||||
@@ -32,4 +32,4 @@
|
|||||||
]
|
]
|
||||||
]
|
]
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,14 @@
|
|||||||
|
{
|
||||||
|
"network": [
|
||||||
|
[
|
||||||
|
"probeNetwork - default - end",
|
||||||
|
4,
|
||||||
|
88638
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"probeNetwork - default - start",
|
||||||
|
0,
|
||||||
|
0
|
||||||
|
]
|
||||||
|
]
|
||||||
|
}
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
{
|
||||||
|
"network": [
|
||||||
|
[
|
||||||
|
"probeNetwork - default - end",
|
||||||
|
4,
|
||||||
|
88638
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"probeNetwork - default - start",
|
||||||
|
0,
|
||||||
|
0
|
||||||
|
]
|
||||||
|
]
|
||||||
|
}
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
{
|
||||||
|
"network": [
|
||||||
|
[
|
||||||
|
"probeNetwork - default - end",
|
||||||
|
3,
|
||||||
|
86757
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"probeNetwork - default - start",
|
||||||
|
0,
|
||||||
|
0
|
||||||
|
]
|
||||||
|
]
|
||||||
|
}
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
{
|
||||||
|
"network": [
|
||||||
|
[
|
||||||
|
"probeNetwork - default - end",
|
||||||
|
5,
|
||||||
|
390425
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"probeNetwork - default - start",
|
||||||
|
0,
|
||||||
|
0
|
||||||
|
]
|
||||||
|
]
|
||||||
|
}
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
{
|
||||||
|
"network": [
|
||||||
|
[
|
||||||
|
"probeNetwork - default - end",
|
||||||
|
4,
|
||||||
|
90025
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"probeNetwork - default - start",
|
||||||
|
0,
|
||||||
|
0
|
||||||
|
]
|
||||||
|
]
|
||||||
|
}
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
{
|
||||||
|
"network": [
|
||||||
|
[
|
||||||
|
"probeNetwork - default - end",
|
||||||
|
4,
|
||||||
|
199330
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"probeNetwork - default - start",
|
||||||
|
0,
|
||||||
|
0
|
||||||
|
]
|
||||||
|
]
|
||||||
|
}
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
{
|
||||||
|
"network": [
|
||||||
|
[
|
||||||
|
"probeNetwork - default - end",
|
||||||
|
4,
|
||||||
|
90025
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"probeNetwork - default - start",
|
||||||
|
0,
|
||||||
|
0
|
||||||
|
]
|
||||||
|
]
|
||||||
|
}
|
||||||
@@ -13,7 +13,9 @@ ImagePosition::ImagePosition(const mapbox::Bin& bin, const style::Image::Impl& i
|
|||||||
version(version_),
|
version(version_),
|
||||||
stretchX(image.stretchX),
|
stretchX(image.stretchX),
|
||||||
stretchY(image.stretchY),
|
stretchY(image.stretchY),
|
||||||
content(image.content) {}
|
content(image.content),
|
||||||
|
textFitWidth(image.textFitWidth),
|
||||||
|
textFitHeight(image.textFitHeight) {}
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
|
|||||||
@@ -28,6 +28,8 @@ public:
|
|||||||
style::ImageStretches stretchX;
|
style::ImageStretches stretchX;
|
||||||
style::ImageStretches stretchY;
|
style::ImageStretches stretchY;
|
||||||
std::optional<style::ImageContent> content;
|
std::optional<style::ImageContent> content;
|
||||||
|
std::optional<style::TextFit> textFitWidth;
|
||||||
|
std::optional<style::TextFit> textFitHeight;
|
||||||
|
|
||||||
std::array<uint16_t, 2> tl() const {
|
std::array<uint16_t, 2> tl() const {
|
||||||
return {{static_cast<uint16_t>(paddedRect.x + padding), static_cast<uint16_t>(paddedRect.y + padding)}};
|
return {{static_cast<uint16_t>(paddedRect.x + padding), static_cast<uint16_t>(paddedRect.y + padding)}};
|
||||||
|
|||||||
@@ -26,7 +26,9 @@ std::unique_ptr<style::Image> createStyleImage(const std::string& id,
|
|||||||
const bool sdf,
|
const bool sdf,
|
||||||
style::ImageStretches&& stretchX,
|
style::ImageStretches&& stretchX,
|
||||||
style::ImageStretches&& stretchY,
|
style::ImageStretches&& stretchY,
|
||||||
const std::optional<style::ImageContent>& content) {
|
const std::optional<style::ImageContent>& content,
|
||||||
|
const std::optional<style::TextFit>& textFitWidth,
|
||||||
|
const std::optional<style::TextFit>& textFitHeight) {
|
||||||
// Disallow invalid parameter configurations.
|
// Disallow invalid parameter configurations.
|
||||||
if (width <= 0 || height <= 0 || width > 1024 || height > 1024 || ratio <= 0 || ratio > 10 || srcX < 0 ||
|
if (width <= 0 || height <= 0 || width > 1024 || height > 1024 || ratio <= 0 || ratio > 10 || srcX < 0 ||
|
||||||
srcY < 0 || srcX >= static_cast<int32_t>(image.size.width) || srcY >= static_cast<int32_t>(image.size.height) ||
|
srcY < 0 || srcX >= static_cast<int32_t>(image.size.width) || srcY >= static_cast<int32_t>(image.size.height) ||
|
||||||
@@ -47,8 +49,15 @@ std::unique_ptr<style::Image> createStyleImage(const std::string& id,
|
|||||||
PremultipliedImage::copy(image, dstImage, {static_cast<uint32_t>(srcX), static_cast<uint32_t>(srcY)}, {0, 0}, size);
|
PremultipliedImage::copy(image, dstImage, {static_cast<uint32_t>(srcX), static_cast<uint32_t>(srcY)}, {0, 0}, size);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
return std::make_unique<style::Image>(
|
return std::make_unique<style::Image>(id,
|
||||||
id, std::move(dstImage), static_cast<float>(ratio), sdf, std::move(stretchX), std::move(stretchY), content);
|
std::move(dstImage),
|
||||||
|
static_cast<float>(ratio),
|
||||||
|
sdf,
|
||||||
|
std::move(stretchX),
|
||||||
|
std::move(stretchY),
|
||||||
|
content,
|
||||||
|
textFitWidth,
|
||||||
|
textFitHeight);
|
||||||
} catch (const util::StyleImageException& ex) {
|
} catch (const util::StyleImageException& ex) {
|
||||||
Log::Error(Event::Sprite, std::string("Can't create image with invalid metadata: ") + ex.what());
|
Log::Error(Event::Sprite, std::string("Can't create image with invalid metadata: ") + ex.what());
|
||||||
return nullptr;
|
return nullptr;
|
||||||
@@ -150,6 +159,40 @@ std::optional<style::ImageContent> getContent(const JSValue& value, const char*
|
|||||||
return std::nullopt;
|
return std::nullopt;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::optional<style::TextFit> parseTextFit(const std::string_view& value) {
|
||||||
|
if (value == "stretchOrShrink") {
|
||||||
|
return style::TextFit::stretchOrShrink;
|
||||||
|
} else if (value == "stretchOnly") {
|
||||||
|
return style::TextFit::stretchOnly;
|
||||||
|
} else if (value == "proportional") {
|
||||||
|
return style::TextFit::proportional;
|
||||||
|
} else {
|
||||||
|
return std::nullopt;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::optional<style::TextFit> getTextFit(const JSValue& value, const char* property, const char* name) {
|
||||||
|
if (value.HasMember(property)) {
|
||||||
|
const auto& v = value[property];
|
||||||
|
if (v.IsString()) {
|
||||||
|
const auto& valueString = v.GetString();
|
||||||
|
const auto textFit = parseTextFit(std::string_view(valueString));
|
||||||
|
if (!textFit.has_value()) {
|
||||||
|
Log::Warning(Event::Sprite,
|
||||||
|
std::string("Invalid sprite image '") + name + "': value of '" + property +
|
||||||
|
"' is an invalid value '" + valueString + "'");
|
||||||
|
}
|
||||||
|
return textFit;
|
||||||
|
} else {
|
||||||
|
Log::Warning(
|
||||||
|
Event::Sprite,
|
||||||
|
std::string("Invalid sprite image '") + name + "': value of '" + property + "' must be a string");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return std::nullopt;
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
std::vector<Immutable<style::Image::Impl>> parseSprite(const std::string& id,
|
std::vector<Immutable<style::Image::Impl>> parseSprite(const std::string& id,
|
||||||
@@ -189,6 +232,8 @@ std::vector<Immutable<style::Image::Impl>> parseSprite(const std::string& id,
|
|||||||
style::ImageStretches stretchX = getStretches(value, "stretchX", name.c_str());
|
style::ImageStretches stretchX = getStretches(value, "stretchX", name.c_str());
|
||||||
style::ImageStretches stretchY = getStretches(value, "stretchY", name.c_str());
|
style::ImageStretches stretchY = getStretches(value, "stretchY", name.c_str());
|
||||||
std::optional<style::ImageContent> content = getContent(value, "content", name.c_str());
|
std::optional<style::ImageContent> content = getContent(value, "content", name.c_str());
|
||||||
|
std::optional<style::TextFit> textFitWidth = getTextFit(value, "textFitWidth", name.c_str());
|
||||||
|
std::optional<style::TextFit> textFitHeight = getTextFit(value, "textFitHeight", name.c_str());
|
||||||
|
|
||||||
auto image = createStyleImage(completeName,
|
auto image = createStyleImage(completeName,
|
||||||
raster,
|
raster,
|
||||||
@@ -200,7 +245,9 @@ std::vector<Immutable<style::Image::Impl>> parseSprite(const std::string& id,
|
|||||||
sdf,
|
sdf,
|
||||||
std::move(stretchX),
|
std::move(stretchX),
|
||||||
std::move(stretchY),
|
std::move(stretchY),
|
||||||
content);
|
content,
|
||||||
|
textFitWidth,
|
||||||
|
textFitHeight);
|
||||||
if (image) {
|
if (image) {
|
||||||
images.push_back(std::move(image->baseImpl));
|
images.push_back(std::move(image->baseImpl));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,7 +17,9 @@ std::unique_ptr<style::Image> createStyleImage(const std::string& id,
|
|||||||
bool sdf,
|
bool sdf,
|
||||||
style::ImageStretches&& stretchX = {},
|
style::ImageStretches&& stretchX = {},
|
||||||
style::ImageStretches&& stretchY = {},
|
style::ImageStretches&& stretchY = {},
|
||||||
const std::optional<style::ImageContent>& content = std::nullopt);
|
const std::optional<style::ImageContent>& content = std::nullopt,
|
||||||
|
const std::optional<style::TextFit>& textFitWidth = std::nullopt,
|
||||||
|
const std::optional<style::TextFit>& textFitHeight = std::nullopt);
|
||||||
|
|
||||||
// Parses an image and an associated JSON file and returns the sprite objects.
|
// Parses an image and an associated JSON file and returns the sprite objects.
|
||||||
std::vector<Immutable<style::Image::Impl>> parseSprite(const std::string& id,
|
std::vector<Immutable<style::Image::Impl>> parseSprite(const std::string& id,
|
||||||
|
|||||||
@@ -11,9 +11,18 @@ Image::Image(std::string id,
|
|||||||
bool sdf,
|
bool sdf,
|
||||||
ImageStretches stretchX,
|
ImageStretches stretchX,
|
||||||
ImageStretches stretchY,
|
ImageStretches stretchY,
|
||||||
const std::optional<ImageContent>& content)
|
const std::optional<ImageContent>& content,
|
||||||
: baseImpl(makeMutable<Impl>(
|
const std::optional<TextFit>& textFitWidth,
|
||||||
std::move(id), std::move(image), pixelRatio, sdf, std::move(stretchX), std::move(stretchY), content)) {}
|
const std::optional<TextFit>& textFitHeight)
|
||||||
|
: baseImpl(makeMutable<Impl>(std::move(id),
|
||||||
|
std::move(image),
|
||||||
|
pixelRatio,
|
||||||
|
sdf,
|
||||||
|
std::move(stretchX),
|
||||||
|
std::move(stretchY),
|
||||||
|
content,
|
||||||
|
textFitWidth,
|
||||||
|
textFitHeight)) {}
|
||||||
|
|
||||||
std::string Image::getID() const {
|
std::string Image::getID() const {
|
||||||
return baseImpl->id;
|
return baseImpl->id;
|
||||||
@@ -45,5 +54,12 @@ const std::optional<ImageContent>& Image::getContent() const {
|
|||||||
return baseImpl->content;
|
return baseImpl->content;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const std::optional<TextFit>& Image::getTextFitWidth() const {
|
||||||
|
return baseImpl->textFitWidth;
|
||||||
|
}
|
||||||
|
|
||||||
|
const std::optional<TextFit>& Image::getTextFitHeight() const {
|
||||||
|
return baseImpl->textFitHeight;
|
||||||
|
}
|
||||||
} // namespace style
|
} // namespace style
|
||||||
} // namespace mbgl
|
} // namespace mbgl
|
||||||
|
|||||||
@@ -38,14 +38,18 @@ Image::Impl::Impl(std::string id_,
|
|||||||
bool sdf_,
|
bool sdf_,
|
||||||
ImageStretches stretchX_,
|
ImageStretches stretchX_,
|
||||||
ImageStretches stretchY_,
|
ImageStretches stretchY_,
|
||||||
std::optional<ImageContent> content_)
|
std::optional<ImageContent> content_,
|
||||||
|
std::optional<TextFit> textFitWidth_,
|
||||||
|
std::optional<TextFit> textFitHeight_)
|
||||||
: id(std::move(id_)),
|
: id(std::move(id_)),
|
||||||
image(std::move(image_)),
|
image(std::move(image_)),
|
||||||
pixelRatio(pixelRatio_),
|
pixelRatio(pixelRatio_),
|
||||||
sdf(sdf_),
|
sdf(sdf_),
|
||||||
stretchX(std::move(stretchX_)),
|
stretchX(std::move(stretchX_)),
|
||||||
stretchY(std::move(stretchY_)),
|
stretchY(std::move(stretchY_)),
|
||||||
content(std::move(content_)) {
|
content(std::move(content_)),
|
||||||
|
textFitWidth(std::move(textFitWidth_)),
|
||||||
|
textFitHeight(std::move(textFitHeight_)) {
|
||||||
if (!image.valid()) {
|
if (!image.valid()) {
|
||||||
throw util::StyleImageException("dimensions may not be zero");
|
throw util::StyleImageException("dimensions may not be zero");
|
||||||
} else if (pixelRatio <= 0) {
|
} else if (pixelRatio <= 0) {
|
||||||
|
|||||||
@@ -17,7 +17,9 @@ public:
|
|||||||
bool sdf = false,
|
bool sdf = false,
|
||||||
ImageStretches stretchX = {},
|
ImageStretches stretchX = {},
|
||||||
ImageStretches stretchY = {},
|
ImageStretches stretchY = {},
|
||||||
std::optional<ImageContent> content = std::nullopt);
|
std::optional<ImageContent> content = std::nullopt,
|
||||||
|
std::optional<TextFit> textFitWidth = std::nullopt,
|
||||||
|
std::optional<TextFit> textFitHeight = std::nullopt);
|
||||||
|
|
||||||
const std::string id;
|
const std::string id;
|
||||||
|
|
||||||
@@ -35,6 +37,13 @@ public:
|
|||||||
|
|
||||||
// The space where text can be fit into this image.
|
// The space where text can be fit into this image.
|
||||||
const std::optional<ImageContent> content;
|
const std::optional<ImageContent> content;
|
||||||
|
|
||||||
|
// If `icon-text-fit` is used in a layer with this image, this option defines constraints on the horizontal scaling
|
||||||
|
// of the image.
|
||||||
|
const std::optional<TextFit> textFitWidth;
|
||||||
|
// If `icon-text-fit` is used in a layer with this image, this option defines constraints on the vertical scaling of
|
||||||
|
// the image.
|
||||||
|
const std::optional<TextFit> textFitHeight;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace style
|
} // namespace style
|
||||||
|
|||||||
@@ -7,19 +7,70 @@ namespace mbgl {
|
|||||||
|
|
||||||
CollisionFeature::CollisionFeature(const GeometryCoordinates& line,
|
CollisionFeature::CollisionFeature(const GeometryCoordinates& line,
|
||||||
const Anchor& anchor,
|
const Anchor& anchor,
|
||||||
const float top,
|
const Shaping& shapedText,
|
||||||
const float bottom,
|
|
||||||
const float left,
|
|
||||||
const float right,
|
|
||||||
const std::optional<Padding>& collisionPadding,
|
|
||||||
const float boxScale,
|
const float boxScale,
|
||||||
const float padding,
|
const float padding,
|
||||||
const style::SymbolPlacementType placement,
|
const style::SymbolPlacementType placement,
|
||||||
IndexedSubfeature indexedFeature_,
|
const RefIndexedSubfeature& indexedFeature_,
|
||||||
const float overscaling,
|
const float overscaling,
|
||||||
const float rotate)
|
const float rotate)
|
||||||
: indexedFeature(std::move(indexedFeature_)),
|
: indexedFeature(std::move(indexedFeature_)),
|
||||||
alongLine(placement != style::SymbolPlacementType::Point) {
|
alongLine(placement != style::SymbolPlacementType::Point) {
|
||||||
|
initialize(line,
|
||||||
|
anchor,
|
||||||
|
shapedText.top,
|
||||||
|
shapedText.bottom,
|
||||||
|
shapedText.left,
|
||||||
|
shapedText.right,
|
||||||
|
std::nullopt,
|
||||||
|
boxScale,
|
||||||
|
padding,
|
||||||
|
overscaling,
|
||||||
|
rotate);
|
||||||
|
}
|
||||||
|
|
||||||
|
CollisionFeature::CollisionFeature(const GeometryCoordinates& line,
|
||||||
|
const Anchor& anchor,
|
||||||
|
std::optional<PositionedIcon> shapedIcon,
|
||||||
|
const float boxScale,
|
||||||
|
const float padding,
|
||||||
|
const RefIndexedSubfeature& indexedFeature_,
|
||||||
|
const float rotate)
|
||||||
|
: indexedFeature(std::move(indexedFeature_)),
|
||||||
|
alongLine(false) {
|
||||||
|
if (shapedIcon) {
|
||||||
|
const auto& image = shapedIcon->image();
|
||||||
|
auto icon = *shapedIcon;
|
||||||
|
if (image.content && (image.textFitWidth || image.textFitHeight)) {
|
||||||
|
icon = shapedIcon->applyTextFit();
|
||||||
|
}
|
||||||
|
initialize(line,
|
||||||
|
anchor,
|
||||||
|
icon.top(),
|
||||||
|
icon.bottom(),
|
||||||
|
icon.left(),
|
||||||
|
icon.right(),
|
||||||
|
shapedIcon->collisionPadding(),
|
||||||
|
boxScale,
|
||||||
|
padding,
|
||||||
|
1,
|
||||||
|
rotate);
|
||||||
|
} else {
|
||||||
|
initialize(line, anchor, 0, 0, 0, 0, std::nullopt, boxScale, padding, 1, rotate);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CollisionFeature::initialize(const GeometryCoordinates& line,
|
||||||
|
const Anchor& anchor,
|
||||||
|
float top,
|
||||||
|
float bottom,
|
||||||
|
float left,
|
||||||
|
float right,
|
||||||
|
const std::optional<Padding>& collisionPadding,
|
||||||
|
float boxScale,
|
||||||
|
float padding,
|
||||||
|
float overscaling,
|
||||||
|
float rotate) {
|
||||||
if (top == 0 && bottom == 0 && left == 0 && right == 0) return;
|
if (top == 0 && bottom == 0 && left == 0 && right == 0) return;
|
||||||
|
|
||||||
float y1 = top * boxScale - padding;
|
float y1 = top * boxScale - padding;
|
||||||
|
|||||||
@@ -89,20 +89,7 @@ public:
|
|||||||
const style::SymbolPlacementType placement,
|
const style::SymbolPlacementType placement,
|
||||||
const RefIndexedSubfeature& indexedFeature_,
|
const RefIndexedSubfeature& indexedFeature_,
|
||||||
const float overscaling,
|
const float overscaling,
|
||||||
const float rotate)
|
const float rotate);
|
||||||
: CollisionFeature(line,
|
|
||||||
anchor,
|
|
||||||
shapedText.top,
|
|
||||||
shapedText.bottom,
|
|
||||||
shapedText.left,
|
|
||||||
shapedText.right,
|
|
||||||
std::nullopt,
|
|
||||||
boxScale,
|
|
||||||
padding,
|
|
||||||
placement,
|
|
||||||
indexedFeature_,
|
|
||||||
overscaling,
|
|
||||||
rotate) {}
|
|
||||||
|
|
||||||
// for icons
|
// for icons
|
||||||
// Icons collision features are always SymbolPlacementType::Point, which
|
// Icons collision features are always SymbolPlacementType::Point, which
|
||||||
@@ -118,40 +105,24 @@ public:
|
|||||||
const float boxScale,
|
const float boxScale,
|
||||||
const float padding,
|
const float padding,
|
||||||
const RefIndexedSubfeature& indexedFeature_,
|
const RefIndexedSubfeature& indexedFeature_,
|
||||||
const float rotate)
|
const float rotate);
|
||||||
: CollisionFeature(line,
|
|
||||||
anchor,
|
|
||||||
(shapedIcon ? shapedIcon->top() : 0),
|
|
||||||
(shapedIcon ? shapedIcon->bottom() : 0),
|
|
||||||
(shapedIcon ? shapedIcon->left() : 0),
|
|
||||||
(shapedIcon ? shapedIcon->right() : 0),
|
|
||||||
(shapedIcon ? shapedIcon->collisionPadding() : std::optional<Padding>{std::nullopt}),
|
|
||||||
boxScale,
|
|
||||||
padding,
|
|
||||||
style::SymbolPlacementType::Point,
|
|
||||||
indexedFeature_,
|
|
||||||
1,
|
|
||||||
rotate) {}
|
|
||||||
|
|
||||||
CollisionFeature(const GeometryCoordinates& line,
|
|
||||||
const Anchor&,
|
|
||||||
float top,
|
|
||||||
float bottom,
|
|
||||||
float left,
|
|
||||||
float right,
|
|
||||||
const std::optional<Padding>& collisionPadding,
|
|
||||||
float boxScale,
|
|
||||||
float padding,
|
|
||||||
style::SymbolPlacementType,
|
|
||||||
IndexedSubfeature,
|
|
||||||
float overscaling,
|
|
||||||
float rotate);
|
|
||||||
|
|
||||||
std::vector<CollisionBox> boxes;
|
std::vector<CollisionBox> boxes;
|
||||||
IndexedSubfeature indexedFeature;
|
IndexedSubfeature indexedFeature;
|
||||||
bool alongLine;
|
bool alongLine;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
void initialize(const GeometryCoordinates& line,
|
||||||
|
const Anchor& anchor,
|
||||||
|
float top,
|
||||||
|
float bottom,
|
||||||
|
float left,
|
||||||
|
float right,
|
||||||
|
const std::optional<Padding>& collisionPadding,
|
||||||
|
float boxScale,
|
||||||
|
float padding,
|
||||||
|
float overscaling,
|
||||||
|
float rotate);
|
||||||
void bboxifyLabel(const GeometryCoordinates& line,
|
void bboxifyLabel(const GeometryCoordinates& line,
|
||||||
GeometryCoordinate& anchorPoint,
|
GeometryCoordinate& anchorPoint,
|
||||||
std::size_t segment,
|
std::size_t segment,
|
||||||
|
|||||||
@@ -76,9 +76,6 @@ SymbolQuads getIconQuads(const PositionedIcon& shapedIcon,
|
|||||||
const uint16_t imageWidth = image.paddedRect.w - 2 * border;
|
const uint16_t imageWidth = image.paddedRect.w - 2 * border;
|
||||||
const uint16_t imageHeight = image.paddedRect.h - 2 * border;
|
const uint16_t imageHeight = image.paddedRect.h - 2 * border;
|
||||||
|
|
||||||
const float iconWidth = shapedIcon.right() - shapedIcon.left();
|
|
||||||
const float iconHeight = shapedIcon.bottom() - shapedIcon.top();
|
|
||||||
|
|
||||||
const ImageStretches stretchXFull{{0.0f, imageWidth}};
|
const ImageStretches stretchXFull{{0.0f, imageWidth}};
|
||||||
const ImageStretches stretchYFull{{0.0f, imageHeight}};
|
const ImageStretches stretchYFull{{0.0f, imageHeight}};
|
||||||
const ImageStretches& stretchX = !image.stretchX.empty() ? image.stretchX : stretchXFull;
|
const ImageStretches& stretchX = !image.stretchX.empty() ? image.stretchX : stretchXFull;
|
||||||
@@ -98,16 +95,23 @@ SymbolQuads getIconQuads(const PositionedIcon& shapedIcon,
|
|||||||
float fixedOffsetY = 0;
|
float fixedOffsetY = 0;
|
||||||
float fixedContentHeight = fixedHeight;
|
float fixedContentHeight = fixedHeight;
|
||||||
|
|
||||||
|
auto icon = shapedIcon;
|
||||||
|
|
||||||
if (hasIconTextFit && image.content) {
|
if (hasIconTextFit && image.content) {
|
||||||
auto& content = *image.content;
|
const auto& content = *image.content;
|
||||||
|
const auto contentWidth = content.right - content.left;
|
||||||
|
const auto contentHeight = content.bottom - content.top;
|
||||||
|
if (image.textFitWidth || image.textFitHeight) {
|
||||||
|
icon = icon.applyTextFit();
|
||||||
|
}
|
||||||
stretchOffsetX = sumWithinRange(stretchX, 0, content.left);
|
stretchOffsetX = sumWithinRange(stretchX, 0, content.left);
|
||||||
stretchOffsetY = sumWithinRange(stretchY, 0, content.top);
|
stretchOffsetY = sumWithinRange(stretchY, 0, content.top);
|
||||||
stretchContentWidth = sumWithinRange(stretchX, content.left, content.right);
|
stretchContentWidth = sumWithinRange(stretchX, content.left, content.right);
|
||||||
stretchContentHeight = sumWithinRange(stretchY, content.top, content.bottom);
|
stretchContentHeight = sumWithinRange(stretchY, content.top, content.bottom);
|
||||||
fixedOffsetX = content.left - stretchOffsetX;
|
fixedOffsetX = content.left - stretchOffsetX;
|
||||||
fixedOffsetY = content.top - stretchOffsetY;
|
fixedOffsetY = content.top - stretchOffsetY;
|
||||||
fixedContentWidth = content.right - content.left - stretchContentWidth;
|
fixedContentWidth = contentWidth - stretchContentWidth;
|
||||||
fixedContentHeight = content.bottom - content.top - stretchContentHeight;
|
fixedContentHeight = contentHeight - stretchContentHeight;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::optional<std::array<float, 4>> matrix{std::nullopt};
|
std::optional<std::array<float, 4>> matrix{std::nullopt};
|
||||||
@@ -118,21 +122,22 @@ SymbolQuads getIconQuads(const PositionedIcon& shapedIcon,
|
|||||||
matrix = std::array<float, 4>{{angle_cos, -angle_sin, angle_sin, angle_cos}};
|
matrix = std::array<float, 4>{{angle_cos, -angle_sin, angle_sin, angle_cos}};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const float iconLeft = icon.left();
|
||||||
|
const float iconTop = icon.top();
|
||||||
|
const float iconWidth = icon.right() - iconLeft;
|
||||||
|
const float iconHeight = icon.bottom() - iconTop;
|
||||||
|
|
||||||
auto makeBox = [&](Cut left, Cut top, Cut right, Cut bottom) {
|
auto makeBox = [&](Cut left, Cut top, Cut right, Cut bottom) {
|
||||||
const float leftEm = getEmOffset(
|
const float leftEm = getEmOffset(left.stretch - stretchOffsetX, stretchContentWidth, iconWidth, iconLeft);
|
||||||
left.stretch - stretchOffsetX, stretchContentWidth, iconWidth, shapedIcon.left());
|
|
||||||
const float leftPx = getPxOffset(left.fixed - fixedOffsetX, fixedContentWidth, left.stretch, stretchWidth);
|
const float leftPx = getPxOffset(left.fixed - fixedOffsetX, fixedContentWidth, left.stretch, stretchWidth);
|
||||||
|
|
||||||
const float topEm = getEmOffset(
|
const float topEm = getEmOffset(top.stretch - stretchOffsetY, stretchContentHeight, iconHeight, iconTop);
|
||||||
top.stretch - stretchOffsetY, stretchContentHeight, iconHeight, shapedIcon.top());
|
|
||||||
const float topPx = getPxOffset(top.fixed - fixedOffsetY, fixedContentHeight, top.stretch, stretchHeight);
|
const float topPx = getPxOffset(top.fixed - fixedOffsetY, fixedContentHeight, top.stretch, stretchHeight);
|
||||||
|
|
||||||
const float rightEm = getEmOffset(
|
const float rightEm = getEmOffset(right.stretch - stretchOffsetX, stretchContentWidth, iconWidth, iconLeft);
|
||||||
right.stretch - stretchOffsetX, stretchContentWidth, iconWidth, shapedIcon.left());
|
|
||||||
const float rightPx = getPxOffset(right.fixed - fixedOffsetX, fixedContentWidth, right.stretch, stretchWidth);
|
const float rightPx = getPxOffset(right.fixed - fixedOffsetX, fixedContentWidth, right.stretch, stretchWidth);
|
||||||
|
|
||||||
const float bottomEm = getEmOffset(
|
const float bottomEm = getEmOffset(bottom.stretch - stretchOffsetY, stretchContentHeight, iconHeight, iconTop);
|
||||||
bottom.stretch - stretchOffsetY, stretchContentHeight, iconHeight, shapedIcon.top());
|
|
||||||
const float bottomPx = getPxOffset(
|
const float bottomPx = getPxOffset(
|
||||||
bottom.fixed - fixedOffsetY, fixedContentHeight, bottom.stretch, stretchHeight);
|
bottom.fixed - fixedOffsetY, fixedContentHeight, bottom.stretch, stretchHeight);
|
||||||
|
|
||||||
|
|||||||
@@ -92,6 +92,45 @@ PositionedIcon PositionedIcon::shapeIcon(const ImagePosition& image,
|
|||||||
return PositionedIcon{image, top, bottom, left, right, collisionPadding};
|
return PositionedIcon{image, top, bottom, left, right, collisionPadding};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
PositionedIcon PositionedIcon::applyTextFit() const {
|
||||||
|
if (!_image.textFitWidth && !_image.textFitHeight) {
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
const float width = _right - _left;
|
||||||
|
const float height = _bottom - _top;
|
||||||
|
|
||||||
|
const float contentWidth = _image.content->right - _image.content->left;
|
||||||
|
const float contentHeight = _image.content->bottom - _image.content->top;
|
||||||
|
const float contentAspectRatio = contentWidth / contentHeight;
|
||||||
|
const auto textFitWidth = _image.textFitWidth.value();
|
||||||
|
const auto textFitHeight = _image.textFitHeight.value();
|
||||||
|
float newLeft = _left;
|
||||||
|
float newRight = _right;
|
||||||
|
float newTop = _top;
|
||||||
|
float newBottom = _bottom;
|
||||||
|
|
||||||
|
if (textFitHeight == style::TextFit::proportional) {
|
||||||
|
if ((textFitWidth == style::TextFit::stretchOnly && (width / height) < contentAspectRatio) ||
|
||||||
|
textFitWidth == style::TextFit::proportional) {
|
||||||
|
float newIconWidth = std::ceil(height * contentAspectRatio);
|
||||||
|
newLeft *= newIconWidth / width;
|
||||||
|
newRight = newLeft + newIconWidth;
|
||||||
|
}
|
||||||
|
} else if (textFitWidth == style::TextFit::proportional) {
|
||||||
|
if (textFitHeight == style::TextFit::stretchOnly && contentAspectRatio != 0 &&
|
||||||
|
(width / height) > contentAspectRatio) {
|
||||||
|
float newIconHeight = std::ceil(width / contentAspectRatio);
|
||||||
|
newTop *= newIconHeight / height;
|
||||||
|
newBottom = newTop + newIconHeight;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// If neither textFitHeight nor textFitWidth are proportional then
|
||||||
|
// there is no effect since the content rectangle should be precisely
|
||||||
|
// matched to the content
|
||||||
|
}
|
||||||
|
return PositionedIcon{_image, newTop, newBottom, newLeft, newRight, _collisionPadding};
|
||||||
|
}
|
||||||
|
|
||||||
void PositionedIcon::fitIconToText(const Shaping& shapedText,
|
void PositionedIcon::fitIconToText(const Shaping& shapedText,
|
||||||
const style::IconTextFitType textFit,
|
const style::IconTextFitType textFit,
|
||||||
const std::array<float, 4>& padding,
|
const std::array<float, 4>& padding,
|
||||||
|
|||||||
@@ -73,6 +73,10 @@ public:
|
|||||||
const std::array<float, 2>& iconOffset,
|
const std::array<float, 2>& iconOffset,
|
||||||
float fontScale);
|
float fontScale);
|
||||||
|
|
||||||
|
// Called after a PositionedIcon has already been run through fitIconToText,
|
||||||
|
// but needs further adjustment to apply textFitWidth and textFitHeight.
|
||||||
|
PositionedIcon applyTextFit() const;
|
||||||
|
|
||||||
const ImagePosition& image() const { return _image; }
|
const ImagePosition& image() const { return _image; }
|
||||||
float top() const { return _top; }
|
float top() const { return _top; }
|
||||||
float bottom() const { return _bottom; }
|
float bottom() const { return _bottom; }
|
||||||
|
|||||||
@@ -589,3 +589,87 @@ TEST(Sprite, SpriteParsingNullRatio) {
|
|||||||
"sprite",
|
"sprite",
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST(Sprite, SpriteParsingTextFit) {
|
||||||
|
FixtureLog log;
|
||||||
|
|
||||||
|
const auto image_1x = util::read_file("test/fixtures/annotations/emerald.png");
|
||||||
|
|
||||||
|
const auto images = parseSprite("default", image_1x, R"JSON({
|
||||||
|
"image": {
|
||||||
|
"width": 16,
|
||||||
|
"height": 16,
|
||||||
|
"x": 0,
|
||||||
|
"y": 0,
|
||||||
|
"pixelRatio": 1,
|
||||||
|
"textFitWidth": "stretchOrShrink",
|
||||||
|
"textFitHeight": "proportional"
|
||||||
|
}
|
||||||
|
})JSON");
|
||||||
|
EXPECT_EQ(1u, images.size());
|
||||||
|
EXPECT_EQ("image", images[0]->id);
|
||||||
|
EXPECT_EQ(style::TextFit::stretchOrShrink, images[0]->textFitWidth);
|
||||||
|
EXPECT_EQ(style::TextFit::proportional, images[0]->textFitHeight);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(Sprite, SpriteParsingNullTextFit) {
|
||||||
|
FixtureLog log;
|
||||||
|
|
||||||
|
const auto image_1x = util::read_file("test/fixtures/annotations/emerald.png");
|
||||||
|
|
||||||
|
const auto images = parseSprite("default", image_1x, R"JSON({
|
||||||
|
"image": {
|
||||||
|
"width": 16,
|
||||||
|
"height": 16,
|
||||||
|
"x": 0,
|
||||||
|
"y": 0,
|
||||||
|
"pixelRatio": 1,
|
||||||
|
"textFitHeight": "stretchOnly"
|
||||||
|
}
|
||||||
|
})JSON");
|
||||||
|
EXPECT_EQ(1u, images.size());
|
||||||
|
EXPECT_EQ("image", images[0]->id);
|
||||||
|
EXPECT_FALSE(images[0]->textFitWidth.has_value());
|
||||||
|
EXPECT_EQ(style::TextFit::stretchOnly, images[0]->textFitHeight);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(Sprite, SpriteParsingInvalidTextFit) {
|
||||||
|
FixtureLog log;
|
||||||
|
|
||||||
|
const auto image_1x = util::read_file("test/fixtures/annotations/emerald.png");
|
||||||
|
|
||||||
|
parseSprite("default", image_1x, R"JSON({
|
||||||
|
"image": {
|
||||||
|
"width": 16,
|
||||||
|
"height": 16,
|
||||||
|
"x": 0,
|
||||||
|
"y": 0,
|
||||||
|
"pixelRatio": 1,
|
||||||
|
"textFitWidth": "invalid",
|
||||||
|
"textFitHeight": "stretchOnly"
|
||||||
|
}
|
||||||
|
})JSON");
|
||||||
|
EXPECT_EQ(1u,
|
||||||
|
log.count({EventSeverity::Warning,
|
||||||
|
Event::Sprite,
|
||||||
|
int64_t(-1),
|
||||||
|
"Invalid sprite image 'image': value of 'textFitWidth' "
|
||||||
|
"is an invalid value 'invalid'"}));
|
||||||
|
|
||||||
|
parseSprite("default", image_1x, R"JSON({
|
||||||
|
"image": {
|
||||||
|
"width": 16,
|
||||||
|
"height": 16,
|
||||||
|
"x": 0,
|
||||||
|
"y": 0,
|
||||||
|
"pixelRatio": 1,
|
||||||
|
"textFitHeight": 0
|
||||||
|
}
|
||||||
|
})JSON");
|
||||||
|
EXPECT_EQ(1u,
|
||||||
|
log.count({EventSeverity::Warning,
|
||||||
|
Event::Sprite,
|
||||||
|
int64_t(-1),
|
||||||
|
"Invalid sprite image 'image': value of 'textFitHeight' "
|
||||||
|
"must be a string"}));
|
||||||
|
}
|
||||||
@@ -103,3 +103,125 @@ TEST(Shaping, ZWSP) {
|
|||||||
ASSERT_EQ(shaping.writingMode, WritingModeType::Horizontal);
|
ASSERT_EQ(shaping.writingMode, WritingModeType::Horizontal);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void setupShapedText(Shaping& shapedText, float textSize) {
|
||||||
|
const auto glyph = PositionedGlyph(32,
|
||||||
|
0.0f,
|
||||||
|
0.0f,
|
||||||
|
false,
|
||||||
|
0,
|
||||||
|
1.0,
|
||||||
|
/*texRect*/ {},
|
||||||
|
/*metrics*/ {},
|
||||||
|
/*imageID*/ std::nullopt);
|
||||||
|
shapedText.right = textSize;
|
||||||
|
shapedText.bottom = textSize;
|
||||||
|
shapedText.positionedLines.emplace_back();
|
||||||
|
shapedText.positionedLines.back().positionedGlyphs.emplace_back(glyph);
|
||||||
|
}
|
||||||
|
|
||||||
|
void testApplyTextFit(const mapbox::Bin& rectangle,
|
||||||
|
const style::ImageContent& content,
|
||||||
|
const std::optional<style::TextFit> textFitWidth,
|
||||||
|
const std::optional<style::TextFit> textFitHeight,
|
||||||
|
const Shaping& shapedText,
|
||||||
|
float fontScale,
|
||||||
|
float expectedRight,
|
||||||
|
float expectedBottom) {
|
||||||
|
ImagePosition image = {
|
||||||
|
rectangle,
|
||||||
|
style::Image::Impl("test",
|
||||||
|
PremultipliedImage({static_cast<uint32_t>(rectangle.w), static_cast<uint32_t>(rectangle.h)}),
|
||||||
|
1.0f,
|
||||||
|
false,
|
||||||
|
{},
|
||||||
|
{},
|
||||||
|
content,
|
||||||
|
textFitWidth,
|
||||||
|
textFitHeight)};
|
||||||
|
auto shapedIcon = PositionedIcon::shapeIcon(image, {0, 0}, style::SymbolAnchorType::TopLeft);
|
||||||
|
shapedIcon.fitIconToText(shapedText, style::IconTextFitType::Both, {0, 0, 0, 0}, {0, 0}, fontScale);
|
||||||
|
const auto& icon = shapedIcon.applyTextFit();
|
||||||
|
ASSERT_EQ(icon.top(), 0);
|
||||||
|
ASSERT_EQ(icon.left(), 0);
|
||||||
|
ASSERT_EQ(icon.right(), expectedRight);
|
||||||
|
ASSERT_EQ(icon.bottom(), expectedBottom);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(Shaping, applyTextFit) {
|
||||||
|
float textSize = 4;
|
||||||
|
float fontScale = 4;
|
||||||
|
float expectedImageSize = textSize * fontScale;
|
||||||
|
Shaping shapedText;
|
||||||
|
setupShapedText(shapedText, textSize);
|
||||||
|
|
||||||
|
{
|
||||||
|
// applyTextFitHorizontal
|
||||||
|
// This set of tests against applyTextFit starts with a 100x20 image with a 5,5,95,15 content box
|
||||||
|
// that has been fitted to a 4*4 text with scale 4, resulting in a 16*16 image.
|
||||||
|
const auto horizontalRectangle = mapbox::Bin(-1, 100, 20, -1, -1, 0, 0);
|
||||||
|
const style::ImageContent horizontalContent = {5, 5, 95, 15};
|
||||||
|
|
||||||
|
{
|
||||||
|
// applyTextFit: not specified
|
||||||
|
// No change should happen
|
||||||
|
testApplyTextFit(horizontalRectangle,
|
||||||
|
horizontalContent,
|
||||||
|
std::nullopt,
|
||||||
|
std::nullopt,
|
||||||
|
shapedText,
|
||||||
|
fontScale,
|
||||||
|
expectedImageSize,
|
||||||
|
expectedImageSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
// applyTextFit: both stretchOrShrink
|
||||||
|
// No change should happen
|
||||||
|
testApplyTextFit(horizontalRectangle,
|
||||||
|
horizontalContent,
|
||||||
|
style::TextFit::stretchOrShrink,
|
||||||
|
style::TextFit::stretchOrShrink,
|
||||||
|
shapedText,
|
||||||
|
fontScale,
|
||||||
|
expectedImageSize,
|
||||||
|
expectedImageSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
// applyTextFit: stretchOnly, proportional
|
||||||
|
// Since textFitWidth is stretchOnly, it should be returned to
|
||||||
|
// the aspect ratio of the content rectangle (9:1) aspect ratio so 144x16.
|
||||||
|
testApplyTextFit(horizontalRectangle,
|
||||||
|
horizontalContent,
|
||||||
|
style::TextFit::stretchOnly,
|
||||||
|
style::TextFit::proportional,
|
||||||
|
shapedText,
|
||||||
|
fontScale,
|
||||||
|
expectedImageSize * 9,
|
||||||
|
expectedImageSize);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
// applyTextFitVertical
|
||||||
|
// This set of tests against applyTextFit starts with a 20x100 image with a 5,5,15,95 content box
|
||||||
|
// that has been fitted to a 4*4 text with scale 4, resulting in a 16*16 image.
|
||||||
|
const auto verticalRectangle = mapbox::Bin(-1, 20, 100, -1, -1, 0, 0);
|
||||||
|
const style::ImageContent verticalContent = {5, 5, 15, 95};
|
||||||
|
|
||||||
|
{
|
||||||
|
// applyTextFit: stretchOnly, proportional
|
||||||
|
// Since textFitWidth is stretchOnly, it should be returned to
|
||||||
|
// the aspect ratio of the content rectangle (9:1) aspect ratio so 144x16.
|
||||||
|
testApplyTextFit(verticalRectangle,
|
||||||
|
verticalContent,
|
||||||
|
style::TextFit::proportional,
|
||||||
|
style::TextFit::stretchOnly,
|
||||||
|
shapedText,
|
||||||
|
fontScale,
|
||||||
|
expectedImageSize,
|
||||||
|
expectedImageSize * 9);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||