Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit 1d61c84

Browse files
mathislogesopyer
authored andcommittedJul 11, 2021
Windows port
1 parent 92c5688 commit 1d61c84

30 files changed

+513
-89
lines changed
 

‎.gitignore

+4
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
11
# Created by http://www.gitignore.io
22

3+
### OSX ###
4+
.vscode
5+
.vs
6+
37
### OSX ###
48
.DS_Store
59
.AppleDouble

‎CMakeLists.txt

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
cmake_minimum_required(VERSION 3.2)
1+
cmake_minimum_required(VERSION 3.10)
22

33
project(tangram)
44

@@ -19,7 +19,7 @@ option(TANGRAM_DEV_MODE "For developers only: Don't omit the frame pointer" OFF)
1919
message(STATUS "Build type configuration: ${CMAKE_BUILD_TYPE}")
2020

2121
# Check that submodules are present.
22-
if(NOT EXISTS "${PROJECT_SOURCE_DIR}/core/deps/harfbuzz-icu-freetype/harfbuzz/README")
22+
if(NOT (WIN32 OR EXISTS "${PROJECT_SOURCE_DIR}/core/deps/harfbuzz-icu-freetype/harfbuzz/README"))
2323
message(SEND_ERROR "Missing submodules - Please run:\n 'git submodule update --init'")
2424
return()
2525
endif()

‎cmake/utils.cmake

+6-1
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ function(check_unsupported_compiler_version)
33
set(MIN_GCC 4.9)
44
set(MIN_CLANG 3.4)
55
set(MIN_APPLECLANG 6.0)
6+
set(MIN_MSVC 19.0)
67

78
if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
89
if(CMAKE_CXX_COMPILER_VERSION VERSION_LESS ${MIN_GCC})
@@ -16,8 +17,12 @@ function(check_unsupported_compiler_version)
1617
if(CMAKE_CXX_COMPILER_VERSION VERSION_LESS ${MIN_APPLECLANG})
1718
message(FATAL_ERROR "Your Xcode version does not support C++14, please install version ${MIN_APPLECLANG} or higher")
1819
endif()
20+
elseif(CMAKE_CXX_COMPILER_ID STREQUAL "MSVC")
21+
if(CMAKE_CXX_COMPILER_VERSION VERSION_LESS ${MIN_MSVC})
22+
message(FATAL_ERROR "Your MSVC version does not support C++14, please install version ${MIN_MSVC} or higher")
23+
endif()
1924
else()
20-
message(WARNING "Compilation has only been tested with Clang, AppleClang, and GCC")
25+
message(WARNING "Compilation has only been tested with Clang, AppleClang, GCC and MSVC")
2126
endif()
2227

2328
endfunction(check_unsupported_compiler_version)

‎core/CMakeLists.txt

+13-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,11 @@
11
project(tangram-core)
22

33
# Build core library dependencies.
4+
if (WIN32)
5+
find_package(yaml-cpp CONFIG REQUIRED)
6+
find_package(ZLIB REQUIRED)
7+
endif()
8+
49
add_subdirectory(deps)
510

611
add_library(tangram-core
@@ -222,6 +227,13 @@ target_include_directories(tangram-core
222227
deps/double-conversion/include
223228
)
224229

230+
if (WIN32)
231+
set(ZLIB_NAME ZLIB::ZLIB)
232+
target_compile_definitions(tangram-core PUBLIC _USE_MATH_DEFINES)
233+
else()
234+
set(ZLIB_NAME z)
235+
endif()
236+
225237
# Link core library dependencies.
226238
target_link_libraries(tangram-core
227239
PRIVATE
@@ -231,7 +243,7 @@ target_link_libraries(tangram-core
231243
alfons
232244
double-conversion
233245
miniz
234-
z
246+
${ZLIB_NAME}
235247
)
236248

237249
# Add JavaScript implementation.

‎core/deps/CMakeLists.txt

+21-12
Original file line numberDiff line numberDiff line change
@@ -13,13 +13,15 @@ target_compile_definitions(glm INTERFACE GLM_FORCE_CTOR_INIT)
1313

1414
## yaml-cpp ##
1515
##############
16-
set(YAML_CPP_BUILD_TESTS OFF CACHE BOOL "")
17-
set(YAML_CPP_BUILD_TOOLS OFF CACHE BOOL "")
18-
set(YAML_CPP_BUILD_CONTRIB OFF CACHE BOOL "")
19-
set(YAML_CPP_INSTALL OFF CACHE BOOL "")
20-
add_subdirectory(yaml-cpp)
21-
22-
target_include_directories(yaml-cpp PUBLIC yaml-cpp/include)
16+
if (NOT WIN32)
17+
set(YAML_CPP_BUILD_TESTS OFF CACHE BOOL "")
18+
set(YAML_CPP_BUILD_TOOLS OFF CACHE BOOL "")
19+
set(YAML_CPP_BUILD_CONTRIB OFF CACHE BOOL "")
20+
set(YAML_CPP_INSTALL OFF CACHE BOOL "")
21+
add_subdirectory(yaml-cpp)
22+
23+
target_include_directories(yaml-cpp PUBLIC yaml-cpp/include)
24+
endif()
2325

2426
## css-color-parser-cpp ##
2527
##########################
@@ -48,14 +50,21 @@ target_include_directories(miniz
4850
if(NOT TANGRAM_USE_SYSTEM_FONT_LIBS)
4951
## Harfbuzz - ICU-Common - Freetype2 ##
5052
#######################################
51-
set(HARFBUZZ_BUILD_ICU ON CACHE BOOL "Enable building of ICU")
52-
add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/harfbuzz-icu-freetype)
53-
54-
message(STATUS "harfbuzz" ${HARFBUZZ_LIBRARIES})
53+
if(WIN32)
54+
#find_package(ICU REQUIRED COMPONENTS common)
55+
find_package(harfbuzz CONFIG REQUIRED)
56+
set(HARFBUZZ_LIB_NAME harfbuzz::harfbuzz)
57+
else()
58+
set(HARFBUZZ_BUILD_ICU ON CACHE BOOL "Enable building of ICU")
59+
add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/harfbuzz-icu-freetype)
60+
61+
message(STATUS "harfbuzz" ${HARFBUZZ_LIBRARIES})
62+
set(HARFBUZZ_LIB_NAME harfbuzz ${HARFBUZZ_LIBRARIES})
63+
endif()
5564

5665
set(ALFONS_DEPS_LIBRARIES
5766
${ALFONS_DEPS_LIBRARIES}
58-
harfbuzz ${HARFBUZZ_LIBRARIES}
67+
${HARFBUZZ_LIB_NAME}
5968
CACHE INTERNAL "alfons-libs" FORCE)
6069
endif()
6170

‎core/deps/pbf/pbf.hpp

+5-1
Original file line numberDiff line numberDiff line change
@@ -26,9 +26,13 @@
2626
#endif
2727

2828
namespace protobuf {
29-
29+
#if defined(__GNUC__)
3030
#define FORCEINLINE inline __attribute__((always_inline))
3131
#define NOINLINE __attribute__((noinline))
32+
#else
33+
#define FORCEINLINE inline
34+
#define NOINLINE
35+
#endif
3236
#define PBF_INLINE FORCEINLINE
3337

3438
class message {

‎core/include/tangram/log.h

+4
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,11 @@ static constexpr const char * past_last_slash(const char * const str) {
2727
return past_last_slash(str, str);
2828
}
2929

30+
#ifdef TANGRAM_WINDOWS
31+
#define __FILENAME__ __FILE__
32+
#else
3033
#define __FILENAME__ ({constexpr const char * const sf__ {past_last_slash(__FILE__)}; sf__;})
34+
#endif
3135

3236
#define TANGRAM_MAX_BUFFER_LOG_SIZE 99999
3337

‎core/include/tangram/tile/tileID.h

+1
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
#include <cassert>
44
#include <cstdint>
55
#include <string>
6+
#include <algorithm>
67

78
/* An immutable identifier for a map tile
89
*

‎core/include/tangram/util/variant.h

+9-1
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,15 @@ using Value = variant<none_type, double, std::string>;
5555

5656
class Value : public detail::Value {
5757
using Base = detail::Value;
58-
using Base::Base;
58+
59+
public:
60+
Value(): Base() {}
61+
62+
template<typename T>
63+
Value(const T& val): Base(val) {}
64+
65+
template<typename T>
66+
Value(T&& val): Base(val) {}
5967
};
6068

6169
const static Value NOT_A_VALUE(none_type{});

‎core/src/data/rasterSource.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -208,7 +208,7 @@ std::shared_ptr<Texture> RasterSource::cacheTexture(const TileID& _tileId, std::
208208
}
209209

210210
texture = std::shared_ptr<Texture>(_texture.release(),
211-
[c = std::weak_ptr<Cache>(m_textures), id](auto t) {
211+
[c = std::weak_ptr<Cache>(m_textures), id](auto* t) {
212212
if (auto cache = c.lock()) {
213213
cache->erase(id);
214214
LOGD("%d - remove %s", cache->size(), id.toString().c_str());

‎core/src/debug/textDisplay.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,7 @@ void TextDisplay::draw(RenderState& rs, const std::string& _text, int _posx, int
8989
std::vector<glm::vec2> vertices;
9090
int nquads;
9191

92-
nquads = stb_easy_font_print(_posx, _posy, _text.c_str(), NULL, m_vertexBuffer, VERTEX_BUFFER_SIZE);
92+
nquads = stb_easy_font_print(_posx, _posy, const_cast<char*>(_text.c_str()), NULL, m_vertexBuffer, VERTEX_BUFFER_SIZE);
9393

9494
float* data = reinterpret_cast<float*>(m_vertexBuffer);
9595

‎core/src/gl/framebuffer.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -147,7 +147,7 @@ void FrameBuffer::init(RenderState& _rs) {
147147
}
148148

149149
GLenum status = GL::checkFramebufferStatus(GL_FRAMEBUFFER);
150-
GL_CHECK();
150+
GL_CHECK({});
151151

152152
if (status != GL_FRAMEBUFFER_COMPLETE) {
153153
LOGE("Framebuffer status is incomplete:");

‎core/src/scene/importer.cpp

+4
Original file line numberDiff line numberDiff line change
@@ -188,7 +188,11 @@ void Importer::addSceneYaml(const Url& sceneUrl, const char* sceneYaml, size_t l
188188
auto& sceneNode = m_sceneNodes[sceneUrl];
189189

190190
try {
191+
#ifdef TANGRAM_WINDOWS
192+
sceneNode.yaml = YAML::Load(sceneYaml);
193+
#else
191194
sceneNode.yaml = YAML::Load(sceneYaml, length);
195+
#endif
192196
} catch (const YAML::ParserException& e) {
193197
LOGE("Parsing scene config '%s'", e.what());
194198
return;

‎core/src/scene/sceneLoader.cpp

+15-15
Original file line numberDiff line numberDiff line change
@@ -145,7 +145,7 @@ void SceneLoader::applyScene(const Node& _node, Color& backgroundColor,
145145
Stops& backgroundStops, Scene::animate& animated) {
146146
if (!_node) { return; }
147147
if (!_node.IsMap()) {
148-
LOGNode("Invalid 'scene' section", _node);
148+
LOGNode("Invalid 'scene' section", _node, "");
149149
return;
150150
}
151151

@@ -302,7 +302,7 @@ Scene::Lights SceneLoader::applyLights(const Node& _node) {
302302
}
303303
}
304304
} else if (_node) {
305-
LOGNode("Invalid 'lights'", _node);
305+
LOGNode("Invalid 'lights'", _node, "");
306306
}
307307

308308
if (lights.empty()) {
@@ -436,14 +436,14 @@ void SceneLoader::parseLightPosition(const Node& _positionNode, PointLight& _lig
436436
}
437437
_light.setPosition(positionResult);
438438
} else {
439-
LOGNode("Invalid light position parameter:", _positionNode);
439+
LOGNode("Invalid light position parameter:", _positionNode, "");
440440
}
441441
}
442442

443443
void SceneLoader::applyTextures(const Node& _node, SceneTextures& _textures) {
444444
if (!_node) { return; }
445445
if (!_node.IsMap()) {
446-
LOGNode("Invalid 'textures' section", _node);
446+
LOGNode("Invalid 'textures' section", _node, "");
447447
return;
448448
}
449449

@@ -543,7 +543,7 @@ bool SceneLoader::parseTexFiltering(const Node& _filteringNode, TextureOptions&
543543
void SceneLoader::applyFonts(const Node& _node, SceneFonts& _fonts) {
544544
if (!_node) { return; }
545545
if (!_node.IsMap()) {
546-
LOGNode("Invalid 'fonts' section", _node);
546+
LOGNode("Invalid 'fonts' section", _node, "");
547547
return;
548548
}
549549

@@ -570,7 +570,7 @@ void SceneLoader::applyFonts(const Node& _node, SceneFonts& _fonts) {
570570
void SceneLoader::loadFontDescription(const Node& _node, const std::string& _family, SceneFonts& _fonts) {
571571
if (!_node) { return; }
572572
if (!_node.IsMap()) {
573-
LOGNode("Invalid 'font' section", _node);
573+
LOGNode("Invalid 'font' section", _node, "");
574574
return;
575575
}
576576

@@ -634,18 +634,18 @@ Scene::TileSources SceneLoader::applySources(const Node& _config, const SceneOpt
634634

635635
if (const Node& rasters = source.second["rasters"]) {
636636
if (!rasters.IsSequence()) {
637-
LOGNode("Invalid 'rasters'", rasters);
637+
LOGNode("Invalid 'rasters'", rasters, "");
638638
continue;
639639
}
640640
for (const auto& raster : rasters) {
641641
if (!raster.IsScalar()) {
642-
LOGNode("Invalid 'raster'", raster);
642+
LOGNode("Invalid 'raster'", raster, "");
643643
continue;
644644
}
645645
if (auto rasterSource = getTileSource(raster.Scalar())) {
646646
tileSource->addRasterSource(rasterSource);
647647
} else {
648-
LOGNode("Missing raster source", raster);
648+
LOGNode("Missing raster source", raster, "");
649649
}
650650
}
651651
}
@@ -676,7 +676,7 @@ Scene::TileSources SceneLoader::applySources(const Node& _config, const SceneOpt
676676
if (!data_source) { continue;}
677677

678678
if (!data_source.IsScalar()) {
679-
LOGNode("Invalid 'source", data);
679+
LOGNode("Invalid 'source", data, "");
680680
continue;
681681
}
682682
auto source = data_source.Scalar();
@@ -875,7 +875,7 @@ Scene::Styles SceneLoader::applyStyles(const Node& _node, SceneTextures& _textur
875875

876876
if (!_node) { return styles; }
877877
if (!_node.IsMap()) {
878-
LOGNode("Invalid 'styles' section", _node);
878+
LOGNode("Invalid 'styles' section", _node, "");
879879
return styles;
880880
}
881881

@@ -1256,7 +1256,7 @@ void SceneLoader::loadShaderConfig(const Node& _shaders, Style& _style, SceneTex
12561256

12571257
_style.styleUniforms().emplace_back(name, styleUniform.value);
12581258
} else {
1259-
LOGNode("Style uniform parsing failure", uniform.second);
1259+
LOGNode("Style uniform parsing failure", uniform.second, "");
12601260
}
12611261
}
12621262
}
@@ -1387,7 +1387,7 @@ void SceneLoader::loadMaterial(const Node& _matNode, Material& _material, Style&
13871387
// Handled as texture
13881388
break;
13891389
default:
1390-
LOGNode("Invalid 'material'", prop);
1390+
LOGNode("Invalid 'material'", prop, "");
13911391
break;
13921392
}
13931393
return glm::vec4(0.0);
@@ -1441,7 +1441,7 @@ MaterialTexture SceneLoader::loadMaterialTexture(const Node& _matCompNode, Style
14411441

14421442
Node textureNode = _matCompNode["texture"];
14431443
if (!textureNode) {
1444-
LOGNode("Expected a 'texture' parameter", _matCompNode);
1444+
LOGNode("Expected a 'texture' parameter", _matCompNode, "");
14451445

14461446
return MaterialTexture{};
14471447
}
@@ -1501,7 +1501,7 @@ std::vector<DataLayer> SceneLoader::applyLayers(const Node& _node, SceneFunctio
15011501
SceneStops& _stops, DrawRuleNames& _ruleNames) {
15021502
if (!_node) { return {}; }
15031503
if (!_node.IsMap()) {
1504-
LOGNode("Invalid 'layers' section", _node);
1504+
LOGNode("Invalid 'layers' section", _node, "");
15051505
return {};
15061506
}
15071507

‎core/src/scene/stops.cpp

+24-19
Original file line numberDiff line numberDiff line change
@@ -266,15 +266,16 @@ auto Stops::Numbers(const YAML::Node& node) -> Stops {
266266
auto Stops::evalExpFloat(float _key) const -> float {
267267
if (frames.empty()) { return 0; }
268268

269+
if (_key <= frames[0].key) {
270+
return frames[0].value.get<float>();
271+
}
272+
269273
auto upper = nearestHigherFrame(_key);
270274
auto lower = upper - 1;
271275

272276
if (upper == frames.end()) {
273277
return lower->value.get<float>();
274278
}
275-
if (lower < frames.begin()) {
276-
return upper->value.get<float>();
277-
}
278279

279280
if (upper->key <= _key) {
280281
return upper->value.get<float>();
@@ -294,15 +295,16 @@ auto Stops::evalExpFloat(float _key) const -> float {
294295
auto Stops::evalFloat(float _key) const -> float {
295296
if (frames.empty()) { return 0; }
296297

298+
if (_key <= frames[0].key) {
299+
return frames[0].value.get<float>();
300+
}
301+
297302
auto upper = nearestHigherFrame(_key);
298303
auto lower = upper - 1;
299304

300305
if (upper == frames.end()) {
301306
return lower->value.get<float>();
302307
}
303-
if (lower < frames.begin()) {
304-
return upper->value.get<float>();
305-
}
306308

307309
float lerp = (_key - lower->key) / (upper->key - lower->key);
308310

@@ -312,14 +314,15 @@ auto Stops::evalFloat(float _key) const -> float {
312314
auto Stops::evalColor(float _key) const -> uint32_t {
313315
if (frames.empty()) { return 0; }
314316

317+
if (_key <= frames[0].key) {
318+
return frames[0].value.get<Color>().abgr;
319+
}
320+
315321
auto upper = nearestHigherFrame(_key);
316322
auto lower = upper - 1;
317323
if (upper == frames.end()) {
318324
return lower->value.get<Color>().abgr;
319325
}
320-
if (lower < frames.begin()) {
321-
return upper->value.get<Color>().abgr;
322-
}
323326

324327
float lerp = (_key - lower->key) / (upper->key - lower->key);
325328

@@ -329,15 +332,16 @@ auto Stops::evalColor(float _key) const -> uint32_t {
329332
auto Stops::evalExpVec2(float _key) const -> glm::vec2 {
330333
if (frames.empty()) { return glm::vec2{0.f}; }
331334

335+
if (_key <= frames[0].key) {
336+
return frames[0].value.get<glm::vec2>();
337+
}
338+
332339
auto upper = nearestHigherFrame(_key);
333340
auto lower = upper - 1;
334341

335342
if (upper == frames.end()) {
336343
return lower->value.get<glm::vec2>();
337344
}
338-
if (lower < frames.begin()) {
339-
return upper->value.get<glm::vec2>();
340-
}
341345

342346
double range = exp2(upper->key - lower->key) - 1.0;
343347
double pos = exp2(_key - lower->key) - 1.0;
@@ -349,21 +353,21 @@ auto Stops::evalExpVec2(float _key) const -> glm::vec2 {
349353

350354
return glm::vec2(lowerVal.x * (1 - lerp) + upperVal.x * lerp,
351355
lowerVal.y * (1 - lerp) + upperVal.y * lerp);
352-
353356
}
354357

355358
auto Stops::evalVec2(float _key) const -> glm::vec2 {
356359
if (frames.empty()) { return glm::vec2{0.f}; }
357360

361+
if (_key <= frames[0].key) {
362+
return frames[0].value.get<glm::vec2>();
363+
}
364+
358365
auto upper = nearestHigherFrame(_key);
359366
auto lower = upper - 1;
360367

361368
if (upper == frames.end()) {
362369
return lower->value.get<glm::vec2>();
363370
}
364-
if (lower < frames.begin()) {
365-
return upper->value.get<glm::vec2>();
366-
}
367371

368372
float lerp = (_key - lower->key) / (upper->key - lower->key);
369373

@@ -379,15 +383,16 @@ auto Stops::evalSize(float _key, const glm::vec2& _cssSize) const -> glm::vec2 {
379383

380384
if (frames.empty()) { return {NAN, NAN}; }
381385

386+
if (_key <= frames[0].key) {
387+
return frames[0].value.get<StyleParam::SizeValue>().getSizePixels(_cssSize);
388+
}
389+
382390
auto upper = nearestHigherFrame(_key);
383391
auto lower = upper - 1;
384392

385393
if (upper == frames.end()) {
386394
return lower->value.get<StyleParam::SizeValue>().getSizePixels(_cssSize);
387395
}
388-
if (lower < frames.begin()) {
389-
return upper->value.get<StyleParam::SizeValue>().getSizePixels(_cssSize);
390-
}
391396

392397
double range = exp2(upper->key - lower->key) - 1.0;
393398
double pos = exp2(_key - lower->key) - 1.0;

‎core/src/text/textUtil.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ int TextWrapper::draw(alfons::TextBatch& _batch, float _maxWidth, const alfons::
6767
TextLabelProperty::Align _alignment, float _lineSpacing,
6868
alfons::LineMetrics& _layoutMetrics) {
6969
size_t shapeStart = 0;
70-
glm::vec2 position;
70+
glm::vec2 position{};
7171

7272
for (auto wrap : m_lineWraps) {
7373
alfons::LineMetrics lineMetrics;

‎core/src/util/floatFormatter.h

+2-2
Original file line numberDiff line numberDiff line change
@@ -20,14 +20,14 @@ struct ff {
2020

2121
static double stod(const std::string& _string) {
2222
int end = 0;
23-
return stod(_string.data(), _string.size(), &end);
23+
return stod(_string.data(), static_cast<int>(_string.size()), &end);
2424
}
2525

2626
static float stof(const char* _string, int _length, int* _end);
2727

2828
static float stof(const std::string& _string) {
2929
int end = 0;
30-
return stof(_string.data(), _string.size(), &end);
30+
return stof(_string.data(), static_cast<int>(_string.size()), &end);
3131
}
3232

3333
};

‎core/src/util/geom.h

+3-3
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@ float signedArea(InputIt begin, InputIt end) {
7272
float area = 0;
7373
auto prev = end - 1;
7474
for (auto curr = begin; curr != end; ++curr) {
75-
area += curr->x * prev->y - curr->y * prev->x;
75+
area += static_cast<float>(curr->x * prev->y - curr->y * prev->x);
7676
prev = curr;
7777
}
7878
return 0.5f * area;
@@ -82,14 +82,14 @@ float signedArea(InputIt begin, InputIt end) {
8282
/// If the polygon has no area, the coordinates returned are NaN.
8383
template<class InputIt, class Vector = typename InputIt::value_type>
8484
Vector centroid(InputIt begin, InputIt end) {
85-
Vector centroid;
85+
Vector centroid{};
8686
float area = 0.f;
8787
const Vector offset(begin->x, begin->y);
8888

8989
for (auto curr = begin, prev = end - 1; curr != end; prev = curr, ++curr) {
9090
const Vector prevPoint(prev->x - offset.x, prev->y - offset.y);
9191
const Vector currPoint(curr->x - offset.x, curr->y - offset.y);
92-
float a = (prevPoint.x * currPoint.y - currPoint.x * prevPoint.y);
92+
float a = static_cast<float>(prevPoint.x * currPoint.y - currPoint.x * prevPoint.y);
9393
centroid.x += (prevPoint.x + currPoint.x) * a;
9494
centroid.y += (prevPoint.y + currPoint.y) * a;
9595
area += a;

‎core/src/util/url.cpp

+10-1
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
#include <cstdlib>
44
#include <cassert>
5+
#include <algorithm>
56

67
namespace Tangram {
78

@@ -321,6 +322,13 @@ std::string Url::removeDotSegmentsFromString(std::string path) {
321322

322323
void Url::parse() {
323324

325+
// Normalize Windows paths. Chromium also does this.
326+
for(auto &c: buffer) {
327+
if(c == '\\') {
328+
c = '/';
329+
}
330+
}
331+
324332
// The parsing process roughly follows https://tools.ietf.org/html/rfc1808#section-2.4
325333

326334
size_t start = 0;
@@ -351,7 +359,8 @@ void Url::parse() {
351359
}
352360

353361
// If a scheme is present, it must be followed by a ':'.
354-
if (c == ':') {
362+
// Check if 'scheme' is longer than 1 - could be a Windows disk drive
363+
if (c == ':' && i - start > 1) {
355364
parts.scheme.start = start;
356365
parts.scheme.count = i - start;
357366

‎platforms/common/glfwApp.cpp

+23-11
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,12 @@
33
#include "imgui_impl_glfw.h"
44
#include "imgui_impl_opengl3.h"
55
#include "imgui_stl.h"
6+
7+
#ifdef TANGRAM_WINDOWS
8+
#define GLFW_INCLUDE_NONE
9+
#include <glad/glad.h>
10+
#endif // TANGRAM_WINDOWS
11+
612
#define GLFW_INCLUDE_GLEXT
713
#define GL_SILENCE_DEPRECATION
814
#include <GLFW/glfw3.h>
@@ -203,6 +209,10 @@ void create(std::unique_ptr<Platform> p, int w, int h) {
203209
glfwMakeContextCurrent(main_window);
204210
glfwSwapInterval(1); // Enable vsync
205211

212+
#ifdef TANGRAM_WINDOWS
213+
gladLoadGLLoader((GLADloadproc) glfwGetProcAddress);
214+
#endif
215+
206216
// Set input callbacks
207217
glfwSetFramebufferSizeCallback(main_window, framebufferResizeCallback);
208218
glfwSetMouseButtonCallback(main_window, mouseButtonCallback);
@@ -535,17 +545,19 @@ void keyCallback(GLFWwindow* window, int key, int scancode, int action, int mods
535545
map->loadSceneYamlAsync("{ scene: { background: { color: red } } }", std::string(""));
536546
break;
537547
case GLFW_KEY_G:
538-
static bool geoJSON = false;
539-
if (!geoJSON) {
540-
loadSceneFile(false,
541-
{ SceneUpdate{"sources.osm.type", "GeoJSON"},
542-
SceneUpdate{"sources.osm.url", "https://tile.mapzen.com/mapzen/vector/v1/all/{z}/{x}/{y}.json"}});
543-
} else {
544-
loadSceneFile(false,
545-
{ SceneUpdate{"sources.osm.type", "MVT"},
546-
SceneUpdate{"sources.osm.url", "https://tile.mapzen.com/mapzen/vector/v1/all/{z}/{x}/{y}.mvt"}});
548+
{
549+
static bool geoJSON = false;
550+
if (!geoJSON) {
551+
loadSceneFile(false,
552+
{ SceneUpdate{"sources.osm.type", "GeoJSON"},
553+
SceneUpdate{"sources.osm.url", "https://tile.mapzen.com/mapzen/vector/v1/all/{z}/{x}/{y}.json"}});
554+
} else {
555+
loadSceneFile(false,
556+
{ SceneUpdate{"sources.osm.type", "MVT"},
557+
SceneUpdate{"sources.osm.url", "https://tile.mapzen.com/mapzen/vector/v1/all/{z}/{x}/{y}.mvt"}});
558+
}
559+
geoJSON = !geoJSON;
547560
}
548-
geoJSON = !geoJSON;
549561
break;
550562
case GLFW_KEY_ESCAPE:
551563
glfwSetWindowShouldClose(window, true);
@@ -603,7 +615,7 @@ void keyCallback(GLFWwindow* window, int key, int scancode, int action, int mods
603615
case GLFW_KEY_W:
604616
map->onMemoryWarning();
605617
break;
606-
default:
618+
default:
607619
break;
608620
}
609621
}

‎platforms/common/platform_gl.cpp

+8-8
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ GLenum GL::getError() {
1111

1212
const GLubyte* GL::getString(GLenum name) {
1313
auto result = glGetString(name);
14-
GL_CHECK();
14+
GL_CHECK({});
1515
return result;
1616
}
1717

@@ -86,12 +86,12 @@ void GL::deleteShader(GLuint shader) {
8686
}
8787
GLuint GL::createShader(GLenum type) {
8888
auto result = glCreateShader(type);
89-
GL_CHECK();
89+
GL_CHECK({});
9090
return result;
9191
}
9292
GLuint GL::createProgram() {
9393
auto result = glCreateProgram();
94-
GL_CHECK();
94+
GL_CHECK({});
9595
return result;
9696
}
9797

@@ -117,12 +117,12 @@ void GL::getProgramInfoLog(GLuint program, GLsizei bufSize, GLsizei *length, GLc
117117
}
118118
GLint GL::getUniformLocation(GLuint program, const GLchar *name) {
119119
auto result = glGetUniformLocation(program, name);
120-
GL_CHECK();
120+
GL_CHECK({});
121121
return result;
122122
}
123123
GLint GL::getAttribLocation(GLuint program, const GLchar *name) {
124124
auto result = glGetAttribLocation(program, name);
125-
GL_CHECK();
125+
GL_CHECK({});
126126
return result;
127127
}
128128
void GL::getProgramiv(GLuint program, GLenum pname, GLint *params) {
@@ -263,12 +263,12 @@ void GL::uniformMatrix4fv(GLint location, GLsizei count, GLboolean transpose, co
263263
// mapbuffer
264264
void* GL::mapBuffer(GLenum target, GLenum access) {
265265
auto result = glMapBuffer(target, access);
266-
GL_CHECK();
266+
GL_CHECK({});
267267
return result;
268268
}
269269
GLboolean GL::unmapBuffer(GLenum target) {
270270
auto result = glUnmapBuffer(target);
271-
GL_CHECK();
271+
GL_CHECK({});
272272
return result;
273273
}
274274

@@ -329,7 +329,7 @@ void GL::deleteRenderbuffers(GLsizei n, const GLuint *renderbuffers) {
329329

330330
GLenum GL::checkFramebufferStatus(GLenum target) {
331331
GLenum status = glCheckFramebufferStatus(target);
332-
GL_CHECK();
332+
GL_CHECK({});
333333
return status;
334334
}
335335

‎platforms/common/platform_gl.h

+9
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,15 @@ extern PFNGLGENVERTEXARRAYSOESPROC glGenVertexArraysOESEXT;
4545
#include <GLFW/glfw3.h>
4646
#endif // TANGRAM_LINUX
4747

48+
#ifdef TANGRAM_WINDOWS
49+
#define GL_GLEXT_PROTOTYPES
50+
#include <glad/glad.h>
51+
#include <GLFW/glfw3.h>
52+
// Resolve aliased names on Windows
53+
#define glClearDepthf glClearDepth
54+
#define glDepthRangef glDepthRange
55+
#endif // TANGRAM_WINDOWS
56+
4857
#ifdef TANGRAM_RPI
4958
// Broadcom library for direct GPU access
5059
#include "bcm_host.h"

‎platforms/common/urlClient.cpp

+96-7
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,9 @@
44
#include <cassert>
55
#include <cstring>
66
#include <curl/curl.h>
7+
#ifndef _MSC_VER
78
#include <unistd.h>
9+
#endif
810
#include <time.h>
911

1012
constexpr char const* requestCancelledError = "Request cancelled";
@@ -22,6 +24,92 @@ struct CurlGlobals {
2224
}
2325
} s_curl;
2426

27+
UrlClient::SelfPipe::~SelfPipe() {
28+
#if defined(_WIN32)
29+
if(pipeFds[0] != SocketInvalid) {
30+
closesocket(pipeFds[0]);
31+
}
32+
if(pipeFds[1] != SocketInvalid) {
33+
closesocket(pipeFds[1]);
34+
}
35+
#endif
36+
}
37+
38+
bool UrlClient::SelfPipe::initialize() {
39+
#if defined(_WIN32)
40+
// https://stackoverflow.com/questions/3333361/how-to-cancel-waiting-in-select-on-windows
41+
struct sockaddr_in inaddr;
42+
int len = sizeof(inaddr);
43+
memset(&inaddr, 0, len);
44+
struct sockaddr addr;
45+
memset(&addr, 0, sizeof(addr));
46+
47+
inaddr.sin_family = AF_INET;
48+
inaddr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
49+
inaddr.sin_port = 0;
50+
int yes = 1;
51+
SOCKET lst = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
52+
if(lst == INVALID_SOCKET) {
53+
return false;
54+
}
55+
if(
56+
setsockopt(lst, SOL_SOCKET, SO_REUSEADDR, (char*)&yes, sizeof(yes)) == SOCKET_ERROR ||
57+
bind(lst, (struct sockaddr *)&inaddr, sizeof(inaddr)) == SOCKET_ERROR ||
58+
listen(lst, 1) == SOCKET_ERROR ||
59+
getsockname(lst, &addr, &len) ||
60+
(pipeFds[0] = socket(AF_INET, SOCK_STREAM, 0)) == INVALID_SOCKET
61+
) {
62+
closesocket(lst);
63+
return false;
64+
}
65+
66+
if(
67+
(connect(pipeFds[0], &addr, len)) == SOCKET_ERROR ||
68+
(pipeFds[1] = accept(lst, 0, 0)) == INVALID_SOCKET
69+
) {
70+
closesocket(pipeFds[0]);
71+
closesocket(lst);
72+
pipeFds[0] = -1;
73+
return false;
74+
}
75+
76+
closesocket(lst);
77+
return true;
78+
#else
79+
return pipe(pipeFds) >= 0;
80+
#endif
81+
}
82+
83+
bool UrlClient::SelfPipe::write() {
84+
#if defined(_WIN32)
85+
return send(pipeFds[1], "\0", 1, 0) >= 0;
86+
#else
87+
return ::write(pipeFds[1], "\0", 1) >= 0;
88+
#endif
89+
}
90+
91+
bool UrlClient::SelfPipe::read(int *error) {
92+
char buffer[1];
93+
#if defined(_WIN32)
94+
int n = recv(pipeFds[0], buffer, sizeof(buffer), 0);
95+
if(n == SOCKET_ERROR) {
96+
*error = WSAGetLastError();
97+
return false;
98+
}
99+
#else
100+
int n = ::read(pipeFds[0], buffer, sizeof(buffer));
101+
if (n <= 0) {
102+
*error = n;
103+
return false;
104+
}
105+
#endif
106+
return true;
107+
}
108+
109+
UrlClient::SelfPipe::Socket UrlClient::SelfPipe::getReadFd() {
110+
return pipeFds[0];
111+
}
112+
25113
struct UrlClient::Task {
26114
// Reduce Task content capacity when it's more than 128kb and last
27115
// content size was less then half limit_capacity.
@@ -108,7 +196,7 @@ UrlClient::UrlClient(Options options) : m_options(options) {
108196

109197
// Using a pipe to notify select() in curl-thread of new requests..
110198
// https://www.linuxquestions.org/questions/programming-9/exit-from-blocked-pselect-661200/
111-
if (pipe(m_requestNotify) < 0) {
199+
if (!m_requestNotify.initialize()) {
112200
LOGE("Could not initialize select breaker!");
113201
}
114202
}
@@ -155,7 +243,7 @@ UrlClient::~UrlClient() {
155243
void UrlClient::curlWakeUp() {
156244

157245
if (!m_curlNotified) {
158-
if (write(m_requestNotify[1], "\0", 1) <= 0) {
246+
if (!m_requestNotify.write()) {
159247
// err
160248
return;
161249
}
@@ -293,7 +381,7 @@ void UrlClient::curlLoop() {
293381
}
294382

295383
// Listen on requestNotify to break select when new requests are added.
296-
FD_SET(m_requestNotify[0], &fdread);
384+
FD_SET(m_requestNotify.getReadFd(), &fdread);
297385

298386
// Wait for transfers
299387
// On success the value of maxfd is guaranteed to be >= -1. We call
@@ -307,11 +395,12 @@ void UrlClient::curlLoop() {
307395
continue;
308396

309397
} else {
310-
if (FD_ISSET(m_requestNotify[0], &fdread)) {
398+
if (FD_ISSET(m_requestNotify.getReadFd(), &fdread)) {
311399
// Clear notify fd
312-
char buffer[1];
313-
int n = read(m_requestNotify[0], buffer, sizeof(buffer));
314-
if (n <= 0) { LOGE("Read request notify %d", n); }
400+
int error;
401+
if(!m_requestNotify.read(&error)) {
402+
LOGE("Read request notify %d", error);
403+
}
315404
//LOG("Got request notifies %d %d", n, m_curlNotified);
316405
m_curlNotified = false;
317406
}

‎platforms/common/urlClient.h

+22-1
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,9 @@
1313
#include <thread>
1414
#include <vector>
1515

16+
#if defined(_WIN32)
17+
#include <winsock2.h>
18+
#endif
1619

1720
namespace Tangram {
1821

@@ -44,6 +47,24 @@ class UrlClient {
4447
RequestId id;
4548
};
4649

50+
class SelfPipe {
51+
public:
52+
#if defined(_WIN32)
53+
using Socket = SOCKET;
54+
const Socket SocketInvalid = INVALID_SOCKET;
55+
#else
56+
using Socket = int;
57+
const Socket SocketInvalid = -1;
58+
#endif
59+
~SelfPipe();
60+
bool initialize();
61+
bool write();
62+
bool read(int *error);
63+
Socket getReadFd();
64+
private:
65+
Socket pipeFds[2] = { SocketInvalid, SocketInvalid };
66+
};
67+
4768
struct Task;
4869

4970
void curlLoop();
@@ -74,7 +95,7 @@ class UrlClient {
7495
std::atomic<uint64_t> m_requestCount{0};
7596

7697
// File descriptors to break waiting select.
77-
int m_requestNotify[2] = { -1, -1 };
98+
SelfPipe m_requestNotify;
7899
};
79100

80101
} // namespace Tangram

‎platforms/windows/config.cmake

+48
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
if (CMAKE_CXX_COMPILER_ID MATCHES "Clang")
2+
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-gnu-zero-variadic-macro-arguments")
3+
endif()
4+
5+
check_unsupported_compiler_version()
6+
7+
add_definitions(-DTANGRAM_WINDOWS)
8+
9+
find_package(OpenGL REQUIRED)
10+
find_package(CURL REQUIRED)
11+
12+
include(cmake/glfw.cmake)
13+
14+
add_executable(tangram
15+
platforms/windows/src/windowsPlatform.cpp
16+
platforms/windows/src/main.cpp
17+
platforms/common/platform_gl.cpp
18+
platforms/common/urlClient.cpp
19+
platforms/common/glfwApp.cpp
20+
platforms/common/imgui_impl_glfw.cpp
21+
platforms/common/imgui_impl_opengl3.cpp
22+
platforms/common/glfw/deps/glad.c
23+
)
24+
25+
add_resources(tangram "${PROJECT_SOURCE_DIR}/scenes" "res")
26+
27+
add_subdirectory(platforms/common/imgui)
28+
29+
target_include_directories(tangram
30+
PRIVATE
31+
platforms/common
32+
platforms/common/glfw/deps
33+
${CURL_INCLUDE_DIRS}
34+
)
35+
36+
target_link_libraries(tangram
37+
PRIVATE
38+
tangram-core
39+
glfw
40+
imgui
41+
${GLFW_LIBRARIES}
42+
${OPENGL_LIBRARIES}
43+
${CURL_LIBRARIES}
44+
wsock32 ws2_32 crypt32 wldap32
45+
)
46+
47+
get_nextzen_api_key(NEXTZEN_API_KEY)
48+
target_compile_definitions(tangram PRIVATE NEXTZEN_API_KEY="${NEXTZEN_API_KEY}")

‎platforms/windows/src/main.cpp

+39
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
#include "glfwApp.h"
2+
#include "windowsPlatform.h"
3+
#include "log.h"
4+
#include "map.h"
5+
#include <memory>
6+
#include <direct.h> // _getcwd
7+
8+
#define PATH_MAX 512
9+
10+
using namespace Tangram;
11+
12+
int main(int argc, char* argv[]) {
13+
14+
// Create the windowed app.
15+
GlfwApp::create(std::make_unique<WindowsPlatform>(), 1024, 768);
16+
17+
GlfwApp::sceneFile = "res/scene.yaml";
18+
GlfwApp::parseArgs(argc, argv);
19+
20+
// Resolve the input path against the current directory.
21+
Url baseUrl("file://");
22+
char pathBuffer[PATH_MAX] = {0};
23+
if (getcwd(pathBuffer, PATH_MAX) != nullptr) {
24+
baseUrl = baseUrl.resolve(Url(std::string(pathBuffer) + "/"));
25+
}
26+
27+
LOG("Base URL: %s", baseUrl.string().c_str());
28+
29+
Url sceneUrl = baseUrl.resolve(Url(GlfwApp::sceneFile));
30+
GlfwApp::sceneFile = sceneUrl.string();
31+
32+
// Loop until the user closes the window
33+
GlfwApp::run();
34+
35+
// Clean up.
36+
GlfwApp::destroy();
37+
38+
return 0;
39+
}
+77
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
#include "windowsPlatform.h"
2+
#include "gl/hardware.h"
3+
#include "log.h"
4+
#include <stdio.h>
5+
#include <stdarg.h>
6+
7+
#include <GLFW/glfw3.h>
8+
9+
#define DEFAULT "res/fonts/NotoSans-Regular.ttf"
10+
#define FONT_AR "res/fonts/NotoNaskh-Regular.ttf"
11+
#define FONT_HE "res/fonts/NotoSansHebrew-Regular.ttf"
12+
#define FONT_JA "res/fonts/DroidSansJapanese.ttf"
13+
#define FALLBACK "res/fonts/DroidSansFallback.ttf"
14+
15+
namespace Tangram {
16+
17+
void logMsg(const char* fmt, ...) {
18+
va_list args;
19+
va_start(args, fmt);
20+
vfprintf(stderr, fmt, args);
21+
va_end(args);
22+
}
23+
24+
WindowsPlatform::WindowsPlatform()
25+
: WindowsPlatform(UrlClient::Options{}) {}
26+
27+
WindowsPlatform::WindowsPlatform(UrlClient::Options urlClientOptions) :
28+
m_urlClient(std::make_unique<UrlClient>(urlClientOptions)) {
29+
}
30+
31+
WindowsPlatform::~WindowsPlatform() {}
32+
33+
void WindowsPlatform::shutdown() {
34+
// Stop all UrlWorker threads
35+
m_urlClient.reset();
36+
37+
Platform::shutdown();
38+
}
39+
40+
void WindowsPlatform::requestRender() const {
41+
if (m_shutdown) { return; }
42+
glfwPostEmptyEvent();
43+
}
44+
45+
std::vector<FontSourceHandle> WindowsPlatform::systemFontFallbacksHandle() const {
46+
std::vector<FontSourceHandle> handles;
47+
48+
handles.emplace_back(Url(DEFAULT));
49+
handles.emplace_back(Url(FONT_AR));
50+
handles.emplace_back(Url(FONT_HE));
51+
handles.emplace_back(Url(FONT_JA));
52+
handles.emplace_back(Url(FALLBACK));
53+
54+
return handles;
55+
}
56+
57+
bool WindowsPlatform::startUrlRequestImpl(const Url& _url, const UrlRequestHandle _request, UrlRequestId& _id) {
58+
auto onURLResponse = [this, _request](UrlResponse&& response) {
59+
onUrlResponse(_request, std::move(response));
60+
};
61+
_id = m_urlClient->addRequest(_url.string(), onURLResponse);
62+
return false;
63+
}
64+
65+
void WindowsPlatform::cancelUrlRequestImpl(const UrlRequestId _id) {
66+
if (m_urlClient) {
67+
m_urlClient->cancelRequest(_id);
68+
}
69+
}
70+
71+
void setCurrentThreadPriority(int priority) {}
72+
73+
void initGLExtensions() {
74+
Tangram::Hardware::supportsMapBuffer = true;
75+
}
76+
77+
} // namespace Tangram
+25
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
#pragma once
2+
3+
#include "platform.h"
4+
#include "urlClient.h"
5+
6+
namespace Tangram {
7+
8+
class WindowsPlatform : public Platform {
9+
10+
public:
11+
12+
WindowsPlatform();
13+
explicit WindowsPlatform(UrlClient::Options urlClientOptions);
14+
~WindowsPlatform() override;
15+
void shutdown() override;
16+
void requestRender() const override;
17+
std::vector<FontSourceHandle> systemFontFallbacksHandle() const override;
18+
bool startUrlRequestImpl(const Url& _url, const UrlRequestHandle _request, UrlRequestId& _id) override;
19+
void cancelUrlRequestImpl(const UrlRequestId _id) override;
20+
21+
protected:
22+
std::unique_ptr<UrlClient> m_urlClient;
23+
};
24+
25+
} // namespace Tangram

‎tests/src/mockPlatform.cpp

+8
Original file line numberDiff line numberDiff line change
@@ -6,14 +6,22 @@
66
#include <fstream>
77
#include <string>
88

9+
#ifndef TANGRAM_WINDOWS
910
#include <libgen.h>
1011
#include <unistd.h>
12+
#else
13+
#include <direct.h> // _getcwd
14+
#endif
1115
#include <limits.h>
1216

1317
#define DEFAULT_FONT "res/fonts/NotoSans-Regular.ttf"
1418

1519
#include "log.h"
1620

21+
#ifdef TANGRAM_WINDOWS
22+
#define PATH_MAX 512
23+
#endif
24+
1725
namespace Tangram {
1826

1927
void logMsg(const char* fmt, ...) {

‎vcpkg.json

+31
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
{
2+
"name": "tangram-es",
3+
"version-string": "0.1.0",
4+
"dependencies": [
5+
{
6+
"name":"curl",
7+
"features":[
8+
"ssl",
9+
"http2"
10+
]
11+
},
12+
"glad",
13+
"zlib",
14+
"yaml-cpp",
15+
"glfw3",
16+
"benchmark",
17+
{
18+
"name": "harfbuzz",
19+
"features": [
20+
"icu",
21+
"graphite2"
22+
]
23+
},
24+
{
25+
"name": "imgui",
26+
"features": [
27+
"docking-experimental"
28+
]
29+
}
30+
]
31+
}

0 commit comments

Comments
 (0)
Please sign in to comment.