diff --git a/AdvancedCppV2/.gitignore b/AdvancedCppV2/.gitignore new file mode 100644 index 0000000..259148f --- /dev/null +++ b/AdvancedCppV2/.gitignore @@ -0,0 +1,32 @@ +# Prerequisites +*.d + +# Compiled Object files +*.slo +*.lo +*.o +*.obj + +# Precompiled Headers +*.gch +*.pch + +# Compiled Dynamic libraries +*.so +*.dylib +*.dll + +# Fortran module files +*.mod +*.smod + +# Compiled Static libraries +*.lai +*.la +*.a +*.lib + +# Executables +*.exe +*.out +*.app diff --git a/AdvancedCppV2/LICENSE b/AdvancedCppV2/LICENSE new file mode 100644 index 0000000..d15cf3b --- /dev/null +++ b/AdvancedCppV2/LICENSE @@ -0,0 +1,19 @@ +Copyright (C) 2020 Hakim El Hattab, http://hakim.se, and reveal.js contributors + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. \ No newline at end of file diff --git a/AdvancedCppV2/Presentation/agenda.md b/AdvancedCppV2/Presentation/agenda.md new file mode 100644 index 0000000..ec1d320 --- /dev/null +++ b/AdvancedCppV2/Presentation/agenda.md @@ -0,0 +1,26 @@ + + +### Agenda + +* Cloning and building example project +* What's new since C++98 + * C++11 + * C++14 + * C++17 + * C++20 +* Smart pointers + - std::unique_ptr<> + - std::shared_ptr<> + - std::weak_ptr<> + - Best practices + - Implementation details + - Efficiency +* Templates + * Basics + * Typetraits + * Specializations + * Partial specializations + * Templates variable + * Deduction guides + + \ No newline at end of file diff --git a/AdvancedCppV2/Presentation/compilation.md b/AdvancedCppV2/Presentation/compilation.md new file mode 100644 index 0000000..fc292fa --- /dev/null +++ b/AdvancedCppV2/Presentation/compilation.md @@ -0,0 +1,46 @@ +# Cloning and building example project + +___ + + +## Setup + +* Clone repository: https://github.com/nauka-programowania-MA/AdvancedCppV2 +* Go to exercises/exampleProject +* Compile it and run: + * mkdir build + * cd build + * cmake .. + * make -j4 (where 4 is available threads) + * ./ExampleProject +* Should print Hello World + +If you don't have linux, you can use replit + +* Click Create C++ +* Name it and confirm with button Create Repl. +* Click three dot on the rigt top screen and click upload folder +* Now find your directory with repo and upload it +* Congratulation, you can use linux shell wit sanitizers, cmake and valgridn support :) + + +___ + + +## replit + +If you decided to use replit please configure this file: `replit.nix`: + +```bash +{ pkgs }: { + deps = [ + pkgs.clang_12 + pkgs.ccls + pkgs.gdb + pkgs.gnumake + pkgs.vim + pkgs.valgrind + pkgs.cmake + ]; +} +``` \ No newline at end of file diff --git a/AdvancedCppV2/Presentation/exercises/complex/CMakeLists.txt b/AdvancedCppV2/Presentation/exercises/complex/CMakeLists.txt new file mode 100644 index 0000000..1d92400 --- /dev/null +++ b/AdvancedCppV2/Presentation/exercises/complex/CMakeLists.txt @@ -0,0 +1,14 @@ +cmake_minimum_required(VERSION 3.2) + +set(CMAKE_CXX_STANDARD 17) +set(CMAKE_CXX_STANDARD_REQUIRED ON) + +project(Complex) + +set(SRC_LIST + complex.cpp +) + +add_executable(${PROJECT_NAME} ${SRC_LIST}) +target_compile_options(${PROJECT_NAME} PUBLIC -Wall -Werror -Wpedantic -Wextra) +target_include_directories(${PROJECT_NAME} PUBLIC ${CMAKE_SOURCE_DIR}) \ No newline at end of file diff --git a/AdvancedCppV2/Presentation/exercises/complex/README.md b/AdvancedCppV2/Presentation/exercises/complex/README.md new file mode 100644 index 0000000..e4d70f3 --- /dev/null +++ b/AdvancedCppV2/Presentation/exercises/complex/README.md @@ -0,0 +1,16 @@ +## Linux compilation + + > mkdir build + > cd build + > cmake -DCMAKE_BUILD_TYPE=Debug .. + > make + +## Exercise 1 + +Write a function that creates `std::complex` number from two provided numbers. If the types of numbers are different, it should create `std::complex` of the first parameter. Usage: + +```c++ +std::complex a = makeComplex(4, 5); // both ints +std::complex b = makeComplex(3.0, 2.0); // both doubles +std::complex c = makeComplex(1, 5.0); // int, double -> takes int +``` \ No newline at end of file diff --git a/AdvancedCppV2/Presentation/exercises/complex/complex.cpp b/AdvancedCppV2/Presentation/exercises/complex/complex.cpp new file mode 100644 index 0000000..0931381 --- /dev/null +++ b/AdvancedCppV2/Presentation/exercises/complex/complex.cpp @@ -0,0 +1 @@ +#include diff --git a/AdvancedCppV2/Presentation/exercises/complex/soulutions/complex.cpp b/AdvancedCppV2/Presentation/exercises/complex/soulutions/complex.cpp new file mode 100644 index 0000000..0e1461f --- /dev/null +++ b/AdvancedCppV2/Presentation/exercises/complex/soulutions/complex.cpp @@ -0,0 +1,6 @@ +#include + +template +std::complex makeComplex(T a, U b) { + return std::complex{a, static_cast(b)}; +} \ No newline at end of file diff --git a/AdvancedCppV2/Presentation/exercises/converter/CMakeLists.txt b/AdvancedCppV2/Presentation/exercises/converter/CMakeLists.txt new file mode 100644 index 0000000..2337c43 --- /dev/null +++ b/AdvancedCppV2/Presentation/exercises/converter/CMakeLists.txt @@ -0,0 +1,14 @@ +cmake_minimum_required(VERSION 3.2) + +set(CMAKE_CXX_STANDARD 17) +set(CMAKE_CXX_STANDARD_REQUIRED ON) + +project(Converter) + +set(SRC_LIST + converter.cpp +) + +add_executable(${PROJECT_NAME} ${SRC_LIST}) +target_compile_options(${PROJECT_NAME} PUBLIC -Wall -Werror -Wpedantic -Wextra) +target_include_directories(${PROJECT_NAME} PUBLIC ${CMAKE_SOURCE_DIR}) \ No newline at end of file diff --git a/AdvancedCppV2/Presentation/exercises/converter/README.md b/AdvancedCppV2/Presentation/exercises/converter/README.md new file mode 100644 index 0000000..eb46653 --- /dev/null +++ b/AdvancedCppV2/Presentation/exercises/converter/README.md @@ -0,0 +1,18 @@ +## Linux compilation + + > mkdir build + > cd build + > cmake -DCMAKE_BUILD_TYPE=Debug .. + > make + +## Valgrind usage + + > valgrind valgrind_params path/to/binary binary_params, eg: + > valgrind --leak-check=full ./Converter + > or full output using command: valgrind --leak-check=full --show-leak-kinds=all --track-origins=yes --verbose --log-file=valgrind-out.txt ./Converter + +## Converter exapmle + +1. Compile and run Converter application and check memory leaks under valgrind +2. Fix code using std::unique_ptr and std::make_unique +3. Find other issues and fix them (use good practise etc...) diff --git a/AdvancedCppV2/Presentation/exercises/converter/converter.cpp b/AdvancedCppV2/Presentation/exercises/converter/converter.cpp new file mode 100644 index 0000000..8e7d424 --- /dev/null +++ b/AdvancedCppV2/Presentation/exercises/converter/converter.cpp @@ -0,0 +1,59 @@ +#include +#include +#include + +class Resource { +public: + Resource(const std::string& str): str_(str) {} + + const std::string& str() const { + return str_; + } + +private: + std::string str_; +}; + +class Converter { +public: + virtual void Convert(Resource* resource) = 0; +}; + +class CurlyBracketConverter : public Converter { +public: + virtual void Convert(Resource* resource) { + std::cout << "{" << resource->str() << "}\n"; + } +}; + +class SquareBracketConverter : public Converter { +public: + virtual void Convert(Resource* resource) { + std::cout << "[" << resource->str() << "]\n"; + } +}; + +class Printer { +public: + Printer(Converter* converter): converter_(converter) {} + + void Print(Resource* resource) { + converter_->Convert(resource); + } + +private: + Converter* converter_; +}; + +int main() { + Resource* resource = new Resource("Ala has a cat"); + Printer printer(new SquareBracketConverter{}); + Printer printer2(new CurlyBracketConverter{}); + + printer.Print(resource); + printer2.Print(resource); + + delete resource; + + return 0; +} diff --git a/AdvancedCppV2/Presentation/exercises/converter/solution/converter.cpp b/AdvancedCppV2/Presentation/exercises/converter/solution/converter.cpp new file mode 100644 index 0000000..0677212 --- /dev/null +++ b/AdvancedCppV2/Presentation/exercises/converter/solution/converter.cpp @@ -0,0 +1,84 @@ +#include +#include +#include + +class Resource { +public: + explicit Resource(const std::string& str): str_(str) {} + + const std::string& str() const { + return str_; + } + +private: + std::string str_; +}; + +class Converter { +public: + Converter() = default; + + // Rule of 5 + virtual ~Converter() = default; + Converter(const Converter& other) = default; + Converter(Converter&& other) = default; + Converter& operator=(const Converter& other) = default; + Converter& operator=(Converter&& other) = default; + + virtual void Convert(const std::unique_ptr& resource) const = 0; +}; + +class CurlyBracketConverter : public Converter { +public: + void Convert(const std::unique_ptr& resource) const override { + std::cout << "{" << resource->str() << "}\n"; + } +}; + +class SquareBracketConverter : public Converter { +public: + virtual void Convert(const std::unique_ptr& resource) const override{ + std::cout << "[" << resource->str() << "]\n"; + } +}; + +class Printer { +public: + explicit Printer(std::unique_ptr&& converter) noexcept : converter_(std::move(converter)) {} + + void Print(const std::unique_ptr& resource) const { + converter_->Convert(resource); + } + +private: + std::unique_ptr converter_; +}; + +struct Foo { + Foo(std::unique_ptr ptr); +}; + +struct Bar { + use(std::unique_ptr ptr); +}; + +struct MockFoo {}; + +TEST() { + std::unique_ptr mock; + MockFoo* mock_ptr = mock.get(); + Bar bar; + bar.use(std::move(mock)); + + EXPECT_CALL(mock_ptr, use); +} + +int main() { + auto resource = std::make_unique("Ala has a cat"); + Printer printer(std::make_unique()); + Printer printer2(std::make_unique()); + printer.Print(resource); + printer2.Print(resource); + + return 0; +} \ No newline at end of file diff --git a/AdvancedCppV2/Presentation/exercises/exampleProject/CMakeLists.txt b/AdvancedCppV2/Presentation/exercises/exampleProject/CMakeLists.txt new file mode 100644 index 0000000..21e3c97 --- /dev/null +++ b/AdvancedCppV2/Presentation/exercises/exampleProject/CMakeLists.txt @@ -0,0 +1,14 @@ +cmake_minimum_required(VERSION 3.2) + +set(CMAKE_CXX_STANDARD 20) +set(CMAKE_CXX_STANDARD_REQUIRED ON) + +project(ExampleProject) + +set(SRC_LIST + exampleProject.cpp +) + +add_executable(${PROJECT_NAME} ${SRC_LIST}) +# target_compile_options(${PROJECT_NAME} PUBLIC -Wall -Werror -Wpedantic -Wextra) +target_include_directories(${PROJECT_NAME} PUBLIC ${CMAKE_SOURCE_DIR}) \ No newline at end of file diff --git a/AdvancedCppV2/Presentation/exercises/exampleProject/README.md b/AdvancedCppV2/Presentation/exercises/exampleProject/README.md new file mode 100644 index 0000000..14082ac --- /dev/null +++ b/AdvancedCppV2/Presentation/exercises/exampleProject/README.md @@ -0,0 +1,10 @@ +## Linux compilation + + > mkdir build + > cd build + > cmake -DCMAKE_BUILD_TYPE=Debug .. + > make + +## Run program + +Run program ./ExampleProject and check output, which should be "Hello World"; diff --git a/AdvancedCppV2/Presentation/exercises/exampleProject/exampleProject.cpp b/AdvancedCppV2/Presentation/exercises/exampleProject/exampleProject.cpp new file mode 100644 index 0000000..4229ba4 --- /dev/null +++ b/AdvancedCppV2/Presentation/exercises/exampleProject/exampleProject.cpp @@ -0,0 +1,7 @@ +#include +#include + +int main() { + const std::string str("Hello world!\n"); + std::cout << str << '\n'; +} diff --git a/AdvancedCppV2/Presentation/exercises/list/CMakeLists.txt b/AdvancedCppV2/Presentation/exercises/list/CMakeLists.txt new file mode 100644 index 0000000..752b75d --- /dev/null +++ b/AdvancedCppV2/Presentation/exercises/list/CMakeLists.txt @@ -0,0 +1,14 @@ +cmake_minimum_required(VERSION 3.2) + +set(CMAKE_CXX_STANDARD 17) +set(CMAKE_CXX_STANDARD_REQUIRED ON) + +project(List) + +set(SRC_LIST + list.cpp +) + +add_executable(${PROJECT_NAME} ${SRC_LIST}) +target_compile_options(${PROJECT_NAME} PUBLIC -Wall -Werror -Wpedantic -Wextra) +target_include_directories(${PROJECT_NAME} PUBLIC ${CMAKE_SOURCE_DIR}) \ No newline at end of file diff --git a/AdvancedCppV2/Presentation/exercises/list/README.md b/AdvancedCppV2/Presentation/exercises/list/README.md new file mode 100644 index 0000000..934b308 --- /dev/null +++ b/AdvancedCppV2/Presentation/exercises/list/README.md @@ -0,0 +1,25 @@ +## Linux compilation + + > mkdir build + > cd build + > cmake -DCMAKE_BUILD_TYPE=Debug .. + > make + +## Valgrind usage + + > valgrind valgrind_params path/to/binary binary_params, eg: + > valgrind --leak-check=full ./List + > or full output using command: valgrind --leak-check=full --show-leak-kinds=all --track-origins=yes --verbose --log-file=valgrind-out.txt ./List + +## Resource exapmle + +Take a look at `list.cpp` file, where simple (and buggy) single-linked list is implemented. + +* `pushFront` method adds a new `Node` at the begining of the list. +* `findByValue` method iterates over the list and returns the first Node with matching `value` or `nullptr`. + +1. Compile and run List application +2. Fix memory leaks without introducing smart pointers +3. Fix memory leaks with smart pointers. What kind of pointers needs to be applied and why? +4. Add function to add a node at the end of the list (try to do this with time complexity O(1)) +5. Add function to delete node with provided value. diff --git a/AdvancedCppV2/Presentation/exercises/list/list.cpp b/AdvancedCppV2/Presentation/exercises/list/list.cpp new file mode 100644 index 0000000..15ad44b --- /dev/null +++ b/AdvancedCppV2/Presentation/exercises/list/list.cpp @@ -0,0 +1,68 @@ +#include + +class Node { +public: + Node(const int value, Node* next) + : next_(next), value_(value) {} + + explicit Node(const int v) + : Node(v, nullptr) {} + + const Node* next() const { return next_; } + int value() const { return value_; } + +private: + Node* next_; + int value_; +}; + +class List { +public: + void pushFront(int value) { + if (!head_) { + head_ = new Node(value); + return; + } + + head_ = new Node(value, head_); + } + + const Node* findByValue(const int value) const { + const auto* current = head_; + + while (current) { + if (current->value() == value) { + return current; + } + current = current->next(); + } + + return nullptr; + } + +private: + Node* head_ = nullptr; +}; + +int main() { + List list; + + list.pushFront(4); + list.pushFront(2); + list.pushFront(7); + list.pushFront(9); + + if (const auto* const node = list.findByValue(1)) { + std::cout << node->value() << '\n'; + } else { + std::cout << "can't find node with value 1\n"; + } + + if (const auto* const node = list.findByValue(7)) { + std::cout << node->value() << '\n'; + } else { + std::cout << "can't find node with value 7\n"; + } + + return 0; +} diff --git a/AdvancedCppV2/Presentation/exercises/list/solution/list.cpp b/AdvancedCppV2/Presentation/exercises/list/solution/list.cpp new file mode 100644 index 0000000..f9da679 --- /dev/null +++ b/AdvancedCppV2/Presentation/exercises/list/solution/list.cpp @@ -0,0 +1,76 @@ +#include +#include +#include + +class Node { +public: + Node(const int value, std::unique_ptr next) + : next_(std::move(next)), value_(value) {} + + explicit Node(const int v) + : Node(v, nullptr) {} + + const Node* next() const { return next_.get(); } + int value() const { return value_; } + std::unique_ptr getNext() { return std::move(next_); } + +private: + std::unique_ptr next_; + int value_; +}; + +// 1 +// 2 -> 1 +// 3 -> 2 -> 1 +// 4 -> 3 -> 2 -> 1 + +class List { +public: + void pushFront(int value) { + if (!head_) { + head_ = std::make_unique(value); + return; + } + + head_ = std::make_unique(value, std::move(head_)); + } + + const Node* findByValue(const int value) const { + const auto* current = head_.get(); + + while (current) { + if (current->value() == value) { + return current; + } + current = current->next(); + } + + return nullptr; + } + +private: + std::unique_ptr head_; +}; + +int main() { + List list; + + list.pushFront(4); + list.pushFront(2); + list.pushFront(7); + list.pushFront(9); + + if (const auto* const node = list.findByValue(1)) { + std::cout << node->value() << '\n'; + } else { + std::cout << "can't find node with value 1\n"; + } + + if (const auto* const node = list.findByValue(7)) { + std::cout << node->value() << '\n'; + } else { + std::cout << "can't find node with value 7\n"; + } + + return 0; +} diff --git a/AdvancedCppV2/Presentation/exercises/list/solution/list2.cpp b/AdvancedCppV2/Presentation/exercises/list/solution/list2.cpp new file mode 100644 index 0000000..6f545ee --- /dev/null +++ b/AdvancedCppV2/Presentation/exercises/list/solution/list2.cpp @@ -0,0 +1,181 @@ +#include +#include +#include + +class Node { +public: + Node(const int value, std::unique_ptr next) + : next_(std::move(next)), value_(value) {} + + explicit Node(const int v) + : Node(v, nullptr) {} + + const Node* next() const { return next_.get(); } + Node* next() { return next_.get(); } + int value() const { return value_; } + void setNext(std::unique_ptr next) { next_ = std::move(next); } + std::unique_ptr getNext() { return std::move(next_); } + +private: + std::unique_ptr next_; + int value_; +}; + +// ht +// 1 +// h t +// 2 -> 1 +// h t +// 3 -> 2 -> 1 +// h t +// 4 -> 3 -> 2 -> 1 +// h t +// 4 -> 3 -> 2 -> 1 -> 5 +// +// 3 -> 2 -> 1 -> 5 +// 3 -> 1 -> 5 + +class List { +public: + void pushFront(int value) { + if (!head_) { + pushHead(value); + return; + } + + head_ = std::make_unique(value, std::move(head_)); + } + + void pushBack(int value) { + if (!tail_) { + pushHead(value); + return; + } + + tail_->setNext(std::make_unique(value)); + tail_ = tail_->next(); + } + + bool erase(int value) { + // Remove head + if (head_ && head_->value() == value) { + head_ = head_->getNext(); + if (!head_) { + tail_ = nullptr; + } + return true; + } + + if (auto* node = findPrevNode(value)) { + // Remove tail + if (node->next() == tail_) { + tail_ = node; + } + node->setNext(std::move(node->next()->getNext())); + return true; + } + + return false; + } + + const Node* findByValue(const int value) const { + const auto* current = head_.get(); + + while (current) { + if (current->value() == value) { + return current; + } + current = current->next(); + } + + return nullptr; + } + + void print() const { + const auto* current = head_.get(); + + while (current) { + std::cout << current->value() << ' '; + current = current->next(); + } + std::cout << '\n'; + } + +private: + // ht + // 1 + // h t + // 2 -> 1 + // h t + // 2 -> 1 -> 3 + // 2 -> 3 + void pushHead(int value) { + head_ = std::make_unique(value); + tail_ = head_.get(); + } + + Node* findPrevNode(const int value) const { + auto* current = head_.get(); + Node* prev = nullptr; + + while (current) { + if (current->value() == value) { + return prev; + } + prev = current; + current = current->next(); + } + + return nullptr; + } + + std::unique_ptr head_; + Node* tail_{nullptr}; +}; + +int main() { + List list; + + list.pushFront(4); + list.pushFront(2); + list.pushFront(7); + list.pushFront(9); + list.print(); + + if (const auto* const node = list.findByValue(1)) { + std::cout << node->value() << '\n'; + } else { + std::cout << "can't find node with value 1\n"; + } + + if (const auto* const node = list.findByValue(7)) { + std::cout << node->value() << '\n'; + } else { + std::cout << "can't find node with value 7\n"; + } + + list.pushBack(10); + list.print(); + list.pushBack(12); + list.pushFront(3); + list.pushFront(5); + list.pushBack(13); + list.print(); + + list.erase(2); + list.print(); + + list.erase(5); + list.print(); + + list.erase(13); + list.print(); + + list.erase(12); + list.print(); + + list.pushBack(40); + list.print(); + + return 0; +} diff --git a/AdvancedCppV2/Presentation/exercises/map/CMakeLists.txt b/AdvancedCppV2/Presentation/exercises/map/CMakeLists.txt new file mode 100644 index 0000000..52a7691 --- /dev/null +++ b/AdvancedCppV2/Presentation/exercises/map/CMakeLists.txt @@ -0,0 +1,14 @@ +cmake_minimum_required(VERSION 3.2) + +set(CMAKE_CXX_STANDARD 17) +set(CMAKE_CXX_STANDARD_REQUIRED ON) + +project(Map) + +set(SRC_LIST + map.cpp +) + +add_executable(${PROJECT_NAME} ${SRC_LIST}) +target_compile_options(${PROJECT_NAME} PUBLIC -Wall -Werror -Wpedantic -Wextra) +target_include_directories(${PROJECT_NAME} PUBLIC ${CMAKE_SOURCE_DIR}) \ No newline at end of file diff --git a/AdvancedCppV2/Presentation/exercises/map/README.md b/AdvancedCppV2/Presentation/exercises/map/README.md new file mode 100644 index 0000000..f926fc2 --- /dev/null +++ b/AdvancedCppV2/Presentation/exercises/map/README.md @@ -0,0 +1,55 @@ +## Linux compilation + + > mkdir build + > cd build + > cmake -DCMAKE_BUILD_TYPE=Debug .. + > make + +## Exercise 1 + +Write a template class `VectorMap` that represents an over-engineered `std::map`. + +Inside, it should hold 2 `std::vectors` of the same size, each with different types. The first vector should hold keys, the other one values. + +Elements at the same position in both vectors should create a pair like `1` and `'c'` below. + +```c++ +VectorMap map; +map.insert(1, 'c'); +map[1] = 'e'; // replaces value under 1 +std::cout << map[1]; // prints 'e' +map.at(2); // throw std::out_of_range +``` + +Implement the mentioned above `insert()`, `operator[]`, `at()` methods. + +Do not bother about duplicated keys for now. +You can also try to implement additional methods from the `std::map` interface 🙂 + +Use [cppreference](http://en.cppreference.com/w/cpp/container/map). + +## Exercise 2 - `static_assert` + +Add a constraint to our `VectorMap`. + +Do not allow to create an object when `ValueType` does not have a default constructor. + +Use `static_assert` and proper trait from [``](https://en.cppreference.com/w/cpp/types#Type_traits) library. + +Check if it works properly. + +## Exercise 3 - `isIntKey()` + +Write a function `isIntKey()` in `VectorMap`. It should return `true` when the KeyType is `int` and `false` otherwise. + +Check the [``](https://en.cppreference.com/w/cpp/types#Type_traits) library for some inspiration 🙂 + +# Exercie 4 + +Write a partial specialization of `VectorMap` for boolean keys. We can have only 2 values for boolean keys. There is no need to keep vectors inside. + +Implement properly all currently available functions. + +# Exercie 5 + +Write a variable template `is_int_key_v`. It should return a value of the `is_int_key` field in a given template type. \ No newline at end of file diff --git a/AdvancedCppV2/Presentation/exercises/map/map.cpp b/AdvancedCppV2/Presentation/exercises/map/map.cpp new file mode 100644 index 0000000..23b74e9 --- /dev/null +++ b/AdvancedCppV2/Presentation/exercises/map/map.cpp @@ -0,0 +1,4 @@ +#include +#include +#include +#include diff --git a/AdvancedCppV2/Presentation/exercises/map/soultions/map1.cpp b/AdvancedCppV2/Presentation/exercises/map/soultions/map1.cpp new file mode 100644 index 0000000..948ea21 --- /dev/null +++ b/AdvancedCppV2/Presentation/exercises/map/soultions/map1.cpp @@ -0,0 +1,44 @@ +#include +#include +#include +#include + +template +class VectorMap { + std::vector keys_; + std::vector values_; + +public: + using K = Key; + using V = Value; + + void insert(const Key& k, const Value& v) { + keys_.emplace_back(k); + values_.emplace_back(v); + } + + Value& operator[](const Key& k); + Value& at(const Key& k); +}; + +template +Value& VectorMap::operator[](const Key& k) { + auto it = std::find(std::begin(keys_), std::end(keys_), k); + if (it == std::end(keys_)) { + keys_.emplace_back(k); + values_.emplace_back(Value{}); + return values_.back(); + } + auto dist = std::distance(keys_.begin(), it); + return values_[dist]; +} + +template +Value& VectorMap::at(const Key& k) { + auto it = std::find(std::begin(keys_), std::end(keys_), k); + if (it == std::end(keys_)) { + throw std::out_of_range("This key does not exist"); + } + auto dist = std::distance(keys_.begin(), it); + return values_[dist]; +} diff --git a/AdvancedCppV2/Presentation/exercises/map/soultions/map2.cpp b/AdvancedCppV2/Presentation/exercises/map/soultions/map2.cpp new file mode 100644 index 0000000..cd20dd2 --- /dev/null +++ b/AdvancedCppV2/Presentation/exercises/map/soultions/map2.cpp @@ -0,0 +1,54 @@ +#include +#include +#include +#include + +template +class VectorMap { + std::vector keys_; + std::vector values_; + + static_assert(std::is_default_constructible::value, "Value should have the default constructor"); + static_assert(std::is_default_constructible_v, "Value should have the default constructor"); + +public: + using K = Key; + using V = Value; + void insert(const Key& k, const Value& v) { + keys_.emplace_back(k); + values_.emplace_back(v); + } + + static constexpr bool isIntKey() { + // if (std::is_integral_v) { + if (std::is_same_v) { + return true; + } + return false; + } + + Value& operator[](const Key& k); + Value& at(const Key& k); +}; + +template +Value& VectorMap::operator[](const Key& k) { + auto it = std::find(std::begin(keys_), std::end(keys_), k); + if (it == std::end(keys_)) { + keys_.emplace_back(k); + values_.emplace_back(Value{}); + return values_.back(); + } + auto dist = std::distance(keys_.begin(), it); + return values_[dist]; +} + +template +Value& VectorMap::at(const Key& k) { + auto it = std::find(std::begin(keys_), std::end(keys_), k); + if (it == std::end(keys_)) { + throw std::out_of_range("This key does not exist"); + } + auto dist = std::distance(keys_.begin(), it); + return values_[dist]; +} diff --git a/AdvancedCppV2/Presentation/exercises/map/soultions/map3.cpp b/AdvancedCppV2/Presentation/exercises/map/soultions/map3.cpp new file mode 100644 index 0000000..a0f966b --- /dev/null +++ b/AdvancedCppV2/Presentation/exercises/map/soultions/map3.cpp @@ -0,0 +1,56 @@ +#include +#include +#include +#include + +template +class VectorMap { + std::vector keys_; + std::vector values_; + + static_assert(std::is_default_constructible::value, "Value should have the default constructor"); + static_assert(std::is_default_constructible_v, "Value should have the default constructor"); + +public: + using K = Key; + using V = Value; + void insert(const Key& k, const Value& v) { + keys_.emplace_back(k); + values_.emplace_back(v); + } + + static constexpr bool isIntKey() { + // if (std::is_integral_v) { + if (std::is_same_v) { + return true; + } + return false; + } + + Value& operator[](const Key& k); + Value& at(const Key& k); + + static constexpr bool is_int_key = std::is_same_v; +}; + +template +Value& VectorMap::operator[](const Key& k) { + auto it = std::find(std::begin(keys_), std::end(keys_), k); + if (it == std::end(keys_)) { + keys_.emplace_back(k); + values_.emplace_back(Value{}); + return values_.back(); + } + auto dist = std::distance(keys_.begin(), it); + return values_[dist]; +} + +template +Value& VectorMap::at(const Key& k) { + auto it = std::find(std::begin(keys_), std::end(keys_), k); + if (it == std::end(keys_)) { + throw std::out_of_range("This key does not exist"); + } + auto dist = std::distance(keys_.begin(), it); + return values_[dist]; +} diff --git a/AdvancedCppV2/Presentation/exercises/map/soultions/map4.cpp b/AdvancedCppV2/Presentation/exercises/map/soultions/map4.cpp new file mode 100644 index 0000000..9c7a510 --- /dev/null +++ b/AdvancedCppV2/Presentation/exercises/map/soultions/map4.cpp @@ -0,0 +1,125 @@ +#include +#include +#include +#include + +template +class VectorMap { + std::vector keys_; + std::vector values_; + + static_assert(std::is_default_constructible::value, "Value should have the default constructor"); + static_assert(std::is_default_constructible_v, "Value should have the default constructor"); + +public: + using K = Key; + using V = Value; + template + using iterator = typename std::vector::iterator; + + void insert(const Key& k, const Value& v) { + keys_.emplace_back(k); + values_.emplace_back(v); + } + + static constexpr bool isIntKey() { + // if (std::is_integral_v) { + if (std::is_same_v) { + return true; + } + return false; + } + + Value& operator[](const Key& k); + Value& at(const Key& k); + + static constexpr bool is_int_key = std::is_same_v; +}; + +template +Value& VectorMap::operator[](const Key& k) { + auto it = std::find(std::begin(keys_), std::end(keys_), k); + if (it == std::end(keys_)) { + keys_.emplace_back(k); + values_.emplace_back(Value{}); + return values_.back(); + } + auto dist = std::distance(keys_.begin(), it); + return values_[dist]; +} + +template +Value& VectorMap::at(const Key& k) { + auto it = std::find(std::begin(keys_), std::end(keys_), k); + if (it == std::end(keys_)) { + throw std::out_of_range("This key does not exist"); + } + auto dist = std::distance(keys_.begin(), it); + return values_[dist]; +} + + +template +class VectorMap { // specialization + static_assert(std::is_default_constructible::value, + "ValueType must have the default constructor"); + + ValueType t_; + ValueType f_; + +public: + static constexpr bool is_int_key = false; // type_traits #2 + + VectorMap() { + std::cout << "bool specialization used\n"; + } + + void insert(bool key, ValueType&& value) { + if (key) { + t_ = value; + } else { + f_ = value; + } + } + + ValueType& operator[](bool key) { + if (key) { + return t_; + } + return f_; + } + + ValueType& at(bool key) { + if (key) { + return t_; + } + return f_; + } +}; + +int main() { + VectorMap map; + // VectorMap::iterator k; + map.insert(1, 'c'); + std::cout << map[1] << '\n'; + map[1] = 'e'; // replaces value under 1 + std::cout << map[1] << '\n'; // prints 'e' + // map.at(2); // throw std::out_of_range + std::cout << std::boolalpha << map.isIntKey() << '\n'; + std::cout << std::boolalpha << map.is_int_key << '\n'; + + VectorMap map3; + std::cout << std::boolalpha << map3.isIntKey() << '\n'; + + VectorMap map4; + map4.insert(true, 3); + map4.insert(false, 0); + std::cout << map4[true] << '\n'; + map4[true] = 10; // replaces value under 1 + std::cout << map4[true] << '\n'; // prints 'e' + + std::vector v{1, 2, 3}; + find(begin(v), end(v), 2); + + return 0; +} \ No newline at end of file diff --git a/AdvancedCppV2/Presentation/exercises/map/soultions/map5.cpp b/AdvancedCppV2/Presentation/exercises/map/soultions/map5.cpp new file mode 100644 index 0000000..4e3d4c9 --- /dev/null +++ b/AdvancedCppV2/Presentation/exercises/map/soultions/map5.cpp @@ -0,0 +1,134 @@ +#include +#include +#include +#include + +template +class VectorMap { + std::vector keys_; + std::vector values_; + + static_assert(std::is_default_constructible::value, "Value should have the default constructor"); + static_assert(std::is_default_constructible_v, "Value should have the default constructor"); + +public: + using K = Key; + using V = Value; + template + using iterator = typename std::vector::iterator; + + void insert(const Key& k, const Value& v) { + keys_.emplace_back(k); + values_.emplace_back(v); + } + + static constexpr bool isIntKey() { + // if (std::is_integral_v) { + if (std::is_same_v) { + return true; + } + return false; + } + + Value& operator[](const Key& k); + Value& at(const Key& k); + + static constexpr bool is_int_key = std::is_same_v; +}; + +template +Value& VectorMap::operator[](const Key& k) { + auto it = std::find(std::begin(keys_), std::end(keys_), k); + if (it == std::end(keys_)) { + keys_.emplace_back(k); + values_.emplace_back(Value{}); + return values_.back(); + } + auto dist = std::distance(keys_.begin(), it); + return values_[dist]; +} + +template +Value& VectorMap::at(const Key& k) { + auto it = std::find(std::begin(keys_), std::end(keys_), k); + if (it == std::end(keys_)) { + throw std::out_of_range("This key does not exist"); + } + auto dist = std::distance(keys_.begin(), it); + return values_[dist]; +} + + +template +class VectorMap { // specialization + static_assert(std::is_default_constructible::value, + "ValueType must have the default constructor"); + + ValueType t_; + ValueType f_; + +public: + static constexpr bool is_int_key = false; // type_traits #2 + + VectorMap() { + std::cout << "bool specialization used\n"; + } + + void insert(bool key, ValueType&& value) { + if (key) { + t_ = value; + } else { + f_ = value; + } + } + + ValueType& operator[](bool key) { + if (key) { + return t_; + } + return f_; + } + + ValueType& at(bool key) { + if (key) { + return t_; + } + return f_; + } +}; + +template +constexpr bool is_int_key_v = T::is_int_key; + +template +constexpr bool is_int_key_v1 = VectorMap::is_int_key; + +int main() { + VectorMap map; + // VectorMap::iterator k; + map.insert(1, 'c'); + std::cout << map[1] << '\n'; + map[1] = 'e'; // replaces value under 1 + std::cout << map[1] << '\n'; // prints 'e' + // map.at(2); // throw std::out_of_range + std::cout << std::boolalpha << map.isIntKey() << '\n'; + std::cout << std::boolalpha << map.is_int_key << '\n'; + + VectorMap map3; + std::cout << std::boolalpha << map3.isIntKey() << '\n'; + + VectorMap map4; + map4.insert(true, 3); + map4.insert(false, 0); + std::cout << map4[true] << '\n'; + map4[true] = 10; // replaces value under 1 + std::cout << map4[true] << '\n'; // prints 'e' + std::cout << std::boolalpha << is_int_key_v << '\n'; + std::cout << std::boolalpha << is_int_key_v << '\n'; + std::cout << std::boolalpha << is_int_key_v << '\n'; + + std::vector v{1, 2, 3}; + find(begin(v), end(v), 2); + + return 0; +} \ No newline at end of file diff --git a/AdvancedCppV2/Presentation/exercises/resource/CMakeLists.txt b/AdvancedCppV2/Presentation/exercises/resource/CMakeLists.txt new file mode 100644 index 0000000..78dd153 --- /dev/null +++ b/AdvancedCppV2/Presentation/exercises/resource/CMakeLists.txt @@ -0,0 +1,14 @@ +cmake_minimum_required(VERSION 3.2) + +set(CMAKE_CXX_STANDARD 17) +set(CMAKE_CXX_STANDARD_REQUIRED ON) + +project(Resource) + +set(SRC_LIST + resource.cpp +) + +add_executable(${PROJECT_NAME} ${SRC_LIST}) +target_compile_options(${PROJECT_NAME} PUBLIC -Wall -Werror -Wpedantic -Wextra) +target_include_directories(${PROJECT_NAME} PUBLIC ${CMAKE_SOURCE_DIR}) \ No newline at end of file diff --git a/AdvancedCppV2/Presentation/exercises/resource/README.md b/AdvancedCppV2/Presentation/exercises/resource/README.md new file mode 100644 index 0000000..74cb103 --- /dev/null +++ b/AdvancedCppV2/Presentation/exercises/resource/README.md @@ -0,0 +1,19 @@ +## Linux compilation + + > mkdir build + > cd build + > cmake -DCMAKE_BUILD_TYPE=Debug .. + > make + +## Valgrind usage + + > valgrind valgrind_params path/to/binary binary_params, eg: + > valgrind --leak-check=full ./Resource 5 + > or full output using command: valgrind --leak-check=full --show-leak-kinds=all --track-origins=yes --verbose --log-file=valgrind-out.txt ./Resource + +## Resource exapmle + +1. Compile and run Resource application and check memory leaks under valgrind +2. Fix memory leaks with a proper usage of delete operator +3. Refactor the solution to use `std::unique_ptr<>` +4. Use `std::make_unique` \ No newline at end of file diff --git a/AdvancedCppV2/Presentation/exercises/resource/resource.cpp b/AdvancedCppV2/Presentation/exercises/resource/resource.cpp new file mode 100644 index 0000000..e0c201a --- /dev/null +++ b/AdvancedCppV2/Presentation/exercises/resource/resource.cpp @@ -0,0 +1,32 @@ +#include +#include +#include + +class Resource { +public: + void use(const char* N) { + std::cout << "Using resource. Passed " << *N << '\n'; + if (*N == 'd') { + throw std::logic_error("Passed d. d is prohibited."); + } + }; +}; + +int main(int argc, char* argv[]) { + if (argc != 2) { + std::cerr << "You need to pass 1 argument" << '\n'; + exit(-1); + } + + const char* arg = argv[1]; + Resource* rsc = nullptr; + + try { + rsc = new Resource(); + rsc->use(arg); + delete rsc; + } catch (std::logic_error& e) { + std::cout << e.what() << '\n'; + } + return 0; +} diff --git a/AdvancedCppV2/Presentation/exercises/resource/solution/resource.cpp b/AdvancedCppV2/Presentation/exercises/resource/solution/resource.cpp new file mode 100644 index 0000000..cb23290 --- /dev/null +++ b/AdvancedCppV2/Presentation/exercises/resource/solution/resource.cpp @@ -0,0 +1,32 @@ +#include +#include +#include + +class Resource { +public: + void use(const char* N) { + std::cout << "Using resource. Passed " << *N << '\n'; + if (*N == 'd') { + throw std::logic_error("Passed d. d is prohibited."); + } + }; +}; + +int main(int argc, char* argv[]) { + if (argc != 2) { + std::cerr << "You need to pass 1 argument" << '\n'; + exit(-1); + } + + const char* arg = argv[1]; + std::unique_ptr rsc; + + try { + rsc = std::make_unique(); + rsc->use(arg); + } catch (std::logic_error& e) { + + } + + return 0; +} diff --git a/AdvancedCppV2/Presentation/exercises/resourceFactory/CMakeLists.txt b/AdvancedCppV2/Presentation/exercises/resourceFactory/CMakeLists.txt new file mode 100644 index 0000000..663bf30 --- /dev/null +++ b/AdvancedCppV2/Presentation/exercises/resourceFactory/CMakeLists.txt @@ -0,0 +1,14 @@ +cmake_minimum_required(VERSION 3.2) + +set(CMAKE_CXX_STANDARD 17) +set(CMAKE_CXX_STANDARD_REQUIRED ON) + +project(ResourceFactory) + +set(SRC_LIST + resourceFactory.cpp +) + +add_executable(${PROJECT_NAME} ${SRC_LIST}) +target_compile_options(${PROJECT_NAME} PUBLIC -Wall -Werror -Wpedantic -Wextra) +target_include_directories(${PROJECT_NAME} PUBLIC ${CMAKE_SOURCE_DIR}) \ No newline at end of file diff --git a/AdvancedCppV2/Presentation/exercises/resourceFactory/README.md b/AdvancedCppV2/Presentation/exercises/resourceFactory/README.md new file mode 100644 index 0000000..c2581f2 --- /dev/null +++ b/AdvancedCppV2/Presentation/exercises/resourceFactory/README.md @@ -0,0 +1,20 @@ +## Linux compilation + + > mkdir build + > cd build + > cmake -DCMAKE_BUILD_TYPE=Debug .. + > make + +## Valgrind usage + + > valgrind valgrind_params path/to/binary binary_params, eg: + > valgrind --leak-check=full ./ResourceFactory + > or full output using command: valgrind --leak-check=full --show-leak-kinds=all --track-origins=yes --verbose --log-file=valgrind-out.txt ./ResourceFactory + +## Resource exapmle + +1. Compile and run ResourceFactory application +2. Put comments in places where you can spot some problems +3. How to remove elements from the collection (vector<Resource*> resources)? +4. Check memory leaks +5. Fix problems \ No newline at end of file diff --git a/AdvancedCppV2/Presentation/exercises/resourceFactory/resourceFactory.cpp b/AdvancedCppV2/Presentation/exercises/resourceFactory/resourceFactory.cpp new file mode 100644 index 0000000..959f82f --- /dev/null +++ b/AdvancedCppV2/Presentation/exercises/resourceFactory/resourceFactory.cpp @@ -0,0 +1,65 @@ +#include +#include +#include + +struct Resource +{ + Resource(char* byte) : byte_(byte) {} + char* byte() const { return byte_; } + virtual std::string name() const = 0; + ~Resource() { delete byte_; } + +protected: + char* byte_ = nullptr; +}; + +struct ResourceA : Resource +{ + ResourceA(char* byte) : Resource(byte) {} + std::string name() const override { return std::string("ResourceA ").append(byte_); } +}; + +struct ResourceB : Resource +{ + ResourceB(char* byte) : Resource(byte) {} + std::string name() const override { return std::string("ResourceB ").append(byte_); } +}; + +struct ResourceFactory +{ + Resource* makeResourceA(char* byte) { return new ResourceA{byte}; } + Resource* makeResourceB(char* byte) { return new ResourceB{byte}; } +}; + +struct ResourceCollection +{ + void add(Resource* r) { resources.push_back(r); } + void clear() { resources.clear(); } + Resource* operator[](int index) { return resources[index]; } + void printAll() + { + for (const auto & res : resources) + { + std::cout << res->name() << std::endl; + } + } + +private: + std::vector resources; +}; + +int main() +{ + ResourceCollection collection; + ResourceFactory rf; + collection.add(rf.makeResourceA(new char{91})); + collection.add(rf.makeResourceB(new char{92})); + collection.printAll(); + + auto firstByte = collection[0]->byte(); + collection.clear(); + std::cout << *firstByte << std::endl; + + return 0; +} + diff --git a/AdvancedCppV2/Presentation/exercises/resourceFactory/soultions/resourceFactory.cpp b/AdvancedCppV2/Presentation/exercises/resourceFactory/soultions/resourceFactory.cpp new file mode 100644 index 0000000..2be86a1 --- /dev/null +++ b/AdvancedCppV2/Presentation/exercises/resourceFactory/soultions/resourceFactory.cpp @@ -0,0 +1,77 @@ +#include +#include +#include +#include +#include + +struct Resource { + Resource(std::unique_ptr byte) + : byte_(std::move(byte)) {} + virtual ~Resource() = default; + // Rule of 5 + + char* byte() const { return byte_.get(); } + virtual std::string name() const = 0; + +protected: + std::unique_ptr byte_; +}; + +struct ResourceA : Resource { + ~ResourceA() override { + std::cout << "ResourceA D'tor\n"; + } + + ResourceA(std::unique_ptr byte) + : Resource(std::move(byte)) {} + std::string name() const override { return std::string("ResourceA ").append(1, *byte_); } +}; + +struct ResourceB : Resource { + ~ResourceB() override { + std::cout << "ResourceB D'tor\n"; + } + + ResourceB(std::unique_ptr byte) + : Resource(std::move(byte)) {} + std::string name() const override { return std::string("ResourceB ") + *byte_; } +}; + +struct ResourceFactory { + static std::unique_ptr makeResourceA(std::unique_ptr byte) { + return std::make_unique(std::move(byte)); + } + static std::unique_ptr makeResourceB(std::unique_ptr byte) { + return std::make_unique(std::move(byte)); + } +}; + +struct ResourceCollection { + void add(std::unique_ptr r) { resources.push_back(std::move(r)); } + void clear() { resources.clear(); } + Resource* operator[](int index) const { return resources[index].get(); } + void printAll() const { + for (const auto& res : resources) { + std::cout << res->name() << '\n'; + } + } + +private: + std::vector> resources; +}; + +int main() { + ResourceCollection collection; + collection.add(ResourceFactory::makeResourceA(std::make_unique(0x78))); + collection.add(ResourceFactory::makeResourceB(std::make_unique(0x79))); + collection.printAll(); + + auto* firstByte = collection[0]->byte(); + std::cout << *firstByte << '\n'; + + collection.clear(); + // Use already free memory! + //std::cout << *firstByte << '\n'; + + return 0; +} diff --git a/AdvancedCppV2/Presentation/exercises/searcher/CMakeLists.txt b/AdvancedCppV2/Presentation/exercises/searcher/CMakeLists.txt new file mode 100644 index 0000000..36f5eb9 --- /dev/null +++ b/AdvancedCppV2/Presentation/exercises/searcher/CMakeLists.txt @@ -0,0 +1,14 @@ +cmake_minimum_required(VERSION 3.2) + +set(CMAKE_CXX_STANDARD 20) +set(CMAKE_CXX_STANDARD_REQUIRED ON) + +project(Searcher) + +set(SRC_LIST + searcher.cpp +) + +add_executable(${PROJECT_NAME} ${SRC_LIST}) +target_compile_options(${PROJECT_NAME} PUBLIC -Wall -Werror -Wpedantic -Wextra) +target_include_directories(${PROJECT_NAME} PUBLIC ${CMAKE_SOURCE_DIR}) \ No newline at end of file diff --git a/AdvancedCppV2/Presentation/exercises/searcher/README.md b/AdvancedCppV2/Presentation/exercises/searcher/README.md new file mode 100644 index 0000000..34e1bab --- /dev/null +++ b/AdvancedCppV2/Presentation/exercises/searcher/README.md @@ -0,0 +1,11 @@ +## Linux compilation + + > mkdir build + > cd build + > cmake -DCMAKE_BUILD_TYPE=Debug .. + > make + +## Exercise + +* Open project searcher +* Implement function `searchFiles` which returns all files containing `keyWord`. diff --git a/AdvancedCppV2/Presentation/exercises/searcher/files/fileA.cpp b/AdvancedCppV2/Presentation/exercises/searcher/files/fileA.cpp new file mode 100644 index 0000000..02a351d --- /dev/null +++ b/AdvancedCppV2/Presentation/exercises/searcher/files/fileA.cpp @@ -0,0 +1 @@ +Hello FileA \ No newline at end of file diff --git a/AdvancedCppV2/Presentation/exercises/searcher/files/fileA.hpp b/AdvancedCppV2/Presentation/exercises/searcher/files/fileA.hpp new file mode 100644 index 0000000..2df259e --- /dev/null +++ b/AdvancedCppV2/Presentation/exercises/searcher/files/fileA.hpp @@ -0,0 +1 @@ +Hello FileA Ala ma kota \ No newline at end of file diff --git a/AdvancedCppV2/Presentation/exercises/searcher/files/fileB.cpp b/AdvancedCppV2/Presentation/exercises/searcher/files/fileB.cpp new file mode 100644 index 0000000..0cfda48 --- /dev/null +++ b/AdvancedCppV2/Presentation/exercises/searcher/files/fileB.cpp @@ -0,0 +1 @@ +Hello FileB ALA \ No newline at end of file diff --git a/AdvancedCppV2/Presentation/exercises/searcher/files/fileB.hpp b/AdvancedCppV2/Presentation/exercises/searcher/files/fileB.hpp new file mode 100644 index 0000000..353e76f --- /dev/null +++ b/AdvancedCppV2/Presentation/exercises/searcher/files/fileB.hpp @@ -0,0 +1 @@ +Hello FileB ala \ No newline at end of file diff --git a/AdvancedCppV2/Presentation/exercises/searcher/files/fileC.cpp b/AdvancedCppV2/Presentation/exercises/searcher/files/fileC.cpp new file mode 100644 index 0000000..048655a --- /dev/null +++ b/AdvancedCppV2/Presentation/exercises/searcher/files/fileC.cpp @@ -0,0 +1 @@ +Hello FileC ala kot i ala \ No newline at end of file diff --git a/AdvancedCppV2/Presentation/exercises/searcher/files/fileC.hpp b/AdvancedCppV2/Presentation/exercises/searcher/files/fileC.hpp new file mode 100644 index 0000000..414da62 --- /dev/null +++ b/AdvancedCppV2/Presentation/exercises/searcher/files/fileC.hpp @@ -0,0 +1 @@ +Hello FileC ala kot i Ala i nie ma kota \ No newline at end of file diff --git a/AdvancedCppV2/Presentation/exercises/searcher/searcher.cpp b/AdvancedCppV2/Presentation/exercises/searcher/searcher.cpp new file mode 100644 index 0000000..9fe212c --- /dev/null +++ b/AdvancedCppV2/Presentation/exercises/searcher/searcher.cpp @@ -0,0 +1,26 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace fs = std::filesystem; +namespace rn = std::ranges; + +std::vector searchFiles(std::string_view keyWord, const fs::path& dirName) { + std::vector paths; + + // Write implementation here + + return paths; +} + +int main() { + std::cout << "Files which contains word Ala:\n"; + const auto& res = searchFiles("Ala", fs::current_path().string() + "/files"); + rn::copy(res, std::ostream_iterator(std::cout, "\n")); +} \ No newline at end of file diff --git a/AdvancedCppV2/Presentation/exercises/searcher/solution/searcher.cpp b/AdvancedCppV2/Presentation/exercises/searcher/solution/searcher.cpp new file mode 100644 index 0000000..0679f8f --- /dev/null +++ b/AdvancedCppV2/Presentation/exercises/searcher/solution/searcher.cpp @@ -0,0 +1,37 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace fs = std::filesystem; +namespace rn = std::ranges; + +std::vector searchFiles(std::string_view keyWord, const fs::path& dirName) { + std::vector paths; + rn::transform(fs::directory_iterator(dirName), + fs::directory_iterator{}, + std::back_inserter(paths), + [](const auto& entry) { return entry.path(); }); + + std::vector res; + rn::copy_if(paths, std::back_inserter(res), [keyWord](const auto& path) { + std::ifstream file(path); + const auto end = std::istream_iterator{}; + return std::find_if(std::istream_iterator(file), + end, + [keyWord](const auto& str) { return str == keyWord; }) != end; + }); + + return res; +} + +int main() { + std::cout << "Files which contains word Ala:\n"; + const auto& res = searchFiles("Ala", fs::current_path().string() + "/files"); + rn::copy(res, std::ostream_iterator(std::cout, "\n")); +} \ No newline at end of file diff --git a/AdvancedCppV2/Presentation/exercises/someClass/CMakeLists.txt b/AdvancedCppV2/Presentation/exercises/someClass/CMakeLists.txt new file mode 100644 index 0000000..490a553 --- /dev/null +++ b/AdvancedCppV2/Presentation/exercises/someClass/CMakeLists.txt @@ -0,0 +1,14 @@ +cmake_minimum_required(VERSION 3.2) + +set(CMAKE_CXX_STANDARD 17) +set(CMAKE_CXX_STANDARD_REQUIRED ON) + +project(Someclass) + +set(SRC_LIST + someclass.cpp +) + +add_executable(${PROJECT_NAME} ${SRC_LIST}) +target_compile_options(${PROJECT_NAME} PUBLIC -Wall -Werror -Wpedantic -Wextra) +target_include_directories(${PROJECT_NAME} PUBLIC ${CMAKE_SOURCE_DIR}) \ No newline at end of file diff --git a/AdvancedCppV2/Presentation/exercises/someClass/README.md b/AdvancedCppV2/Presentation/exercises/someClass/README.md new file mode 100644 index 0000000..c80e261 --- /dev/null +++ b/AdvancedCppV2/Presentation/exercises/someClass/README.md @@ -0,0 +1,10 @@ +## Linux compilation + + > mkdir build + > cd build + > cmake -DCMAKE_BUILD_TYPE=Debug .. + > make + +## Not exrecise + +This is only example of template \ No newline at end of file diff --git a/AdvancedCppV2/Presentation/exercises/someClass/someclass.cpp b/AdvancedCppV2/Presentation/exercises/someClass/someclass.cpp new file mode 100644 index 0000000..3d5023e --- /dev/null +++ b/AdvancedCppV2/Presentation/exercises/someClass/someclass.cpp @@ -0,0 +1,7 @@ +#include + +int main() { + SomeClass sc; + std::cout << sc.getValue() << std::endl; + return 0; +} \ No newline at end of file diff --git a/AdvancedCppV2/Presentation/exercises/someClass/soultions/someclass.cpp b/AdvancedCppV2/Presentation/exercises/someClass/soultions/someclass.cpp new file mode 100644 index 0000000..0cbf0f1 --- /dev/null +++ b/AdvancedCppV2/Presentation/exercises/someClass/soultions/someclass.cpp @@ -0,0 +1,16 @@ +#include + +template +class SomeClass { +public: + T getValue() { return value; } +private: + T value = {}; + U* ptr = nullptr; +}; + +int main() { + SomeClass sc; + std::cout << sc.getValue() << std::endl; + return 0; +} \ No newline at end of file diff --git a/AdvancedCppV2/Presentation/exercises/streamer/CMakeLists.txt b/AdvancedCppV2/Presentation/exercises/streamer/CMakeLists.txt new file mode 100644 index 0000000..5c09b8f --- /dev/null +++ b/AdvancedCppV2/Presentation/exercises/streamer/CMakeLists.txt @@ -0,0 +1,14 @@ +cmake_minimum_required(VERSION 3.2) + +set(CMAKE_CXX_STANDARD 20) +set(CMAKE_CXX_STANDARD_REQUIRED ON) + +project(Streamer) + +set(SRC_LIST + streamer.cpp +) + +add_executable(${PROJECT_NAME} ${SRC_LIST}) +target_compile_options(${PROJECT_NAME} PUBLIC -Wall -Werror -Wpedantic -Wextra) +target_include_directories(${PROJECT_NAME} PUBLIC ${CMAKE_SOURCE_DIR}) \ No newline at end of file diff --git a/AdvancedCppV2/Presentation/exercises/streamer/README.md b/AdvancedCppV2/Presentation/exercises/streamer/README.md new file mode 100644 index 0000000..f8e5992 --- /dev/null +++ b/AdvancedCppV2/Presentation/exercises/streamer/README.md @@ -0,0 +1,31 @@ +## Linux compilation + + > mkdir build + > cd build + > cmake -DCMAKE_BUILD_TYPE=Debug .. + > make + +## Exercise 1 + +* Open project streamer +* Add two C'tor: + * first will take initializer_list + * second const StreamInfo& +* initialize vector in initialization list + +## Exercise 2 + +* Open project streamer +* Add aliases for ip adress, port and vlan. + +## Exercise 3 + +* Open project streamer +* Create Streamer interface + * Allow to add data to stream + * Allow to add/remove receivers + * start/stop stream + * validate data +* Create Mpeg2Streamer class +* Create MjpegStreamer class +* Make some implementations that will allow to compile code \ No newline at end of file diff --git a/AdvancedCppV2/Presentation/exercises/streamer/solution/streamer.cpp b/AdvancedCppV2/Presentation/exercises/streamer/solution/streamer.cpp new file mode 100644 index 0000000..35d70cb --- /dev/null +++ b/AdvancedCppV2/Presentation/exercises/streamer/solution/streamer.cpp @@ -0,0 +1,29 @@ +#include +#include + +class Streamer { +public: + struct StreamInfo { + std::string sourceAddress_; + std::string destinationAddress_; + uint16_t sourcePort_; + uint16_t destinationPort_; + uint16_t vlan_; + }; + + Streamer(std::initializer_list info) + : info_(info) { + } + + Streamer(const StreamInfo& info) + : info_{info} { + } + +private: + std::vector info_; +}; + +int main() { + Streamer streamer({"192.168.0.0", "192.168.10.24", 5432, 5432, 12}); + Streamer streamer2{}; +} \ No newline at end of file diff --git a/AdvancedCppV2/Presentation/exercises/streamer/solution/streamer2.cpp b/AdvancedCppV2/Presentation/exercises/streamer/solution/streamer2.cpp new file mode 100644 index 0000000..654d1e1 --- /dev/null +++ b/AdvancedCppV2/Presentation/exercises/streamer/solution/streamer2.cpp @@ -0,0 +1,71 @@ +#include +#include + +template +struct StrongAlias { + // Other C'tors, for r-value etc... + StrongAlias(const T& value) + : value_(value) {} + + const T& operator*() const { return value_; } + T& operator*() { return value_; } + + // Need to add hash function and operator<< + auto operator<=>(const StrongAlias& other) const = default; + +private: + T value_; +}; + +using IpV4 = StrongAlias; +using IpV6 = StrongAlias; +using MacAddress = StrongAlias; + +class Streamer { +public: + using IpAddress = std::string; + using Port = uint16_t; + using Vlan = uint16_t; + + struct StreamInfo { + IpAddress sourceAddress_; + IpAddress destinationAddress_; + Port sourcePort_; + Port destinationPort_; + Vlan vlan_; + }; + + Streamer(std::initializer_list info) + : info_(info) { + } + + Streamer(const StreamInfo& info) + : info_{info} { + } + +private: + std::vector info_; +}; + +struct I {}; +struct A : I {}; +struct B : I {}; + +struct Foo { + Foo(I* inter): inter_(inter) {} + + I* inter_; +} + +int main() { + Streamer streamer({"192.168.0.0", "192.168.10.24", 5432, 5432, 12}); + Streamer streamer2{}; + + IpV4 ip{"192.168.0.1"}; + IpV4 ip2{"192.168.0.2"}; + + std::cout << std::boolalpha << (ip < ip2) << '\n'; + std::cout << std::boolalpha << (ip > ip2) << '\n'; + std::cout << std::boolalpha << (ip != ip2) << '\n'; + std::cout << std::boolalpha << (ip == ip2) << '\n'; +} \ No newline at end of file diff --git a/AdvancedCppV2/Presentation/exercises/streamer/streamer.cpp b/AdvancedCppV2/Presentation/exercises/streamer/streamer.cpp new file mode 100644 index 0000000..aaa9c26 --- /dev/null +++ b/AdvancedCppV2/Presentation/exercises/streamer/streamer.cpp @@ -0,0 +1,23 @@ +#include +#include + +class Streamer { +public: + struct StreamInfo { + std::string sourceAddress_; + std::string destinationAddress_; + uint16_t sourcePort_; + uint16_t destinationPort_; + uint16_t vlan_; + }; + + // Write C'tors here + +private: + std::vector info_; +}; + +int main() { + Streamer streamer({"192.168.0.0", "192.168.10.24", 5432, 5432, 12}); + Streamer streamer2{}; +} \ No newline at end of file diff --git a/AdvancedCppV2/Presentation/exercises/students/CMakeLists.txt b/AdvancedCppV2/Presentation/exercises/students/CMakeLists.txt new file mode 100644 index 0000000..ddbe8c3 --- /dev/null +++ b/AdvancedCppV2/Presentation/exercises/students/CMakeLists.txt @@ -0,0 +1,14 @@ +cmake_minimum_required(VERSION 3.2) + +set(CMAKE_CXX_STANDARD 20) +set(CMAKE_CXX_STANDARD_REQUIRED ON) + +project(Students) + +set(SRC_LIST + students.cpp +) + +add_executable(${PROJECT_NAME} ${SRC_LIST}) +target_compile_options(${PROJECT_NAME} PUBLIC -Wall -Werror -Wpedantic -Wextra) +target_include_directories(${PROJECT_NAME} PUBLIC ${CMAKE_SOURCE_DIR}) \ No newline at end of file diff --git a/AdvancedCppV2/Presentation/exercises/students/README.md b/AdvancedCppV2/Presentation/exercises/students/README.md new file mode 100644 index 0000000..193c733 --- /dev/null +++ b/AdvancedCppV2/Presentation/exercises/students/README.md @@ -0,0 +1,22 @@ +## Linux compilation + + > mkdir build + > cd build + > cmake -DCMAKE_BUILD_TYPE=Debug .. + > make + +## Exercise + +Open project `students`: + +* implement function `filterStudents`, +* Student should be disqualified whether his average is below `minAvergae`, +* Write an algorithm that prints students using ranges (do not implement friend operator<<) + +Output: + +```C++ +Name: Jane | index: 743561 | average: 4.44 +Name: Tom | index: 811111 | average: 4.36 +Name: Mike | index: 811111 | average: 4.45 +``` diff --git a/AdvancedCppV2/Presentation/exercises/students/solution/students.cpp b/AdvancedCppV2/Presentation/exercises/students/solution/students.cpp new file mode 100644 index 0000000..856366b --- /dev/null +++ b/AdvancedCppV2/Presentation/exercises/students/solution/students.cpp @@ -0,0 +1,49 @@ +#include +#include +#include +#include +#include +#include +#include + +namespace rn = std::ranges; + +struct Student { + int index_; + std::string name_; + double average_; +}; + +std::vector filterStudents(const std::vector>& students, double minAverage) { + std::vector result; + + rn::copy(students | + std::views::transform([](const auto& student) { return student.get(); }) | + std::views::filter([minAverage](const auto& student) { return student->average_ <= minAverage; }), + std::back_inserter(result)); + + return result; +} + +int main() { + std::vector> students; + students.push_back(std::make_unique(123456, "Jordan", 4.53)); + students.push_back(std::make_unique(654321, "Michael", 4.51)); + students.push_back(std::make_unique(246892, "John", 4.56)); + students.push_back(std::make_unique(743561, "Jane", 4.44)); + students.push_back(std::make_unique(811111, "Anna", 4.46)); + students.push_back(std::make_unique(811111, "Tom", 4.36)); + students.push_back(std::make_unique(811111, "Jerry", 4.56)); + students.push_back(std::make_unique(811111, "Mike", 4.45)); + + const auto res = filterStudents(students, 4.45); + rn::transform(res, + std::ostream_iterator(std::cout, "\n"), + [](const Student* student) { + std::ostringstream os; + os << "Name: " << student->name_ + << " | index: " << student->index_ + << " | average: " << student->average_; + return os.str(); + }); +} \ No newline at end of file diff --git a/AdvancedCppV2/Presentation/exercises/students/students.cpp b/AdvancedCppV2/Presentation/exercises/students/students.cpp new file mode 100644 index 0000000..032a64d --- /dev/null +++ b/AdvancedCppV2/Presentation/exercises/students/students.cpp @@ -0,0 +1,34 @@ +#include +#include +#include +#include +#include +#include +#include + +namespace rn = std::ranges; + +struct Student { + int index_; + std::string name_; + double average_; +}; + +std::vector filterStudents(const std::vector>& students, double minAverage) { + // Implement method here +} + +int main() { + std::vector> students; + students.push_back(std::make_unique(123456, "Jordan", 4.53)); + students.push_back(std::make_unique(654321, "Michael", 4.51)); + students.push_back(std::make_unique(246892, "John", 4.56)); + students.push_back(std::make_unique(743561, "Jane", 4.44)); + students.push_back(std::make_unique(811111, "Anna", 4.46)); + students.push_back(std::make_unique(811111, "Tom", 4.36)); + students.push_back(std::make_unique(811111, "Jerry", 4.56)); + students.push_back(std::make_unique(811111, "Mike", 4.45)); + + const auto res = filterStudents(students, 4.45); + // Print result here using ranges (do not create friend operator<<) +} \ No newline at end of file diff --git a/AdvancedCppV2/Presentation/img/cyclic_dependencies.gif b/AdvancedCppV2/Presentation/img/cyclic_dependencies.gif new file mode 100644 index 0000000..d0c6e4a Binary files /dev/null and b/AdvancedCppV2/Presentation/img/cyclic_dependencies.gif differ diff --git a/AdvancedCppV2/Presentation/img/cyclicinverted.png b/AdvancedCppV2/Presentation/img/cyclicinverted.png new file mode 100644 index 0000000..311cc82 Binary files /dev/null and b/AdvancedCppV2/Presentation/img/cyclicinverted.png differ diff --git a/AdvancedCppV2/Presentation/img/kosz.png b/AdvancedCppV2/Presentation/img/kosz.png new file mode 100644 index 0000000..d93388b Binary files /dev/null and b/AdvancedCppV2/Presentation/img/kosz.png differ diff --git a/AdvancedCppV2/Presentation/img/kot.jpg b/AdvancedCppV2/Presentation/img/kot.jpg new file mode 100644 index 0000000..d656c64 Binary files /dev/null and b/AdvancedCppV2/Presentation/img/kot.jpg differ diff --git a/AdvancedCppV2/Presentation/img/memory.png b/AdvancedCppV2/Presentation/img/memory.png new file mode 100644 index 0000000..b2c099f Binary files /dev/null and b/AdvancedCppV2/Presentation/img/memory.png differ diff --git a/AdvancedCppV2/Presentation/img/sharedptr10inverted.png b/AdvancedCppV2/Presentation/img/sharedptr10inverted.png new file mode 100644 index 0000000..eb9565a Binary files /dev/null and b/AdvancedCppV2/Presentation/img/sharedptr10inverted.png differ diff --git a/AdvancedCppV2/Presentation/img/sharedptr11inverted.png b/AdvancedCppV2/Presentation/img/sharedptr11inverted.png new file mode 100644 index 0000000..7ed1afc Binary files /dev/null and b/AdvancedCppV2/Presentation/img/sharedptr11inverted.png differ diff --git a/AdvancedCppV2/Presentation/img/sharedptr1inverted.png b/AdvancedCppV2/Presentation/img/sharedptr1inverted.png new file mode 100644 index 0000000..f7af228 Binary files /dev/null and b/AdvancedCppV2/Presentation/img/sharedptr1inverted.png differ diff --git a/AdvancedCppV2/Presentation/img/sharedptr2inverted.png b/AdvancedCppV2/Presentation/img/sharedptr2inverted.png new file mode 100644 index 0000000..c7a20a5 Binary files /dev/null and b/AdvancedCppV2/Presentation/img/sharedptr2inverted.png differ diff --git a/AdvancedCppV2/Presentation/img/sharedptr3inverted.png b/AdvancedCppV2/Presentation/img/sharedptr3inverted.png new file mode 100644 index 0000000..821ce77 Binary files /dev/null and b/AdvancedCppV2/Presentation/img/sharedptr3inverted.png differ diff --git a/AdvancedCppV2/Presentation/img/sharedptr4inverted.png b/AdvancedCppV2/Presentation/img/sharedptr4inverted.png new file mode 100644 index 0000000..0230980 Binary files /dev/null and b/AdvancedCppV2/Presentation/img/sharedptr4inverted.png differ diff --git a/AdvancedCppV2/Presentation/img/sharedptr5inverted.png b/AdvancedCppV2/Presentation/img/sharedptr5inverted.png new file mode 100644 index 0000000..465fa2f Binary files /dev/null and b/AdvancedCppV2/Presentation/img/sharedptr5inverted.png differ diff --git a/AdvancedCppV2/Presentation/img/sharedptr6inverted.png b/AdvancedCppV2/Presentation/img/sharedptr6inverted.png new file mode 100644 index 0000000..b4b38f0 Binary files /dev/null and b/AdvancedCppV2/Presentation/img/sharedptr6inverted.png differ diff --git a/AdvancedCppV2/Presentation/img/sharedptr7inverted.png b/AdvancedCppV2/Presentation/img/sharedptr7inverted.png new file mode 100644 index 0000000..2cfdf23 Binary files /dev/null and b/AdvancedCppV2/Presentation/img/sharedptr7inverted.png differ diff --git a/AdvancedCppV2/Presentation/img/sharedptr8inverted.png b/AdvancedCppV2/Presentation/img/sharedptr8inverted.png new file mode 100644 index 0000000..d251d10 Binary files /dev/null and b/AdvancedCppV2/Presentation/img/sharedptr8inverted.png differ diff --git a/AdvancedCppV2/Presentation/img/sharedptr9inverted.png b/AdvancedCppV2/Presentation/img/sharedptr9inverted.png new file mode 100644 index 0000000..c337d95 Binary files /dev/null and b/AdvancedCppV2/Presentation/img/sharedptr9inverted.png differ diff --git a/AdvancedCppV2/Presentation/img/uniqueptrinverted.png b/AdvancedCppV2/Presentation/img/uniqueptrinverted.png new file mode 100644 index 0000000..11ac980 Binary files /dev/null and b/AdvancedCppV2/Presentation/img/uniqueptrinverted.png differ diff --git a/AdvancedCppV2/Presentation/img/weakptrinverted.png b/AdvancedCppV2/Presentation/img/weakptrinverted.png new file mode 100644 index 0000000..0cf727a Binary files /dev/null and b/AdvancedCppV2/Presentation/img/weakptrinverted.png differ diff --git a/AdvancedCppV2/Presentation/index.html b/AdvancedCppV2/Presentation/index.html new file mode 100644 index 0000000..ae9e665 --- /dev/null +++ b/AdvancedCppV2/Presentation/index.html @@ -0,0 +1,236 @@ + + + + + + + Advanced Cpp + + + + + + + + + + + + + +
+
+ +
+

Advanced Cpp

+
+

Altkom Akademia

+ https://www.altkomakademia.pl + +
+
+ Altkom Akademia + +48 801 258 566 +
+ +
+ +
+ Altkom Akademia + Mateusz Adamski + nauka.programowania.ma@gmail.com +
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

Altkom Akademia

+ https://www.altkomakademia.pl + +

+ +
+
+
+ altkomakademia +
+ Zapraszamy do współpracy + ALTKOM AKADEMIA + ul. Chłodna 51, budynek WTT, + 00-867 Warszawa + Telefon: (+48 22) 460 99 99, + Fax: (+48 22) 460 99 90 + warszawa@altkom.pl +
+
+
+ +
+ +
+ Mateusz Adamski + nauka.programowania.ma@gmail.com +
+
+
+ +
+ +
+ + + + + + diff --git a/AdvancedCppV2/Presentation/introduction.md b/AdvancedCppV2/Presentation/introduction.md new file mode 100644 index 0000000..e7c750d --- /dev/null +++ b/AdvancedCppV2/Presentation/introduction.md @@ -0,0 +1,59 @@ + + +

Presentation authors

+ +
+
+ Mateusz +
+
+ Mateusz Adamski +
+
+___ + + +

Mateusz Adamski

+ +
+
+ +Experience: + +* Trainer at Coders School and Altkom Academy +* C++ developer: worked in Nokia, Opera and Consult red + +Training experience: + +* [C++ trainings @ Coders School](https://coders.school/) +* [C++ trainings @ Altkom Academy](https://www.altkomakademia.pl/) +* [Nokia Academy](http://nokiawroclaw.pl/nasze-akcje/akademia/) +* Internal corporate trainings + +
+ +
+ Mateusz +
+
+___ + + +## Let's introduce yourself! + +* Your name and experience form C++ programing. +* Do you use modern C++ features or prefer old old proven solutions? +* Did you use any C++20 features? +* Have you ever used weak_ptr, when? +* Do you know how control block works? +* What do you expect from today's session? + +___ + + +## Contract + +* 🎰 Vegas rule +* 🗣 Discussion, not a lecture +* ☕️ Additional breaks on demand +* ⌚️ Be on time after breaks diff --git a/AdvancedCppV2/Presentation/moder_cpp_cpp11.md b/AdvancedCppV2/Presentation/moder_cpp_cpp11.md new file mode 100644 index 0000000..ff617c7 --- /dev/null +++ b/AdvancedCppV2/Presentation/moder_cpp_cpp11.md @@ -0,0 +1,358 @@ +## Cpp11 + + +* A quick reminder of lesser known features + * static_assert + * Uniform initialization + * In-class initialization of non-static variables + * initializer_list + * alias + * Template alias + * C'tor inheritance + * Attributes + * Data structure alignment +___ + + +## static_assert + +```cpp +template +void swap(T& a, T& b) +{ + static_assert(std::is_copy_constructible::value, + "Swap requires copying"); + static_assert(std::is_nothrow_move_constructible_v && + std::is_nothrow_move_assignable_v); + auto c = b; + b = a; + a = c; +} +``` + + +**Rationale**: Preventing compilation on user defined conditions (usually specific types). + + +Performs compile-time assertion checking. Usually used with `` library. + + +The message is optional from C++17. + + +___ + + +## C++98/03 initialization + +

+int a;                            // undefined value                           
+int b(5);                         // direct initialization, b = 5              
+int c = 10;                       // copy initialization, c = 10               
+int d = int();                    // default initialization, d = 0             
+int e();                          // function declaration - "most vexing parse"
+
+int values[] = { 1, 2, 3, 4 };    // brace initialization of aggregate         
+int array[] = { 1, 2, 3.5 };      // C++98 - ok, implicit type narrowing       
+
+struct P { int a, b; };                                                        
+P p = { 20, 40 };                 // brace initialization of POD               
+
+std::complex<double> c(4.0, 2.0); // initialization of classes                 
+
+std::vector<std::string> names;   // no initialization for list of values      
+names.push_back("John");                                                       
+names.push_back("Jane");                                                       
+
+ + +___ + + +## C++11 initialization with {} + +

+int a;                               // still undefined value                    
+int b{5};                            // brace initialization, b = 5              
+int c{};                             // brace initialization, c = 0              
+
+int values[] = { 1, 2, 3, 4 };       // brace initialization of aggregate        
+int array[] = { 1, 2, 3.5 };         // C++11: error - implicit type narrowing   
+
+struct P { int a, b;                                                             
+P p = { 20, 40 };                    // brace initialization of POD              
+
+std::complex<double> c{4.0, 2.0};    // brace initialization calls adequate c-tor
+
+std::vector<std::string> names = { "John", "Jane" };                             
+                                    // brace initialization of vector           
+
+ +**Rationale**: eliminate problematic initialization cases from C++98, initialization of STL containers, have one universal way of initialization. + + +___ + + +## In-class initialization of non-static variables + +```cpp +struct Foo +{ + Foo() {} + Foo(std::string a) : a_(a) {} + void print() { std::cout << a_ << std::endl; } + +private: + std::string a_ = "Foo"; // C++98: error, C++11: OK + static const unsigned VALUE = 20u; // C++98: OK, C++11: OK +}; + +Foo().print(); // Foo +Foo("Bar").print(); // Bar +``` + +___ + + +## `std::initializer_list` + +```cpp +auto values = {1, 2, 3, 4, 5}; // values is std::initializer_list +std::vector v = {1, 2, -3}; // creates a vector from + // std::initializer_list +``` + +* Defined in initializer_list header +* Elements are kept in an array +* Elements are immutable +* Elements must be copyable +* Have limited interface and access via iterators - begin(), end(), size() +* Should be passed to functions by value + +___ + + +## Constructor priority + +

+template<class Type>                                               
+class Bar {                                                        
+    std::vector<Type> values_;                                     
+public:                                                            
+    Bar(std::initializer_list<Type> values) : values_(values) {}   
+    Bar(Type a, Type b) : values_{a, b} {}                         
+};                                                                 
+
+Bar<int> c = {1, 2, 5, 51};   // calls std::initializer_list c-tor
+Bar<int> d{1, 2, 5, 51};      // calls std::initializer_list c-tor
+Bar<int> e = {1, 2};          // calls std::initializer_list c-tor
+Bar<int> f{1, 2};             // calls std::initializer_list c-tor
+Bar<int> g(1, 2);             // calls Bar(Type a, Type b) c-tor  
+Bar<int> h = {};              // calls std::initializer_list c-tor
+                       // or default c-tor if exists
+Bar<std::unique_ptr> c = {new int{1}, new int{2}};                
+// error - std::unique_ptr is non-copyable                        
+
+ +C-tor with std::initializer_list has greater priority, even if other c-tors match. + + +___ + + +## Exercise 1 + +* Open project streamer +* Add two C'tor: + * first will take initializer_list + * second const StreamInfo& +* initialize vector in initialization list +___ + + +## Type aliasing + +```cpp +typedef std::ios_base::fmtflags Flags; +using Flags = std::ios_base::fmtflags; // the same as above +Flags fl = std::ios_base::dec; +``` + + +```cpp +typedef std::vector> SocketContainer; +std::vector> typedef SocketContainer; // correct ;) +using SocketContainer = std::vector>; +``` + + +**Rationale**: More intuitive alias creation. + + +A type alias is a name that refers to a previously defined type. It could be created with typedef. +From C++11 type aliases should be created with `using` keyword. + + +___ + + +### Template aliases + +```cpp +struct ThemedLabelToogleButton { ... } + +template +using ButtonMap = std::map; + +ButtonMap> my_map; +// std::map +``` + +Type alias can be parametrized with templates. It was impossible with typedef. + + +Template aliases cannot be specialized. + + +___ + + +### Constructors inheritance + +```cpp +struct A { + explicit A(int); + int a; +}; + +struct B : A { + using A::A; // implicit declaration of B::B(int) + B(int, int); // overloaded inherited Base ctor +}; +``` + +* Derived class constructors are generated implicitly, only if they are used +* Derived class constructors take the same arguments as base class constructors +* Derived class constructor calls according base class constructor +* Constructor inheritance in a class that adds a new field might be risky - new fields can be uninitialized + +___ + + +## Exercise 2 + +* Open project streamer +* Add aliases for ip adress, port and vlan. + +___ + + +## Attributes + + +___ + + +### Standard attributes + +* [[noreturn]] - function does never return, like std::terminate. If it does, we have UB +* [[deprecated]] (C++14) - function is deprecated +* [[deprecated("reason")]] (C++14) - as above, but compiler will emit the reason +* [[fallthrough]] (C++17) - in switch statement, indicated that fall through is intentional +* [[nodiscard]] (C++17) - you cannot ignore value returned from function +* [[maybe_unused]] (C++17) - suppress compiler warning on unused class, typedef, variable, function, etc. + + +___ + + +## `[[noreturn]]` attribute + +```c++ +[[noreturn]] void f() { + throw "error"; + // OK +} + +[[noreturn]] void q(int i) { + if (i > 0) { + throw "positive"; + } + // the behavior is undefined if called with argument <=0 +} +``` +___ + + +## `[[deprecated]] attribute` + +Attributes for namespaces and enumerators are available from C++17. + +```c++ +[[deprecated("Please use f2 instead")]] int f1(); + +enum E { + foo = 0, + bar [[deprecated]] = foo +}; +E e = bar; // Emits warning + +namespace [[deprecated]] old_stuff { + void legacy(); +} +old_stuff::legacy(); //Emits warning +``` +___ + + +## `[[fallthrough]]` attribute + +```c++ +void f(int n){ + void g(), h(), i(); + switch(n) { + case 1: + case 2: + g(); + [[fallthrough]]; + case 3: // no warning on fallthrough + h(); + case 4: // compiler may warn on fallthrough + i(); + [[fallthrough]]; // illformed, not before a case label + } +} +``` + +___ + + +## `[[nodiscard]]` attribute + +```c++ +struct [[nodiscard]] error_info {}; +error_info process(Data*); + +// ... + +void passMessage() { + auto data = getData(); + process(data); // compiler warning, discarding error_info +} +``` + +___ + + +## `[[maybe_unused]]` attributes + +```c++ +[[maybe_unused]] void f([[maybe_unused]] bool thing1, + [[maybe_unused]] bool thing2) +{ + [[maybe_unused]] bool b = thing1 && thing2; + assert (b); // in release mode, assert is compiled out, and b is unused + // no warning because it is declared [[maybe_unused]] +} // parameters thing1 and thing2 are not used, no warning +``` \ No newline at end of file diff --git a/AdvancedCppV2/Presentation/moder_cpp_cpp14.md b/AdvancedCppV2/Presentation/moder_cpp_cpp14.md new file mode 100644 index 0000000..8aa3d4d --- /dev/null +++ b/AdvancedCppV2/Presentation/moder_cpp_cpp14.md @@ -0,0 +1,256 @@ +## Cpp14 + + +* A quick reminder of lesser known features + * decltype(auto) + * Variable templates + * Binary literals (Finaly!) + * Digit separators +___ + + +## `decltype` + +**Rationale**: Deduction provided in contexts where auto is not allowed. + +`decltype` allows a compiler to deduce the type of the variable or expression, eg. the returned type can be deduced from function parameters. + + +```cpp +std::map collection; + +decltype(collection) other; // other has type of collection +decltype(collection)::mapped_type value; // value is float + +template +auto add(T1 a, T2 b) -> decltype(a + b) // from C++14 decltype not necessary +{ + return a + b; +} +``` + +___ + + +It is useful in various scenarios: + +```C++ +auto compare = [](const auto &first, const auto &second) { + if (first.size() == second.size()) { + return first < second; + } + return first.size() < second.size(); +}; + +std::map map(compare); +map.emplace("C++20", 20); +map.emplace("C++1234", 1234); +map.emplace("Bababab", 12); +map.emplace("Abababa", 13); + +for (const auto &[standard, number] : map) { + std::cout << "Standard: " << standard << " | number: " << number << '\n'; + /* Output: + Standard: C++20 | number: 20 + Standard: Abababa | number: 13 + Standard: Bababab | number: 12 + Standard: C++1234 | number: 1234 */ +} +``` + +___ + + +Since C++20 we can use lambda expressions in unevaluated operands: + +```C++ +using SquareRoot = decltype([](const int val) { + return std::sqrt(val); +}); + +using Compare = decltype([](const auto &first, const auto &second) { + if (first.size() == second.size()) { + return first < second; + } + return first.size() < second.size(); +}); + +int main() { + std::vector vec(30); + std::iota(begin(vec), end(vec), 0); + std::transform(begin(vec), end(vec), begin(vec), SquareRoot{}); + for (const auto& el : vec) { + std::cout << el << ' '; + } + // Output: + // 0 1 1 1 2 2 2 2 2 3 3 3 3 3 3 3 4 4 4 4 4 4 4 4 4 5 5 5 5 5 + + // Compare lambda will be constructed by default + std::map map; + map.emplace("C++20", 20); + map.emplace("C++1234", 1234); + map.emplace("Bababab", 12); + map.emplace("Abababa", 13); +} +``` + +Closure types are not default constructible before C++20. In C++20 a closure type that has no capture is default constructible. That's why we can do a litle magic here :) + + +___ + + +## `decltype(auto)` + +`decltype(auto)` deduction mechanism preserves type modifiers (references, const, volatile). + +`auto` deduction mechanism does not preserve type modifiers. + + +When you write generic code you want to be able to perfectly forward a return type without knowing whether you are dealing with a reference or a value. + + +```cpp +template +decltype(auto) Example(Fun fun, Args&&... args) +{ + return fun(std::forward(args)...); +} +``` + +___ + + +## Let's test it + +We have the following class: + +```C++ +class Server { +public: + bool addRequest(const std::string& serviceId, const std::string& request) { + return requests_.emplace(serviceId, request).second; + } + + std::string& getRequest(const std::string& serviceId) { + if (const auto it = requests_.find(serviceId) ; it != std::cend(requests_)) { + return it->second; + } + throw std::runtime_error("Invalid serviceId"); + } + +private: + std::map requests_; +}; + +int main() { + Server server; + server.addRequest("SuperService", "Eat meat first!"); + + server.getRequest("SuperService") += " Leave the potatoes"; + std::cout << server.getRequest("SuperService") << '\n'; + // Eat meat first! Leave the potatoes +} +``` + +___ + + +Now let's use it with generic function, but without `decltype(auto)` + +```C++ +template +auto RunFun(Fun fun, Args&&... args) +{ + return fun(std::forward(args)...); +} + +int main() { + Server server; + server.addRequest("SuperService", "Eat meat first!"); + + // Write that we want to return std::string& + RunFun([&server](const auto& id) -> std::string& { return server.getRequest(id); }, + "SuperService") += " Leave the potatoes"; + std::cout << server.getRequest("SuperService") << '\n'; + // Output: Eat meat first! + // Compiler didn't emit any warning! +} +``` + +___ + + +Now fix this with `decltype(auto)` + +```C++ +template +decltype(auto) RunFun(Fun fun, Args&&... args) +{ + return fun(std::forward(args)...); +} + +int main() { + Server server; + server.addRequest("SuperService", "Eat meat first!"); + + // Write that we want to return std::string& + RunFun([&server](const auto& id) -> std::string& { return server.getRequest(id); }, + "SuperService") += " Leave the potatoes"; + std::cout << server.getRequest("SuperService") << '\n'; + // Output: Eat meat first! Leave the potatoes +} +``` + +Now we avoid misleading and don't waste time on debugging sessions! + + +___ + + +## Variable templates + +```C++ +template +constexpr T pi = T(3.141592653589793238462643383); + +// Usual specialization rules apply: +template <> +constexpr const char* pi = "pi"; + +template <> +constexpr const int pi = 4; + +int main() { + std::cout << pi << '\n'; // 3.14159 + std::cout << pi << '\n'; // pi + std::cout << pi << '\n'; // 3 + std::cout << pi << '\n'; // 4 + + return 0; +} +``` +___ + + +## Binary literals + +```C++ +int main() { + std::cout << 0b10101010 << '\n'; // 170 + const int val = 0b1111; + std::cout << (val ^ 0b1010) << '\n'; // 5 + + return 0; +} +``` + + +## Digit separators + + +```C++ +const int milion = 1'000'000; +const double val = 123'456'789'101.000; +``` + diff --git a/AdvancedCppV2/Presentation/moder_cpp_cpp17_constexpr.md b/AdvancedCppV2/Presentation/moder_cpp_cpp17_constexpr.md new file mode 100644 index 0000000..420f52e --- /dev/null +++ b/AdvancedCppV2/Presentation/moder_cpp_cpp17_constexpr.md @@ -0,0 +1,425 @@ +## constexpr - one of the most undervalued feature in modern C++ (1) + +* constexpr was introduced in C++11 + * constexpr values are know during compilation process + * Function also could be constexpr with some restriction: + * they may only have exactly one statement and this statement had to be a return statement + * not allowed to have any side effects, like if-else + * not allowed to have exception and try-catch block + * can use ternary operator + * Usually wrote recurent rather then iterative functions + * Functions behave like normal functions (not solved during compilation) when working with non-constexpr arguments + * Class/ struct could have constexpr C'tor and member functions +* In C++14 introduced: + * Less restrictions for functions: + * more then one return + * can use if-else +___ + +### constexpr - one of the most undervalued feature in modern C++ (2) + +* In C++17 introduced: + * constexpr class string_view + * constexpr std::array + * constexpr iterator for array and std::begin, std::end functions + * constexpr lambda +* In C++20 introduced: + * constexpr STL algorithms + * constexpr std::vector and std::string and their iterators. (not supported by clang and gcc. Surprisely its supported by MSVC STL) + * Allow to use try-catch in constexpr functions + * Allow to allocate and deallocate values on heap, but need to free them before exit function + * Allow to create virtual functions + * Allow to use asm code block +___ + +## C++11 constexpr function + +```C++ +#include + +constexpr bool isLower(char c) { + return c >= 'a' && c <= 'z'; +} + +template +constexpr size_t countLower(const T (&str)[N], size_t current, size_t counter) { + return current == N + ? counter + : isLower(str[current]) + ? countLower(str, current + 1, counter + 1) + : countLower(str, current + 1, counter); +} + +int main() { + static_assert(9 == countLower("Ala has a cat", 0, 0)); +} +``` + + +```Bash +xor eax,eax +ret +nop WORD PTR cs:[rax+rax*1+0x0] +nop DWORD PTR [rax] +``` + + + + + +___ + +## C++14 constexpr function + +```C++ +constexpr bool isLower(char c) { + return c >= 'a' && c <= 'z'; +} + +template +constexpr size_t countLower(const T (&str)[N]) { + size_t counter = 0; + for (auto c : str) { + if (isLower(c)) { + ++counter; + } + } + + return counter; +} + +int main() { + static_assert(9 == countLower("Ala has a cat")); +} +``` + + +```Bash +xor eax,eax +ret +nop WORD PTR cs:[rax+rax*1+0x0] +nop DWORD PTR [rax] +``` + + + + + +___ + +## C++17 constexpr function (1) + +```C++ +template +constexpr size_t countLower(const T (&str)[N]) { + constexpr auto isLower = [](char c) { return c >= 'a' && c <= 'z'; }; + size_t counter = 0; + + for (auto c : str) { + if (isLower(c)) { + ++counter; + } + } + + return counter; +} + +int main() { + static_assert(9 == countLower("Ala has a cat")); +} +``` + + +```Bash +xor eax,eax +ret +nop WORD PTR cs:[rax+rax*1+0x0] +nop DWORD PTR [rax] +``` + + + + + +___ + +## C++17 constexpr function (2) + +```C++ +constexpr size_t countLower(const std::string_view& str) { + constexpr auto isLower = [](char c) { return c >= 'a' && c <= 'z'; }; + size_t counter = 0; + + for (size_t i = 0 ; i < str.size() ; ++i) { + if (isLower(str[i])) { + ++counter; + } + } + + return counter; +} + +int main() { + static_assert(9 == countLower("Ala has a cat")); +} +``` + + +```Bash +xor eax,eax +ret +cs nop WORD PTR [rax+rax*1+0x0] +nop DWORD PTR [rax] +``` + + + + + +___ + +## C++20 constexpr function +```C++ +constexpr size_t countLower(const std::string& str) { + constexpr auto isLower = [](char c) { return c >= 'a' && c <= 'z'; }; + size_t counter = 0; + + for (size_t i = 0 ; i < str.size() ; ++i) { + if (isLower(str[i])) { + ++counter; + } + } + + return counter; +} + +int main() { + static_assert(9 == countLower(std::string("Ala has a cat"))); +} +``` + + + + +___ + +## C++20 constexpr function - algorithms + +```C++ +constexpr size_t countLower(const std::string& str) { + constexpr auto isLower = [](char c) { return c >= 'a' && c <= 'z'; }; + return std::count_if(cbegin(str), cend(str), isLower); +} + +int main() { + static_assert(9 == countLower(std::string("Ala has a cat"))); +} +``` + + + + +___ + +## C++20 constexpr - allocation on heap (1) + +```C++ +template +constexpr std::array generatePseudoRandom(int from, int to) { + std::array arr; + const int seed = ((N << 1) ^ (from << to) ^ to) ^ ((from + to) ^ (N << 3)); + const size_t size = to - from; + auto tmp = new int[size]; + std::iota(tmp, tmp + size, from); + + for (int i = 0; i < N; ++i) { + arr[i] = tmp[(seed ^ i) % size]; + } + + delete[] tmp; + return arr; +} + +int main() { + static_assert(generatePseudoRandom(10, 20).size() == 10); +} +``` + + +```C++ +Will print: 18 19 16 17 14 15 12 13 10 11 +``` + + +```Bash +xor eax,eax +ret +cs nop WORD PTR [rax+rax*1+0x0] +nop DWORD PTR [rax] +``` + + + + + +___ + +## C++20 constexpr - allocation on heap (1) + +If we forget to add delete[], compiler will detect it! + +```C++ +template +constexpr std::array generatePseudoRandom(int from, int to) { + std::array arr; + const int seed = ((N << 1) ^ (from << to) ^ to) ^ ((from + to) ^ (N << 3)); + const size_t size = to - from; + auto tmp = new int[size]; + std::iota(tmp, tmp + size, from); + + for (int i = 0; i < N; ++i) { + arr[i] = tmp[(seed ^ i) % size]; + } + + //delete[] tmp; + return arr; +} + +int main() { + static_assert(generatePseudoRandom(10, 20).size() == 10); +} +``` + + +```C++ +: In function 'int main()': +:22:64: error: non-constant condition for static assertion + 22 | static_assert(generatePseudoRandom(10, 20).size() == 10); + | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~~ +:10:16: error: '(generatePseudoRandom(10, 20).std::array::size() == 10)' is not a constant expression because allocated storage has not been deallocated + 10 | auto tmp = new int[size]; + | ^~~~~~~~~~~~~ +Execution build compiler returned: 1 +``` + + +___ + +### contexpr-if (1) + +* Who uses SFINAE? +* Who likes SFINAE? + +```C++ +namespace { +constexpr double epsilon = 0.000001; +} + +template +constexpr std::enable_if_t, bool> +equal(T lhs, T rhs) { + return std::abs(lhs - rhs) < epsilon; +} + +template +constexpr std::enable_if_t, bool> +equal(T lhs, T rhs) { + return lhs == rhs; +} + +int main() { + static_assert(equal(10, 10) == true); + static_assert(equal(10.123f, 10.123f) == true); + static_assert(equal(10.45678, 10.45678) == true); +} +``` + + +```C++ +xor eax,eax +ret +cs nop WORD PTR [rax+rax*1+0x0] +nop DWORD PTR [rax] +``` + + +___ + +### contexpr-if (2) + +```C++ +template +constexpr bool equal(T lhs, T rhs) { + constexpr double epsilon = 0.000001; + + if constexpr (std::is_floating_point_v) { + return std::abs(lhs - rhs) < epsilon; + } else { + return lhs == rhs; + } +} + +int main() { + static_assert(equal(10, 10) == true); + static_assert(equal(10.123f, 10.123f) == true); + static_assert(equal(10.45678, 10.45678) == true); +} +``` + + +```C++ +xor eax,eax +ret +cs nop WORD PTR [rax+rax*1+0x0] +nop DWORD PTR [rax] +``` + + +___ + +### C++20 concept + +```C++ +template +requires std::is_floating_point_v +constexpr bool equal(T lhs, T rhs) { + constexpr double epsilon = 0.000001; + + return std::abs(lhs - rhs) < epsilon; +} + +// Work only, when both types are equal! +constexpr bool equal(auto lhs, auto rhs) { + return lhs == rhs; +} + +int main() { + static_assert(equal(10, 10) == true); + static_assert(equal(10.123f, 10.123f) == true); + static_assert(equal(10.45678, 10.45678) == true); +} +``` + + +```C++ +xor eax,eax +ret +cs nop WORD PTR [rax+rax*1+0x0] +nop DWORD PTR [rax] +``` + + diff --git a/AdvancedCppV2/Presentation/moder_cpp_cpp17_filesystem.md b/AdvancedCppV2/Presentation/moder_cpp_cpp17_filesystem.md new file mode 100644 index 0000000..8427dd1 --- /dev/null +++ b/AdvancedCppV2/Presentation/moder_cpp_cpp17_filesystem.md @@ -0,0 +1,341 @@ +## Filesystem + + +Since C++17 we can efficiently work with the file systems on all OS like Mac, Windows, and various Linux distributions. + +```C++ +namespace fs = std::filesystem; + +void printStatsForDirectory(const fs::path& dir_path) { + std::cout << "Statistics:\n"; + std::cout << ".cpp files: " + << std::count_if(fs::recursive_directory_iterator(dir_path), {}, + [](const auto& entry) { + return entry.is_regular_file() && entry.path().extension() == ".cpp"; + }) << '\n'; + std::cout << ".md files: " + << std::count_if(fs::recursive_directory_iterator(dir_path), {}, + [](const auto& entry) { + return entry.is_regular_file() && entry.path().extension() == ".md"; + }) << '\n'; + std::cout << ".h files: " + << std::count_if(fs::recursive_directory_iterator(dir_path), {}, + [](const auto& entry) { + return entry.is_regular_file() && entry.path().extension() == ".h"; + }) << '\n'; + std::cout << "Total size: " + << (std::accumulate(fs::recursive_directory_iterator(dir_path), {}, 0, + [](const auto& init, const auto& entry) { + return init + (entry.is_regular_file() ? entry.file_size() : 0); + }) >> 20) << " MB\n"; +} +``` + + + + +___ + + +## Output + +```C++ +int main() { + const auto path{fs::current_path()}; + std::cout << "current path: " << path << '\n'; + const auto path2 = path.parent_path().parent_path(); + std::cout << "path2: " << path2 << '\n'; + + printStatsForDirectory(path2); +} +``` + +```bash +current path: "C:\\Users\\madamski\\Documents\\altcom_academy\\Nokia2022\\Advanced\\Course_part1\\exercises\\streamer" +path2: "C:\\Users\\madamski\\Documents\\altcom_academy\\Nokia2022\\Advanced\\Course_part1" +Statistics: +.cpp files: 16 +.md files: 53 +.h files: 47 +Total size: 103 MB +``` + + +___ + + +## Info about system space + +```C++ +void printSpaceInfo(auto const& dirs, int width = 10) { + std::cout << std::left; + for (const auto s : {"Capacity", "Free", "Available", "Dir"}) { + std::cout << "| " << std::setw(width) << s << std::string(3, ' '); + } + std::cout << '\n'; + + for (auto const& dir : dirs) { + const auto info = fs::space(dir); + std::cout + << "| " << std::setw(width) << (info.capacity >> 30) << " GB" + << "| " << std::setw(width) << (info.free >> 30) << " GB" + << "| " << std::setw(width) << (info.available >> 30) << " GB" + << "| " << dir << '\n'; + } +} + +int main() { + const auto dirs = {"C:\\", "D:\\", "E:\\"}; + printSpaceInfo(dirs); + /* + | Capacity | Free | Available | Dir + | 237 GB| 15 GB| 15 GB| C:\ + | 383 GB| 179 GB| 179 GB| D:\ + | 463 GB| 220 GB| 220 GB| E:\ + */ +} +``` + + +___ + + +## Permissions + +```C++ +void printPerms(fs::perms p) { + std::cout << ((p & fs::perms::owner_read) != fs::perms::none ? "r" : "-") + << ((p & fs::perms::owner_write) != fs::perms::none ? "w" : "-") + << ((p & fs::perms::owner_exec) != fs::perms::none ? "x" : "-") + << ((p & fs::perms::group_read) != fs::perms::none ? "r" : "-") + << ((p & fs::perms::group_write) != fs::perms::none ? "w" : "-") + << ((p & fs::perms::group_exec) != fs::perms::none ? "x" : "-") + << ((p & fs::perms::others_read) != fs::perms::none ? "r" : "-") + << ((p & fs::perms::others_write) != fs::perms::none ? "w" : "-") + << ((p & fs::perms::others_exec) != fs::perms::none ? "x" : "-") + << '\n'; +} + +int main() { + for (const auto& entry : fs::directory_iterator(fs::current_path())) { + if (fs::is_regular_file(entry.path())) { + std::cout << "File: " + << std::left << std::setw(20) + << entry.path().filename() + << " | Permissions: "; + printPerms(fs::status(entry.path()).permissions()); + } + } + /* + File: "CMakeLists.txt" | Permissions: rw-rw-rw- + File: "example.exe" | Permissions: rwxrwxrwx + File: "README.md" | Permissions: rw-rw-rw- + File: "streamer.cpp" | Permissions: rw-rw-rw- + */ +} +``` + + +___ + + +## Exercise + +Open project `files`. Write a program which modify files under `project` directory: + +- Change permision for all .exe files to `rwxrw-rw-`. +- Change permision for all .cpp and .hpp files to `rw-r--r--`. + +You should get output like this: + + +```Bash +File: "fileA.cpp" | Permissions: rw------- +File: "fileA.hpp" | Permissions: rw------- +File: "fileB.cpp" | Permissions: rw------- +File: "fileB.hpp" | Permissions: rw------- +File: "fileC.cpp" | Permissions: rw------- +File: "fileC.hpp" | Permissions: rw------- +File: "project.exe" | Permissions: rw------- + +File: "fileA.cpp" | Permissions: rw-r--r-- +File: "fileA.hpp" | Permissions: rw-r--r-- +File: "fileB.cpp" | Permissions: rw-r--r-- +File: "fileB.hpp" | Permissions: rw-r--r-- +File: "fileC.cpp" | Permissions: rw-r--r-- +File: "fileC.hpp" | Permissions: rw-r--r-- +File: "project.exe" | Permissions: rwxrw-rw- +``` + + +___ + + +## Exercise 2 + +Open project `files`. Modify `FileB` by append any word. Now write a program which: + +- return last modify files +- return a vector with 3 files that were longest unmodified. + +Expected result (path may by different): + + +```Bash +Last modified file is: "/home/runner/SilentSiennaModularity/files/project/fileB.cpp" +File write time is Sat May 14 17:56:18 2022 +files that were longest unmodified: +File: "/home/runner/SilentSiennaModularity/files/project/fileA.cpp" | last modify time: Sat May 14 16:43:33 2022 +File: "/home/runner/SilentSiennaModularity/files/project/fileA.hpp" | last modify time: Sat May 14 16:43:33 2022 +File: "/home/runner/SilentSiennaModularity/files/project/fileB.hpp" | last modify time: Sat May 14 16:43:33 2022 +``` + + +___ + + +## Problems and fixes + +- Remember that recursive_directory_iterator and directory_iterator are InputIterator. If you move iterator to the next position you invalidate all reference to previous object. If you need to use algorithm which demand ForwardIterator you can copy all paths to separate container +- If you want to keep sorted files inside set or map you should check whether their modification times are the same. If true you need to compare their names or files with the same modification time will be lost. +- Setup premissions for files works only on Linux/ MacOS system. This is caused by different type of File system. Windows file system mainly NTFS do not support priviliges like in other systems eg. EXT4. There are still properites but handled in different way: + - Full Control: Grants complete access, including the ability to see, read, write, execute and delete files or folders, as well as change permission settings for all subdirectories. + - Modify: The user can see, read, execute, write and delete files. Also allows for the deletion of the folder itself. + - Read & Execute: Can view folder contents and run programs or scripts. + - List folder contents: Allows the user to see files and directories contained within a folder, an important setting for navigating to deeper levels in the folder structure. + - Read: Can see folder contents and also view the files and folders in question. + - Write: Users can add new files and folders and write to existing files. + - Special permissions: Additional permissions available through the Advanced Security Settings in the Windows file system. Includes options such as Read Attributes, Create Files or Traverse Folder. + +___ + + +## Temporary files for testing + +Sometimes during a test we need to read input data from file. usually we need to create this file and attach to test directory. But since C++17 we can easily use temporary directory to create all files. let's test this class: (The main resposibility is to queued all files and stream them) + +```C++ +class Streamer { +public: + Streamer() = default; + virtual ~Streamer() = default; + Streamer(const Streamer&) = default; + Streamer(Streamer&&) = default; + Streamer& operator=(const Streamer&) = default; + Streamer& operator=(Streamer&&) = default; + + virtual void stream() = 0; + virtual void stop() = 0; +}; +``` +___ + +
+
+ +```C++ +class MpgegStreamer : public Streamer { +public: + MpgegStreamer(const fs::path& path) + : path_(path) { + for (int i = 0; i < 4; ++i) { + workers_.emplace_back(&MpgegStreamer::work, this, i); + } + } + + ~MpgegStreamer() override { + for (auto& th : workers_) { + th.join(); + } + } + + void stream() override { + for (const auto& entry : fs::directory_iterator(path_)) { + std::lock_guard lg(m_); + streamQueue_.push(entry.path()); + } + } + + virtual void stop() { + finishAction_ = true; + } +``` +
+
+ +```C++ +private: + void work(int id) { + while (!finishAction_) { + fs::path path; + { + std::lock_guard lg(m_); + // Ofc this will be better with condition variable + if (streamQueue_.empty()) { + continue; + } + path = std::move(streamQueue_.front()); + streamQueue_.pop(); + } + stream(path, id); + } + } + + void stream(const fs::path path, int id) const { + std::fstream fileToStream(path); + std::transform( + std::istream_iterator(fileToStream), + {}, + std::ostream_iterator(std::cout), + [id](const std::string& str) { + std::stringstream ss; + ss << "Streamer: " << id << " | data: " << str << '\n'; + return ss.str(); + }); + } + + mutable std::mutex m_; + std::vector workers_; + std::queue streamQueue_; + fs::path path_; + std::atomic finishAction_{false}; +}; +``` +
+
+ +___ + + +We can create temporary direcotories (yes we can create them recursive!) and cleanup at the end. We don't need to be afraid of removing sth neccessary because we will work only with tmoprary directories. + +```C++ +int main() { + const auto tmp_path = fs::temp_directory_path(); + const auto mpegDir = tmp_path.string() + "Test/MpgegFiles"; + const auto mp4Dir = tmp_path.string() + "Test/MP4Files"; + + // Create test directory + fs::create_directories(mpegDir); + fs::create_directory(mp4Dir); + + // Add files + for (int i = 0; i < 10; ++i) { + std::ofstream file(mpegDir + "/File" + std::to_string(i)); + file << "this is some text in the new file\n" << i; + } + for (int i = 0; i < 10; ++i) { + std::ofstream file(mp4Dir + "/File" + std::to_string(i)); + file << "this is some text in the new file\n" << i; + } + + std::cout << "Start streaming" << std::endl; + std::unique_ptr streamer = std::make_unique(mpegDir); + streamer->stream(); + std::this_thread::sleep_for(std::chrono::seconds(1)); + streamer->stop(); + + fs::remove_all(tmp_path.string() + "Test"); +} +``` + \ No newline at end of file diff --git a/AdvancedCppV2/Presentation/moder_cpp_cpp17_folding.md b/AdvancedCppV2/Presentation/moder_cpp_cpp17_folding.md new file mode 100644 index 0000000..bf4d36d --- /dev/null +++ b/AdvancedCppV2/Presentation/moder_cpp_cpp17_folding.md @@ -0,0 +1,280 @@ +## Fold expressions + +* Folding is a new way of handling argument package +* It can be one or two arguments +* If it is two arguments we distinguish between + * left folding + * right folding +___ + +### Fold expressions - adding values + +```C++ +template +int add(Args... args) { + return (args + ...); +} + +int main() { + std::cout << add(1, 2, 3, 4, 5, 6, 7, 8, 9, 10) << '\n'; + std::cout << add() << '\n'; // Not compile! +} +``` + + +```C++ +55 +``` + +___ + +### Fold expressions - adding values + +```C++ +template +int add(Args... args) { + return (args + ... + 0); +} + +int main() { + std::cout << add(1, 2, 3, 4, 5, 6, 7, 8, 9, 10) << '\n'; + std::cout << add() << '\n'; // OK +} +``` + + +```C++ +55 +0 +``` + +___ + +### Fold expressions - subtracting values + +```C++ +template +int subR(Args... args) { + return (args - ...); +} + +template +int subL(Args... args) { + return (... - args); +} + +int main() { + // (1 - 2) + std::cout << subR(1, 2) << '\n'; // -1 + // (1 - 2) + std::cout << subL(1, 2) << '\n'; // -1 + // (1 - (2 - 3)) + std::cout << subR(1, 2, 3) << '\n'; // 2 + // ((1 - 2) - 3) + std::cout << subL(1, 2, 3) << '\n'; // -4 + // (1 - (2 - (3 - 4))) + std::cout << subR(1, 2, 3, 4) << '\n'; // -2 + // (((1 - 2) - 3) - 4) + std::cout << subL(1, 2, 3, 4) << '\n'; // -8 + // (1 - (2 - (3 - (4 - 5)))) + std::cout << subR(1, 2, 3, 4, 5) << '\n'; // 3 + // ((((1 - 2) - 3) - 4) - 5) + std::cout << subL(1, 2, 3, 4, 5) << '\n'; // -13 +} +``` + + +___ + +### Fold expressions - make code work without parameters + +Find a problem with the below code. + + +```C++ +template +int subR(Args... args) { + return (args - ... - 0); +} + +template +int subL(Args... args) { + // What's wrong here??? + return (0 - ... - args); +} + +int main() { + // (1 - (2 - (3 - (4 - 5)))) + std::cout << subR(1, 2, 3, 4, 5) << '\n'; + // ((((1 - 2) - 3) - 4) - 5) + std::cout << subL(1, 2, 3, 4, 5) << '\n'; + + std::cout << subR() << '\n'; + std::cout << subL() << '\n'; +} +``` + + +```C++ +3 // (1 - (2 - (3 - (4 - (5 - 0)))) +-15 // (((((0 - 1) - 2) - 3) - 4) - 5) +0 +0 +``` + + + +___ + +## How to demand minimum one variable + +```C++ +template +auto average(Value const& value, Values const&... values) +{ + return (value + ... + values) / (1. + sizeof...(values)); +} + +int main() { + std::cout << average(1, 2, 3, 4) << '\n'; // print 2.5 + std::cout << average() << '\n' // NOT COMPILE! +} +``` +___ + +## Calling member functions + +```C++ +template +void loggStateForAll(const Args&... args) +{ + (..., args.loggState()); +} + +struct A { + void loggState() const { + std::cout << "StateA: good!\n"; + } +}; + +struct B { + void loggState() const { + std::cout << "StateB: bad!\n"; + } +}; + +int main() { + loggStateForAll(A{}, B{}, A{}, B{}); + /* Will print + StateA: good! + StateB: bad! + StateA: good! + StateB: bad! */ +} +``` + +___ + +## Fold expressions - insert to container (1) + +```C++ +class Foo { +public: + Foo(int num) + : num_(num) {} + + int num() const { return num_; } + +private: + int num_; +}; + +template +void emplaceAll(std::vector& vec, Args... args) { + (vec.emplace_back(args), ...); +} + +int main() { + std::vector vec; + emplaceAll(vec, 1, 2, 3, 4, 5, 6, 7); + + std::transform(cbegin(vec), cend(vec), std::ostream_iterator(std::cout, " "), + [](const auto& foo) { return foo.num(); }); +} +``` + + +```C++ +1 2 3 4 5 6 7 +``` + + +* What with (..., vec.emplace_back(args))? + + + +___ + +### Fold expressions - insert to container (2) + +* There is no right/left type of folding for one type of argument + * Unary right fold (fun(arg0) , (fun(arg1) , (fun(arg2) , ...))) + * Unary left fold (((fun(arg0) , fun(arg1)) , fun(arg2)) , ... +* Only for binary folding, we can have different behavior +___ + +### Fold expressions - logic operators + +```C++ +template +bool emplaceAll(std::set& set, Args... args) { + return (set.insert(args).second && ...); +} + +int main() { + std::set set; + emplaceAll(set, 1, 2, 3, 4, 5, 1, 6, 7); + + std::copy(cbegin(set), cend(set), std::ostream_iterator(std::cout, " ")); +} +``` + + +```C++ +1 2 3 4 5 +``` + +For bot way: +return (set.insert(args).second && ...); + + +and +return (... && set.insert(args).second); +output will be the same + + + +___ + +### Fold expressions - cooperation with STL algorithms + +```C++ +template +bool HasAll(const std::vector& vec, Args... args) { + return ((std::find(cbegin(vec), cend(vec), args) != std::cend(vec)) && ...); +} + +int main() { + std::vector vec{1, 2, 3, 4, 1, 2, 3, 5, 6, 7, 4}; + std::cout << std::boolalpha << HasAll(vec, 2, 4, 6) << '\n'; + std::cout << std::boolalpha << HasAll(vec, 2, 4, 6, 8) << '\n'; +} +``` + + +```C++ +true +false +``` + + diff --git a/AdvancedCppV2/Presentation/moder_cpp_cpp17_intro.md b/AdvancedCppV2/Presentation/moder_cpp_cpp17_intro.md new file mode 100644 index 0000000..f9d71b0 --- /dev/null +++ b/AdvancedCppV2/Presentation/moder_cpp_cpp17_intro.md @@ -0,0 +1,11 @@ +## Cpp17 + +* A quick reminder of lesser known features + * Nested namespace definitions + * Class template argument deduction + * Selection statements with initializer + * Unified initialization + * Structural biding + * Fold expressions + * Constexpr + * Filesystem diff --git a/AdvancedCppV2/Presentation/moder_cpp_cpp17_small_features.md b/AdvancedCppV2/Presentation/moder_cpp_cpp17_small_features.md new file mode 100644 index 0000000..863a07a --- /dev/null +++ b/AdvancedCppV2/Presentation/moder_cpp_cpp17_small_features.md @@ -0,0 +1,244 @@ +## Nested namespace definitions + + +You can nest namespaces like this: + + +```c++ +namespace A::B::C { + ... +} +``` + +Instead of this: + + +```c++ +namespace A { + namespace B { + namespace C { + ... + } + } +} +``` + +___ + + +## Class template argument deduction + +From C++17 class template arguments can be deduced automatically. Automatic template argument deduction was available earlier only for template functions. + +```c++ +std::pair p(1, 'x'); // C++17: OK, C++14: error: missing. + // std::pair +std::pair p(1, "x"); // C++14: OK + // std::pair +auto p2 = std::make_pair(1, "x"); // C++17: OK, C++14: OK (but not string!) + // std::pair +std::pair p3(1, "x"); // C++17: OK (but not string!), C++14 error +``` + +___ + + +## Selection statements with initializer (1) + +New versions of the `if` and `switch` statements for C++: + + +### `if (init; condition)` + + +```cpp +status_code foo() { // C++14 + { //variable c scope + status_code c = bar(); + if (c != SUCCESS) { + return c; + } + } + // ... +} +``` + + +```cpp +status_code foo() { // C++17 + if (status_code c = bar(); c != SUCCESS) { + return c; + } + // ... +} +``` + + +___ + + +## Selection statements with initializer (2) + +### `switch (init; condition)` + + +```C++ +class Foo { +public: + enum class ErrorCode { + Ok, + Bad, + VeryBad + }; + + ErrorCode doSth() {} +} + +int main() { + switch (Foo foo ; const auto err = foo.doSth()) { + case ErrorCode::Ok: + break; + case ErrorCode::Bad: + break; + case ErrorCode::VeryBad: + break; + } +} +``` + + +___ + + +## Selection statements with initializer (3) + +```C++ +class ThreadSafeQueue { +public: + std::optional try_pop() { + int val = 0; + // Lock guard is visible inside if-else + if (std::lock_guard lock(m_) ; queue_.empty()) { + return {}; + } else { + val = queue_.front(); + queue_.pop(); + } + + // Here mutex is no longer locked + logger << "pop value from queue"; + return val; + } + +private: + std::queue queue_; + std::mutex m_; +}; +``` + + + +___ + + +## Hiding variable inside if-else statement (2) + +We can avoid assigning iterators and then comapre it in `if` statement. Now we can write it faster + +```C++ +int main() { + std::vector vec; + + if (const auto it = std::find(std::cbegin(vec), std::cend(vec), 10) ; it != std::cend(vec)) { + // *it* is visible here + } else { + // and here + } + // but not here + + std::map + if (const auto it = map.find("Ala") ; it != std::cend(map)) { + // ... + } else { + // ... + } +} +``` + +___ + + +## Unified initialization + +* C++11 introduce {} for initialization +* C++17 fixed some problems with {} and unified it. + +___ + + +## Unified initialization C++11 + +* Guess output (compiler 4.7.4 with C++11 flag) + +

+auto a {1};             //std::initializer_list<int>
+auto b = {1};           //std::initializer_list<int>
+auto c {1, 2};          //std::initializer_list<int>
+auto d = {1, 2};        //std::initializer_list<int>
+auto e = {1, 2, 3.f};   //Not compile               
+auto f {1, 2, 3.f}      //Not compile               
+
+ +___ + + +## Unified initialization C++17 + +* Guess output (compiler 8.4 with C++17 flag) + +

+auto a {1};             //int                       
+auto b = {1};           //std::initializer_list<int>
+auto c {1, 2};          //Not compile (mising =)              
+auto d = {1, 2};        //std::initializer_list<int>
+auto e = {1, 2, 3.f};   //Not compile               
+auto f {1, 2, 3.f}      //Not compile               
+
+ +___ + + +## Structural biding + +* Unpack strucures, classes, tuples, pairs etc... + +```C++ +struct Foo{}; + +std::tuple getTuple() { + return {5, "Ala has a cat", Foo{}}; +} + +struct Bar { + std::string str_; + double val_; + char c_; + std::vector vec_; +}; + +int main() { + const auto& [id, topic, foo] = getTuple(); + + std::vector bar; + for (const auto& [name, value, sign, vec] : bar) { + // ... + } + + std::map map; + for (const auto& [key, value] : map) { + // .. + } +}; +``` + + diff --git a/AdvancedCppV2/Presentation/moder_cpp_cpp20_intro.md b/AdvancedCppV2/Presentation/moder_cpp_cpp20_intro.md new file mode 100644 index 0000000..53f3411 --- /dev/null +++ b/AdvancedCppV2/Presentation/moder_cpp_cpp20_intro.md @@ -0,0 +1,15 @@ +## Cpp20 + + +- ranges +- modules +- operator<=>, +- designated initializers, +- atributes +- pack-expansion in lmabdas (how to avoid copy) +- template syntax for lambdas +- uniform erasure +- How to log useful informations in fast way using C++20 (source_loaction), subtitution for old macros. +- bit operations +- format your string like in printf + diff --git a/AdvancedCppV2/Presentation/moder_cpp_cpp20_modules.md b/AdvancedCppV2/Presentation/moder_cpp_cpp20_modules.md new file mode 100644 index 0000000..9df6a47 --- /dev/null +++ b/AdvancedCppV2/Presentation/moder_cpp_cpp20_modules.md @@ -0,0 +1,142 @@ +## Modules + + +Legacy `includes` system form `C` language finally was replaced in C++20 by modules. `include` is actually 50 years old! + +New keywords: + +* Export +* Import +___ + + +## Less code in binary + +
+
+ +```C++ +#include + +int main() { + std::cout << "Hello World!\n"; +} +``` + +```C++ +g++ -std=c++2b -E main.cpp | wc -c +929065 +``` +
+ +
+ +```C++ +import ; + +int main() { + std::cout << "Hello Modular World!\n"; +} +``` + +```C++ +g++ -std=c++2b -fmodules-ts main.cpp | wc -c +239 +``` +
+ + +___ + + +## Export + +Modules provide better encapsulation because you can export only those methods, which you mark as exported. The rest of the functions stay hidden outside the file. + +```C++ +// calculator.cc +export module Calculator; + +export auto add(auto x, auto y) { + return x + y; +} + +export auto substract(auto x, auto y) { + return x - y; +} + +export namespace Advanced { + auto factorial(auto x) { + decltype(x) res = 1; + for (int i = 2 ; i <= x ; ++i) { + res *= i + } + + return res; + } +} + +void this_function_will_not_be_exported() {} + +// main.cc +import ; +import Calculator; + +int main() { + std::cout << "10 + 20 = " << add(10, 20) << '\n'; + std::cout << "40 - 60 = " << substract(40, 60) << '\n'; + std::cout << "5! = " << Advanced::factorial(5) << '\n'; + // this_function_will_not_be_exported -> compile error +} +``` + + + +___ + + +## spread modules across multiple files + +Only one file can be `interface` and `export` module. Other files can write implementations. + +```C++ +// interface.cc +export module calculator + +export { + auto add(auto x, auto y); + auto substract(auto x, auto y); +} + +// add.cc +module calculator + +auto add(auto x, auto y) { + return x + y; +} + +// substract.cc +module calculator + +auto substract(auto x, auto y) { + return x - y; +} + +// main.cc +import ; +import calculator; + +int main() { + std::cout << "10 + 20 = " << add(10, 20) << '\n'; + std::cout << "40 - 60 = " << substract(40, 60) << '\n'; +} +``` + + +___ + + +## Compiler and Cmake supoort + +Unfortunately when we want to build binary with modules using g++ or clang even when we have the newest version (on 17.05.2022 there is g++ 13 and clang 15) we still have partial support for modules. It will takes a few years before we will start using this in customer projects. Currently, even CMake(3.23.1) Didn't fully support modules: (https://gitlab.kitware.com/cmake/cmake/-/issues/18355). + \ No newline at end of file diff --git a/AdvancedCppV2/Presentation/moder_cpp_cpp20_ranges.md b/AdvancedCppV2/Presentation/moder_cpp_cpp20_ranges.md new file mode 100644 index 0000000..232f7ee --- /dev/null +++ b/AdvancedCppV2/Presentation/moder_cpp_cpp20_ranges.md @@ -0,0 +1,396 @@ +## Ranges + + +Let's start with simple example: + +```C++ +int main() { + auto const ints = {0, 1, 2, 3, 4, 5}; + auto even = [](int i) { return 0 == i % 2; }; + auto square = [](int i) { return i * i; }; + + for (int i : ints | std::views::filter(even) | std::views::transform(square)) { + std::cout << i << ' '; + } +} +``` + + +```C++ +0 4 16 +``` + + +___ + + +## New iterators + +* std::ranges::input_range: specifies a range whose iterator type satisfies input_iterator (can iterate from begin to end at least once) +* std::ranges::output_range: specifies a range whose iterator type satisfies output_iterator +* std::ranges::forward_range: specifies a range whose iterator type satisfies forward_iterator (can iterate from begin to end more than once) +* std::ranges::bidirectional_range: specifies a range whose iterator type satisfies bidirectional_iterator (can iterate forward and backward more than once) +* std::ranges::random_access_range: specifies a range whose iterator type satisfies random_access_iterator (can jump in constant time to an arbitrary element with the index operator []) +* std::ranges::contiguous_range: specifies a range whose iterator type satisfies contiguous_iterator (elements are stored consecutively in memory) + + +___ + + +## Improvements for iterators + +Whenever we iterate through value, we need to check if we reach the end. But We can provide an optimization, which avoids comparing `it != end`. We can do this by passing `std::unreachable_sentinel`. This sentinel always returns `false` when compared, that's why the compiler can optimize the process. **but be careful** if you provide wrong input, like searching numbers which don't exist in acontainer you got `Segmentation fault`. + +```C++ +int main() { + std::vector vec = { 1, 2, 3, 4, 5, 6, 7, 8, 9}; + std::ranges::shuffle(vec, std::mt19937(std::random_device()())); + std::cout << *std::ranges::find(vec.begin(), std::unreachable_sentinel, 5) << '\n'; + // change this for 10 and you got Segmentation fault +} +``` + + +see unreachable.sentinel + +___ + + +## More improvements - predicates + +Whenever you wanted to sort structure based on the class member you need to provide a special comparator: + +```C++ +struct Student { + int index_; + std::string name_; + double average_; +}; + +int main() { + std::vector students{{.index_ = 123456, .name_ = "Jordan", .average_ = 4.53}, + {.index_ = 654321, .name_ = "Michael", .average_ = 4.51}, + {.index_ = 246892, .name_ = "John", .average_ = 4.56}, + {.index_ = 743561, .name_ = "Jane", .average_ = 4.44}, + {.index_ = 811111, .name_ = "Anna", .average_ = 4.46}}; + + std::sort(begin(students), end(students), [](const auto& lhs, const auto& rhs){ + return lhs.average_ < rhs.average_; + }); + + for (const auto& [index, name, average] : students) { + std::cout << "student: " << name << " | index: " << index << " | avergae: " << average << '\n'; + } + /* student: Jane | index: 743561 | avergae: 4.44 + student: Anna | index: 811111 | avergae: 4.46 + student: Michael | index: 654321 | avergae: 4.51 + student: Jordan | index: 123456 | avergae: 4.53 + student: John | index: 246892 | avergae: 4.56 */ +} +``` + +___ + + +Now you can write it much faster!: + +```C++ +struct Student { + int index_; + std::string name_; + double average_; +}; + +int main() { + std::vector students{{.index_ = 123456, .name_ = "Jordan", .average_ = 4.53}, + {.index_ = 654321, .name_ = "Michael", .average_ = 4.51}, + {.index_ = 246892, .name_ = "John", .average_ = 4.56}, + {.index_ = 743561, .name_ = "Jane", .average_ = 4.44}, + {.index_ = 811111, .name_ = "Anna", .average_ = 4.46}}; + + // container, comparator, projection + std::ranges::sort(students, {}, &Student::average_); + + for (const auto& [index, name, average] : students) { + std::cout << "student: " << name << " | index: " << index << " | avergae: " << average << '\n'; + } +} +``` + + +All magic is done by the new parameter `projection`. It points to address to member and use it to provide a comparison: `std::invoke(comp, std::invoke(proj, *(it + n)), std::invoke(proj, *it))` + +___ + + +## View + +Here is a quote from Eric Nieblers range-v3 implementation which is the base for the C++20 ranges: "Views are composable adaptations of ranges where the adaptation happens lazily as the view is iterated." In other words: `view` is not an owner of range. So we don't need to copy/move elements, only perform some action. Only exception is a `std::views::single` which owns the single element it is viewing. + + +Let's use `Foo` which prints whenever we create/ copy/ move or delete him. + + +
+
+ +```C++ +int main() { + auto even = [](const auto& el) { return !(el.id() % 2); }; + std::vector vec {Foo{1}, Foo{2}, Foo{3}, Foo{4}}; + + std::cout << "Start algorithm\n"; + for (const auto& foo : vec + | std::views::filter(even) + | std::views::drop_while([](const auto& el){ return el.id() < 4; })) { + std::cout << "foo: " << foo << '\n'; + } +} +``` +We don't make any copy! +
+ +
+ +```C++ +C'tor id: 1 +C'tor id: 2 +C'tor id: 3 +C'tor id: 4 +Copy C'tor id: 1 +Copy C'tor id: 2 +Copy C'tor id: 3 +Copy C'tor id: 4 +D'tor id:4 +D'tor id:3 +D'tor id:2 +D'tor id:1 +Start algorithm +foo: 4 +D'tor id:1 +D'tor id:2 +D'tor id:3 +D'tor id:4 +``` +
+ + +___ + + +## View (2) + +This is also usefull to create `range loop` which iterate reversed: + +```C++ +int main() { + std::vector students{{.index_ = 123456, .name_ = "Jordan", .average_ = 4.53}, + {.index_ = 654321, .name_ = "Michael", .average_ = 4.51}, + {.index_ = 246892, .name_ = "John", .average_ = 4.56}, + {.index_ = 743561, .name_ = "Jane", .average_ = 4.44}, + {.index_ = 811111, .name_ = "Anna", .average_ = 4.46}}; + + std::ranges::sort(students, {}, &Student::average_); + + for (const auto& [index, name, average] : std::views::reverse(students)) { + std::cout << "student: " << name << " | index: " << index << " | avergae: " << average << '\n'; + } + /* + student: John | index: 246892 | avergae: 4.56 + student: Jordan | index: 123456 | avergae: 4.53 + student: Michael | index: 654321 | avergae: 4.51 + student: Anna | index: 811111 | avergae: 4.46 + student: Jane | index: 743561 | avergae: 4.44 + */ +} +``` + +___ + + +## View (3) + +We can also create `range loop` which iterates only through the first/last `k` elements: + +```C++ +int main() { + std::vector students{{.index_ = 123456, .name_ = "Jordan", .average_ = 4.53}, + {.index_ = 654321, .name_ = "Michael", .average_ = 4.51}, + {.index_ = 246892, .name_ = "John", .average_ = 4.56}, + {.index_ = 743561, .name_ = "Jane", .average_ = 4.44}, + {.index_ = 811111, .name_ = "Anna", .average_ = 4.46}}; + + std::ranges::sort(students, {}, &Student::average_); + + for (const auto& [index, name, average] : std::views::reverse(students) | std::views::drop(3)) { + std::cout << "student: " << name << " | index: " << index << " | avergae: " << average << '\n'; + } + /* student: Anna | index: 811111 | avergae: 4.46 + student: Jane | index: 743561 | avergae: 4.44 */ + + for (const auto& [index, name, average] : std::views::reverse(students) | std::views::take(3)) { + std::cout << "student: " << name << " | index: " << index << " | avergae: " << average << '\n'; + } + /* student: John | index: 246892 | avergae: 4.56 + student: Jordan | index: 123456 | avergae: 4.53 + student: Michael | index: 654321 | avergae: 4.51 */ +} +``` + + +___ + + +## std::map + +```C++ +int main() { + std::map map{{1, "One"}, {2, "Two"}, {3, "Three"}, {4, "Four"}}; + auto odd = [](const auto& el) { return el % 2; }; + + for (auto el : std::views::keys(map) | std::views::filter(odd)) { + std::cout << el << ' '; + } + std::cout << '\n'; + + for (const char c : map | std::views::values | std::views::join) { + std::cout << c << ' '; + } +} +``` + + +```C++ +1 3 +O n e T w o T h r e e F o u r +``` + + +___ + + +## C++23 and further + +Ranges library based on `Ranges V3`. Unfortunately, in C++20 there is a lack of useful things like creating cycles or zip functions. In C++23 there will be a few more operations like `zip` or `join_with`: + +```C++ +int main() { + auto x = std::vector{1, 2, 3, 4}; + auto y = std::list{"α", "β", "γ", "δ", "ε"}; + auto z = std::array{'A', 'B', 'C', 'D', 'E', 'F'}; + + /* 1 α A + 2 β B + 3 γ C + 4 δ D */ + for (const auto& [num, grec, alpha] : std::views::zip(x, y, z)) { + std::cout << num << ' ' << grec << ' ' << alpha << '\n'; + } + + std::map map{{1, "One"}, {2, "Two"}, {3, "Three"}, {4, "Four"}}; + auto ends_with_e = [](const auto& el) { return el.back() == 'e'; }; + const auto joined = std::views::values(map) | std::views::filter(ends_with_e) | std::views::join_with(' '); + /* Two Four */ + for (const auto& el : joined) { + std::cout << el; + } +} +``` + +___ + + +## actions (C++23) + +There is a proposal to extend ranges in C++23 to allow easy convert range to container (http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2021/p1206r6.pdf) + +```C++ +int main() { + std::map map{ + {1, "Hello"}, {2, "Abcd"}, {3, "Hello"}, {4, "Aaa"}, {5, "Ala"}, {6, "Abcd"}}; + + // Since C++23 + for (const auto& el : map + | std::views::values + | std::ranges::to // Since C++23 + | std::ranges::sort + | std::ranges::unique) { + std::cout << el << '\n'; + } +} +``` + +```C++ +Aaa +Abcd +Ala +Hello +``` + + +___ + + +## actions (C++26) + +In C+26 we should get also `operator|=`. + +
+Before C++26 + +```C++ +int main() { + std::vector vec{"Hello", "Abcd", "Hello", "Aaa", "Ala", "Abcd"}; + + std::ranges::sort(vec); + auto ret = std::ranges::unique(vec); + vec.erase(ret.begin(), ret.end()); +} +``` +
+ +
+In C++26 + +```C++ +int main() { + std::vector vec{"Hello","Abcd", "Hello", "Aaa", "Ala", "Abcd"}; + vec |= std::ranges::sort | std::ranges::unique; +} +``` +
+ + +___ + + +## Exercise 1 + +Open project `searcher` and implement function `searchFiles` which returns all files containing `keyWord`. + +Possible output: + +```C++ +"C:\\Users\\mateusz\\Documents\\Nokia2022\\Basic\\Course_part1\\exercises\\searcher/files\\fileA.hpp" +"C:\\Users\\mateusz\\Documents\\Nokia2022\\Basic\\Course_part1\\exercises\\searcher/files\\fileC.hpp" +``` + +___ + + +## Exercise 2 + +Open project `students`: + +* implement function `filterStudents`, +* Student should be disqualified whether his average is below `minAvergae`, +* Write an algorithm that prints students using ranges (do not implement friend operator<<) + +Output: + +```C++ +Name: Jane | index: 743561 | average: 4.44 +Name: Tom | index: 811111 | average: 4.36 +Name: Mike | index: 811111 | average: 4.45 +``` + diff --git a/AdvancedCppV2/Presentation/moder_cpp_cpp20_small_features.md b/AdvancedCppV2/Presentation/moder_cpp_cpp20_small_features.md new file mode 100644 index 0000000..7c9a547 --- /dev/null +++ b/AdvancedCppV2/Presentation/moder_cpp_cpp20_small_features.md @@ -0,0 +1,1082 @@ +## Small features + +___ + + +## operator<=> + +Since C++20 we don't need to define all comparison operators for custom structures. Instead of `==`, `!=`, `>`, `<`, `<=`, `>=` we can simply write one universal comparator `<=>`. + +```C++ +struct Student { + auto operator<=>(const Student& other) const = default; + + std::string name_; + double average_; + int index_; +}; + +int main() { + Student student1{.name_ = "Mateusz", .average_ = 4.67, .index_ = 456123}; + Student student2{.name_ = "Michał", .average_ = 4.57, .index_ = 123456}; + Student student3{.name_ = "Marcelina", .average_ = 4.67, .index_ = 321456}; + Student student4{.name_ = "Mirosław", .average_ = 4.47, .index_ = 135246}; + + std::cout << "student1 < student2 ? " << (student1 < student2) << '\n'; // True + std::cout << "student1 < student3 ? " << (student1 < student3) << '\n'; // False + std::cout << "student1 < student4 ? " << (student1 < student4) << '\n'; // True + std::cout << "student2 < student3 ? " << (student2 < student3) << '\n'; // False + std::cout << "student2 < student4 ? " << (student2 < student4) << '\n'; // True + std::cout << "student3 < student4 ? " << (student3 < student4) << '\n'; // True + std::cout << "student1 == student1 ? " << (student1 == student1) << '\n'; // True +} +``` + + +___ + + +## How it works? + +First, we need to understand how the compiler treats the structure `Student`. This structure has 3 fields: `name`, `average`, and `index`. During the comparison, the first field is to compare if both values are the same, if true we reach a second one, and so on. In other words, first different fields decide which structure is lower. + +```C++ +int main() { + Student student1{.name_ = "Mateusz", .average_ = 4.67, .index_ = 456123}; + Student student2{.name_ = "Mateusz", .average_ = 4.67, .index_ = 123456}; + Student student3{.name_ = "Mateusz", .average_ = 4.57, .index_ = 321456}; + Student student4{.name_ = "Mateusz", .average_ = 4.57, .index_ = 135246}; + + std::cout << "student1 > student2 ? " << (student1 > student2) << '\n'; // T (higher index) + std::cout << "student1 > student3 ? " << (student1 > student3) << '\n'; // T (higher average) + std::cout << "student1 > student4 ? " << (student1 > student4) << '\n'; // T (higher average) + std::cout << "student2 > student3 ? " << (student2 > student3) << '\n'; // T (higher average) + std::cout << "student2 > student4 ? " << (student2 > student4) << '\n'; // T (higher average) + std::cout << "student3 > student4 ? " << (student3 > student4) << '\n'; // T (higher index) + std::cout << "student1 == student1 ? " << (student1 == student1) << '\n'; // T (the same person) +} +``` + + + +___ + + +## But I don't want to compare some fields... + +When you don't want to compare one or more fields, you need to write your own comparator. + +```C++ +struct Student { + std::partial_ordering operator<=>(const Student& other) const { + if (const auto res = average_ <=> other.average_; res != 0) { + return res; + } + return name_ <=> other.name_; + } +}; + +int main() { + Student student1{.name_ = "Mateusz", .average_ = 4.67, .index_ = 456123}; + Student student2{.name_ = "Mateusz", .average_ = 4.67, .index_ = 123456}; + Student student3{.name_ = "Mateusz", .average_ = 4.57, .index_ = 321456}; + + std::cout << "student1 > student2 ? " << (student1 > student2) << '\n'; // T (higher index) + std::cout << "student1 < student3 ? " << (student1 < student3) << '\n'; // F (lower average) + // This line do not compile :( + std::cout << "student1 == student1 ? " << (student1 == student1) << '\n'; // T (the same person) +} +``` + + +But why do we wrote`std::partial_ordering` instead of `auto`? It's because we compare two floating point values. I know that earlier we wrote `auto operator<=>` and it's worked, but this was fully generated by the compiler. If we are writing it manually and we need to specify what result we return. + + +___ + + +## Types of ordering + +* strong_ordering: a total ordering, where equality implies substitutability (that is (a <=> b) == strong_ordering::equal implies that for reasonable functions f, f(a) == f(b). “Reasonable” is deliberately underspecified – but shouldn’t include functions that return the address of their arguments or do things like return the capacity() of a vector, etc. We want to only look at “salient” properties – itself very underspecified, but think of it as referring to the value of a type. The value of a vector is the elements it contains, not its address, etc.). The values are strong_ordering::greater, strong_ordering::equal, and strong_ordering::less. +* weak_ordering: a total ordering, where equality actually only defines an equivalence class. The canonical example here is case-insensitive string comparison – where two objects might be weak_ordering::equivalent but not actually equal (hence the naming change to equivalent). +* partial_ordering: a partial ordering. Here, in addition to the values greater, equivalent, and less (as with weak_ordering), we also get a new value: unordered. This gives us a way to represent partial orders in the type system: 1.f <=> NaN is partial_ordering::unordered. + + +___ + + +## Ok but what with operator== + +beacuse we have custom `operator<=>`, which return `std::partial_ordering` we can't use `operator==`. We need to provide own `operator==`. And we can do this by default (compare all fileds) or manually (compare specific fileds). + +```C++ +struct Student { + std::partial_ordering operator<=>(const Student& other) const { + if (const auto res = average_ <=> other.average_; res != 0) { + return res; + } + return name_ <=> other.name_; + } + + bool operator==(const Student& other) const { + return name_ == other.name_ && average_ == other.average_; + } + + std::string name_; + double average_; + int index_; +}; + +int main() { + Student student1{.name_ = "Mateusz", .average_ = 4.67, .index_ = 456123}; + Student student2{.name_ = "Mateusz", .average_ = 4.67, .index_ = 123456}; + + std::cout << "student1 > student2 ? " << (student1 > student2) << '\n'; // T (higher index) + std::cout << "student1 == student1 ? " << (student1 == student1) << '\n'; // T (the same person) +} +``` + + +___ + + +We can also decide to use default `operator==` and this also work! + +```C++ +struct Student { + std::partial_ordering operator<=>(const Student& other) const { + if (const auto res = average_ <=> other.average_; res != 0) { + return res; + } + return name_ <=> other.name_; + } + + bool operator==(const Student&) const = default; + + std::string name_; + double average_; + int index_; +}; + +int main() { + Student student1{.name_ = "Mateusz", .average_ = 4.67, .index_ = 456123}; + Student student2{.name_ = "Mateusz", .average_ = 4.67, .index_ = 123456}; + + std::cout << "student1 > student2 ? " << (student1 > student2) << '\n'; // T (higher index) + std::cout << "student1 == student1 ? " << (student1 == student1) << '\n'; // T (the same person) +} +``` + + +___ + + +## More about partial_ordering + +To sum up, if we compare 2 floating point values, the result is `std::partial_ordering`. We can't use `operator==` in such a case. This makes sense, but when do we also need this type of order? Let's check the below example: + +```C++ +struct Student { + std::partial_ordering operator<=>(const Student& other) const { + if (!name_ || !other.name_) { + return std::partial_ordering::unordered; + } + if (const auto res = name_ <=> other.name_; res != 0) { + return res; + } + return index_ <=> other.index_; + } + bool operator==(const Student&) const = default; + + std::optional name_; + double average_; + int index_; +}; + +int main() { + Student student1{.name_ = "Mateusz", .average_ = 4.67, .index_ = 456123}; + Student student2{.name_ = std::nullopt, .average_ = 4.67, .index_ = 123456}; + + std::cout << "student1 > student2 ? " << (student1 > student2) << '\n'; // F (second student doesn't has name!) + std::cout << "student1 < student2 ? " << (student1 < student2) << '\n'; // F (second student doesn't has name!) + std::cout << "student1 != student2 ? " << (student1 != student2) << '\n'; // T (here we use operator== not <=>) + std::cout << "student1 == student2 ? " << (student1 == student2) << '\n'; // F (here we use operator== not <=>) + std::cout << "student2 == student2 ? " << (student2 == student2) << '\n'; // T (here we use operator== not <=>) +} +``` + + +___ + + +## Ok but how <=> exactly works? + +Each type or ordering could represent one of those 3 values (partial could also has `unordered`): + +* std::strong_ordering::less / weak_ordering::less / std::partial_ordering::less +* std::strong_ordering::equal / weak_ordering::equivalent / std::partial_ordering::equivalent +* std::strong_ordering::greater / weak_ordering::greater / std::partial_ordering::greater + +We can simply compare them: + +```C++ +int val1(1234); +int val2(12345); +auto res = val1 <=> val2; +if (res < 0) + std::cout << "val1 < val2" << std::endl; +else if (res == 0) + std::cout << "val1 == val2" << std::endl; +else if (res > 0) + std::cout << "val1 > val2" << std::endl; +``` + +This is implicity generated by compiler. For instance `a > b` is converted to `(a <=> b) > 0` + + +___ + + +## Finally, something about weak ordering + +Weak ordering is returned when does not imply substitutability: if a is equivalent to b, f(a) may not be equivalent to f(b), where f denotes a function that reads only comparison-salient state that is accessible via the argument's public const members. In other words, equivalent values may be distinguishable. + +```C++ +struct Student { + int score() const { + return std::accumulate(cbegin(grades_), cend(grades_), 0, [](const auto& sum, const auto& pair) { return sum + pair.second; }); + } + + std::weak_ordering operator<=>(const Student& other) const { + if (const auto res = this->score() <=> other.score(); res != 0) { + return res; + } + return name_ <=> other.name_; + } + + bool operator==(const Student&) const = default; + + std::string name_; + std::multimap grades_; + int index_; +}; + +int main() { + Student student1{.name_ = "Mateusz", .grades_ = {{"Math", 5},{"Bio", 4}}, .index_ = 456123}; + Student student2{.name_ = "Mateusz", .grades_ = {{"Math", 5},{"Eng", 4}}, .index_ = 123456}; + Student student3{.name_ = "Mateusz", .grades_ = {{"Math", 4},{"Phys", 3}}, .index_ = 123456}; + + std::cout << "student1 > student2 ? " << (student1 > student2) << '\n'; // F + std::cout << "student1 < student2 ? " << (student1 < student2) << '\n'; // F + std::cout << "student1 != student2 ? " << (student1 != student2) << '\n'; // T (use operator == here) + std::cout << "student1 == student2 ? " << (student1 == student2) << '\n'; // F (use operator == here) + std::cout << "student1 > student3 ? " << (student1 > student3) << '\n'; // T (higher grades) + std::cout << "student1 < student3 ? " << (student1 < student3) << '\n'; // F +} +``` + +___ + + +## Implicit conversion + +`std::strong_ordering` can be implicitly converted to `std::weak_ordering` and `std::weak_ordering` can be implicitly converted to `std::partial_ordering`. + +___ + + +## designated initializers + +This is a small feature that you saw a few times in action during these lectures: + +```C++ +struct Student { + std::string name_; + std::multimap grades_; + int index_; +}; + +int main() { + Student student1{.name_ = "Mateusz", .grades_ = {{"Math", 5},{"Bio", 4}}, .index_ = 456123}; + Student student2{.name_ = "Mateusz", .grades_ = {{"Math", 5},{"Eng", 4}}, .index_ = 123456}; + Student student3{.name_ = "Mateusz", .grades_ = {{"Math", 4},{"Phys", 3}}, .index_ = 123456}; +``` + + + +___ + + +Every structure or class with public fields could now be initialized by using the name of a field. This makes code more readable and you don't need to switch a few times between headers and source code to check which field means what. + +```C++ +struct StreamInfo { + std::string sourceAddress_; + std::string destinationAddress_; + uint16_t sourcePort_; + uint16_t destinationPort_; + uint16_t vlan_; +}; + +struct Streamer { + Streamer(uint16_t sourcePort): sourcePort_(sourcePort) {} + + uint16_t getSourcePort() const { return sourcePort_; } +private: + uint16_t sourcePort_; +}; + +int main() { + std::map ipTables; + Streamer streamer(6523); + ipTables.emplace("192.168.0.15", "192.168.0.35"); + ipTables.emplace("192.168.0.16", "192.168.0.42"); + + StreamInfo info { + .sourceAddress_ = "192.168.0.15", + .destinationAddress_ = ipTables["192.168.0.15"], + .sourcePort_ = streamer.getSourcePort(), + .destinationPort_ = 9998, + .vlan_ = [](){ return 123; }() + }; +} +``` + +___ + + +## Atributes + +Since C++20 we got 4 more atributes + +* [[nodiscard("reason")]] - encourages the compiler to issue a warning if the return value is discarded +* [[likely]] and [[unlikely]] - indicates that the compiler should optimize for the case where a path of execution through a statement is more or less likely than any other path of execution +* [[no_unique_address]] - indicates that a non-static data member need not have an address distinct from all other non-static data members of its class + +___ + + +## likely and unlikely + +Everyone knows well this `if-else` statements: + +```C++ +if (!vec.empty()) { return vec.front(); } + +if (divider != 0) { + return num / divider; +} else { + return std::nan("nan"); +} + +if (ptr) { + return ptr->doSth(); +} + +if (name_ == other.name_) { + return index < other.index_; +} else { + return name_ < other.name_ +} +``` +* What is common for all of them? + +___ + + +Let's help compiler! + +```C++ +constexpr double pow(double x, int n) noexcept { + if (n > 0) [[likely]] { return x * pow(x, n - 1); } + else [[unlikely]] { return 1; } +} + +constexpr double pow2(double x, int n) noexcept { + if (n > 0) { return x * pow(x, n - 1); } + else { return 1; } +} + +int main() { + auto benchmark = [](auto fun) { + const auto start = std::chrono::high_resolution_clock::now(); + fun(); + const auto diff = std::chrono::high_resolution_clock::now() - start; + std::cout << "Time: " << std::fixed << std::setprecision(6) << diff.count() << " ns\n"; + }; + + std::vector vec(1'000'000); + std::iota(begin(vec), end(vec), 1); + benchmark([&]() { for (auto el : vec) { pow(el, 13); } }); + benchmark([&]() { for (auto el : vec) { pow2(el, 13); } }); + // Time: 59839100 ns + // Time: 79786800 ns +} +``` + +___ + + +There is more! + +```C++ +int Nwd(int a, int b) { + while (b != 0) [[likely]] { a = std::exchange(b, a % b); } + return a; +} + +int Nwd2(int a, int b) { + while (b != 0) { a = std::exchange(b, a % b); } + return a; +} + +int main() { + auto benchmark = [](auto fun) { + const auto start = std::chrono::high_resolution_clock::now(); + fun(); + const auto diff = std::chrono::high_resolution_clock::now() - start; + std::cout << "Time: " << std::fixed << std::setprecision(6) << diff.count() << " ns\n"; + }; + + std::vector vec(1'000'000); + std::iota(begin(vec), end(vec), 1); + benchmark([&](){ for (auto el : vec) { Nwd(1'000'000, el); } }); + benchmark([&](){ for (auto el : vec) { Nwd2(1'000'000, el); } }); + // Time: 140909100 ns + // Time: 182572100 ns +} +``` + +___ + + +## Ok ok, but what happens when I already use optimization flag? + +```C++ +int main() { + auto benchmark = [](auto fun) { + const auto start = std::chrono::high_resolution_clock::now(); + fun(); + const auto diff = std::chrono::high_resolution_clock::now() - start; + std::cout << "Time: " << std::fixed << std::setprecision(6) << diff.count() << " ns\n"; + }; + + std::vector vec(1'000'000); + std::iota(begin(vec), end(vec), 1); + int res = 0; + benchmark([&](){ for (auto el : vec) { res += Nwd(1'000'000, el); } }); // Time: 88765100 ns + benchmark([&](){ for (auto el : vec) { res += Nwd2(1'000'000, el); } }); // Time: 82797600 ns + benchmark([&]() { for (auto el : vec) { res += pow(el, 13); } }); // Time: 6002300 ns + benchmark([&]() { for (auto el : vec) { res += pow2(el, 13); } }); // Time: 8012500 ns + + return res; +} +``` + +Wait what?!. When we use -O3 optimization flag we got worse output for [[likely]]. It depends on various things, sometimes code run faster sometimes not, but generally, you can't charm the compiler with optimization, but sometimes you can help :) + + +___ + + +Use it when it is worth it, and the compiler could have a problem with manual optimization. For instance in 99.99% during response validation, an error occurs when there is no `result` filed, other cases happen mainly when someone implements wrong behavior and this is eliminated during tests. Ofc you still can always write more predictable if statement at the beginning :) And this is even better option in my opinion. + +```C++ +bool validate(const std::string& str) { + constexpr char kResult[] = "result:"; + + if (str.empty()) [[unlikely]] { + return false; + } else if (str.size() > 30) [[unlikely]] { + return false; + } else if (str.front() != '{') [[unlikely]] { + return false; + } else if (str.back() != '}') [[unlikely]] { + return false; + } else if (std::all_of(std::cbegin(str), std::cend(str), [](const char c) { return !std::isalnum(c); })) [[unlikely]] { + return false; + } else if (std::search(std::cbegin(str), std::cend(str), std::cbegin(kResult), std::cend(kResult)) == + std::cend(str)) [[likely]] { + return false; + } + + return true; +} + +bool validate2(const std::string& str) { + constexpr char kResult[] = "result:"; + + if (str.empty()) { + return false; + } else if (str.size() > 30) { + return false; + } else if (str.front() != '{') { + return false; + } else if (str.back() != '}') { + return false; + } else if (std::all_of(std::cbegin(str), std::cend(str), [](const char c) { return !std::isalnum(c); })) { + return false; + } else if (std::search(std::cbegin(str), std::cend(str), std::cbegin(kResult), std::cend(kResult)) == + std::cend(str)) { + return false; + } + + return true; +} + +int main() { + auto benchmark = [](auto fun) { + const auto start = std::chrono::high_resolution_clock::now(); + fun(); + const auto diff = std::chrono::high_resolution_clock::now() - start; + std::cout << "Time: " << std::fixed << std::setprecision(6) << diff.count() << " ns\n"; + }; + + int wrong = 0; + std::vector vec(1'000'000, "{result:12345}"); + benchmark([&]() { + wrong += std::count_if(std::cbegin(vec), std::cend(vec), [](const auto& str) { return validate(str); }); + }); + benchmark([&]() { + wrong += std::count_if(std::cbegin(vec), std::cend(vec), [](const auto& str) { return validate2(str); }); + }); + // Time: 293222100 ns + // Time: 376011000 ns + // + // With 03 + // Time: 14437300 ns + // Time: 21943400 ns + + return wrong; +} +``` + + +___ + + +## no_unique_address + +Allows this data member to be overlapped with other non-static data members or base class subobjects of its class. Generally, we can use it when we have an empty filed in the structure, and we don't want to lost 1 byte to store it. + +```C++ +struct Empty {}; + +struct Filed { + int val_; + double val2_; + Empty empty_; +}; + +struct Filed2 { + int val_; + double val2_; + [[no_unique_address]] Empty empty_; +}; + +int main() { + static_assert(sizeof(Empty) >= 1); + std::cout << "sizeof(Filed): " << sizeof(Filed) << '\n'; // 24 + std::cout << "sizeof(Filed): " << sizeof(Filed2) << '\n'; // 16 +} +``` + + +___ + + +## pack-expansion in lmabdas + +Since C++20 we can easily move all arguments to lambda. Before C++20 we can do this only for one object, but now it works for packages also. + +```C++ +auto postponeTask(auto&& fun, auto&&... args) { + return [f = std::move(fun), ... pack = std::move(args)]() { + return f(pack...); + }; +} + +int main() { + auto task = postponeTask([](const std::string& str, int num) { + std::cout << str << " | " << num << '\n'; + }, std::string("Ala ma kota"), 42); + + task(); +} +``` +___ + + +If you don't have C++20 (but you have C++17) you can still use the trick with the `std::tuple` with `std::apply` method. + +```C++ +template +auto postponeTask(Fun fun, Args... args) { + return [fun = std::move(fun), tup = std::make_tuple(std::move(args)...)]() -> decltype(auto) { + return std::apply([fun = std::move(fun)](auto const&... args) -> decltype(auto) { + return fun(args...); + }, tup); + }; +} +int main() { + auto task = postponeTask([](const std::string& str, int num) { + std::cout << str << " | " << num << '\n'; + }, std::string("Ala ma kota"), 42); + + task(); +} +``` + +___ + + +## template syntax for lambdas + +Ok, but what if I want to perfect forward arguments, instead of moving them? Since C++20 you can use template syntax! + +```C++ +int main() { + auto benchmark = [](auto&& fun, Args... args) { + const auto now = std::chrono::system_clock::now(); + const auto res = std::move(fun)(std::forward(args)...); + const auto then = std::chrono::system_clock::now(); + std::cout << "res: " << res << " | time: " << (then - now).count() << " ns\n"; + }; + + benchmark([](int count, int init) -> long long { + std::vector vec(count); + std::iota(begin(vec), end(vec), init); + return std::accumulate(begin(vec), end(vec), 0); + }, 1'000'000, 50); +} +``` + +___ + + +## uniform erasure + +Ok let's do sth easier! How many times have you written sth like this :)? + +```C++ +std::vector vec {1,2,3,4,5,6}; +vec.erase(std::remove_if(begin(vec), end(vec), [](auto num){ return num & 1; }), vec.end()); +``` + + +`std::remove` only prepares a vector to actually remove, but in the end, we need to erasure these values. Yes, this is why a lot of ppl hate C++, always complications. For instance we can write sth like this: + + +```C++ +std::map map {{"One", 1}, {"Two", 2}, {"Three", 3}}; +map.erase("One"); + +std::list list {"Ala", "ma", "kota"}; +list.remove("Ala"); +``` + + +In the case of a list, there is a member function `remove`, which actually removes an element! But for the map, we have only `erase`, which also takes a key as a value and removes an element. 3 containers and 3 different behavior. Definitely, newcomers won't like this. The funniest part is that list has `remove_if` method, but the map doesn't have `erase_if` ;) + + +___ + + +Since C++20 erasing elements is finally unified! We have two options, `erase` or `erase_if`. Unfortunately, in C++ there is always an exception to the rule. `std::map` and `std::set` (and their hash versions) don't have `std::erase` overload, because they already have specialized members functions. + +```C++ + std::vector vec {1,2,3,4,5,6}; + std::erase(vec, 4); + std::erase_if(vec, [](auto num){ return num & 1; }); + + std::map map {{"One", 1}, {"Two", 2}, {"Three", 3}}; + map.erase("One"); // There is no std::erase() for map :/ + std::erase_if(map, [](const auto& pair){ return pair.second == 2; }); // But there is std::erase_if + + std::list list {"Ala", "ma", "kota"}; + std::erase(list, "ma"); + std::erase_if(list, [](const auto& str){ return str.length() == 3; }); + + std::unordered_set set{1,2,3,4,5,6}; + set.erase(4); + std::erase_if(set, [](auto num){ return num & 1; }); +``` + + +___ + + +## source_loaction + +Since C++20 we got a nice functionality to perform easy and efficient logging. + +```C++ +void log(const std::string_view message, + const std::source_location location = + std::source_location::current()) +{ + std::cout << "file: " + << location.file_name() << "(" + << location.line() << ":" + << location.column() << ") `" + << location.function_name() << "`: " + << message << '\n'; +} + +template void fun(T x) +{ + log(x); +} + +int main(int, char*[]) +{ + log("Hello world!"); + fun("Hello C++20!"); +} +``` + +```bash +file: prog.cc(24:8) `int main(int, char**)`: Hello world! +file: prog.cc(19:8) `void fun(T) [with T = const char*]`: Hello C++20! +``` + + +___ + + +It's easy to rebuild a little this solution and create own logger: + +```C++ +enum LogType {INF, WRN, ERR}; + +struct Logger { + Logger(LogType logType, std::source_location location = std::source_location::current()): + logType_{logType}, + location_{location} {} + + Logger& operator<<(std::string_view message) { + const auto time = std::chrono::system_clock::to_time_t(std::chrono::system_clock::now()); + std::ostringstream os; + os << "[" << toString(logType_) << "]" + << "(" << std::put_time(std::localtime(&time), "%Y-%m-%d %X") << "): " + << location_.file_name() << "(" + << location_.line() << ":" + << location_.column() << ") `" + << location_.function_name() << "`: " + << message << '\n'; + file_ << os.str() << std::flush; + + return *this; + } + +private: + std::string_view toString(LogType logType) { + switch (logType) { + case INF: return "INFO"; + case WRN: return "WARNING"; + case ERR: return "ERROR"; + default: return "UNKNOWN!"; + } + } + + LogType logType_; + std::source_location location_; + static std::ofstream file_; +}; + +std::ofstream Logger::file_("log.txt"); +``` + +___ + + +Ok now is time to log sth + +```C++ +int main() { + Logger(INF) << "Hello!" << "And Hi" << "And Dzien dobry!"; + Logger(WRN) << "Ojej!"; + Logger(ERR) << "Critical!!!" << "UPS!" << "Bad bad!"; +} +``` + +And in file `log.txt` we got: + + +```C++ +[INFO](2022-05-22 14:24:47): prog.cc(55:15) `int main()`: Hello! +[INFO](2022-05-22 14:24:47): prog.cc(55:15) `int main()`: And Hi +[INFO](2022-05-22 14:24:47): prog.cc(55:15) `int main()`: And Dzien dobry! +[WARNING](2022-05-22 14:24:47): prog.cc(56:15) `int main()`: Ojej! +[ERROR](2022-05-22 14:24:47): prog.cc(57:15) `int main()`: Critical!!! +[ERROR](2022-05-22 14:24:47): prog.cc(57:15) `int main()`: UPS! +[ERROR](2022-05-22 14:24:47): prog.cc(57:15) `int main()`: Bad bad! +``` + + + +___ + + +# bit operations + +There is a new header `` which allows performing many valuable operations on bits. All functions are declared as constexpr, so there is a big chance that everything will be evaluated at compile time! Finally, you don't need to write an ugly macro. Let's start with the most important one. + +`std::endian` indicates the endianness of all scalar types: + +- If all scalar types are little-endian, std::endian::native equals std::endian::little +- If all scalar types are big-endian, std::endian::native equals std::endian::big + +Corner case platforms are also supported: + + +- If all scalar types have sizeof equal to 1, endianness does not matter and all three values, std::endian::little, std::endian::big, and std::endian::native are the same. +- If the platform uses mixed endian, std::endian::native equals neither std::endian::big nor std::endian::little. + +```C++ +int main() { + + if constexpr (std::endian::native == std::endian::big) + std::cout << "big-endian\n"; + else if constexpr (std::endian::native == std::endian::little) + std::cout << "little-endian\n"; + else std::cout << "mixed-endian\n"; + // Output: little-endian +} +``` + + +___ + + +For me very usefull is also `popcount`, and all `countX_Y` function, where`X` could be `l` - left, `r` - right, and `Y` could be `zero` or `one`: + +```C++ +int main() { + // counts the number of 1 bits in an unsigned integer + std::cout << std::popcount(0b1010101010101u) << '\n'; // 7 + + // counts the number of consecutive 1 bits, starting from the most significant bit + std::cout << std::countl_one(std::numeric_limits::max()) << '\n'; // 8 + + // counts the number of consecutive 0 bits, starting from the most significant bit + std::cout << std::countl_zero(0b111000011111u) << '\n'; // 20 because this is uint32_t + + // counts the number of consecutive 1 bits, starting from the least significant bit + std::cout << std::countr_one(0b111000011111u) << '\n'; // 5 + + // counts the number of consecutive 0 bits, starting from the least significant bit + std::cout << std::countr_zero(0b111000011100u) << '\n'; // 2 +} +``` + + +___ + + +Sometimes in the algorithm, we need to know the closest power of 2 for a given number. + +```C++ +int main() { + for (uint8_t i = 0 ; i < 16 ; ++i) { + std::cout << "num: " << std::bitset(i) + << " | bit_width: " << +std::bit_width(i) + << " | power of 2: " << std::has_single_bit(i) + << " | floor: " << +std::bit_floor(i) + << " | ceil: " << +std::bit_ceil(i) << '\n'; + } +} +``` +```bash +num: 00000000 | bit_width: 0 | power of 2: 0 | floor: 0 | ceil: 1 +num: 00000001 | bit_width: 1 | power of 2: 1 | floor: 1 | ceil: 1 +num: 00000010 | bit_width: 2 | power of 2: 1 | floor: 2 | ceil: 2 +num: 00000011 | bit_width: 2 | power of 2: 0 | floor: 2 | ceil: 4 +num: 00000100 | bit_width: 3 | power of 2: 1 | floor: 4 | ceil: 4 +num: 00000101 | bit_width: 3 | power of 2: 0 | floor: 4 | ceil: 8 +num: 00000110 | bit_width: 3 | power of 2: 0 | floor: 4 | ceil: 8 +num: 00000111 | bit_width: 3 | power of 2: 0 | floor: 4 | ceil: 8 +num: 00001000 | bit_width: 4 | power of 2: 1 | floor: 8 | ceil: 8 +num: 00001001 | bit_width: 4 | power of 2: 0 | floor: 8 | ceil: 16 +num: 00001010 | bit_width: 4 | power of 2: 0 | floor: 8 | ceil: 16 +num: 00001011 | bit_width: 4 | power of 2: 0 | floor: 8 | ceil: 16 +num: 00001100 | bit_width: 4 | power of 2: 0 | floor: 8 | ceil: 16 +num: 00001101 | bit_width: 4 | power of 2: 0 | floor: 8 | ceil: 16 +num: 00001110 | bit_width: 4 | power of 2: 0 | floor: 8 | ceil: 16 +num: 00001111 | bit_width: 4 | power of 2: 0 | floor: 8 | ceil: 16 +``` + + +___ + + +There is also a rotation `left` /` right`. Standard `c ++ 23` introduced also` byteswap` to convert variables from little endian to big endian and vice versa. + +```C++ +uint16_t num = 0b1111001100111001; +std::cout << "num: " << std::bitset<16>(num) << "\n\n"; +for (uint8_t i = 0 ; i < 16 ; ++i) { + std::cout << "rotr: " << std::bitset<16>(std::rotr(num, i)) + << " | rotl: " << std::bitset<16>(std::rotl(num, i)) + << '\n'; +} +``` + +```bash +num: 1111001100111001 + +rotr: 1111001100111001 | rotl: 1111001100111001 +rotr: 1111100110011100 | rotl: 1110011001110011 +rotr: 0111110011001110 | rotl: 1100110011100111 +rotr: 0011111001100111 | rotl: 1001100111001111 +rotr: 1001111100110011 | rotl: 0011001110011111 +rotr: 1100111110011001 | rotl: 0110011100111110 +rotr: 1110011111001100 | rotl: 1100111001111100 +rotr: 0111001111100110 | rotl: 1001110011111001 +rotr: 0011100111110011 | rotl: 0011100111110011 +rotr: 1001110011111001 | rotl: 0111001111100110 +rotr: 1100111001111100 | rotl: 1110011111001100 +rotr: 0110011100111110 | rotl: 1100111110011001 +rotr: 0011001110011111 | rotl: 1001111100110011 +rotr: 1001100111001111 | rotl: 0011111001100111 +rotr: 1100110011100111 | rotl: 0111110011001110 +rotr: 1110011001110011 | rotl: 1111100110011100 +``` + + +___ + + +## format your string like in printf + +The main problem with `std::cout` is a problem with easy formatting (I know streams are also inefficient, but this is not a point right now). For instance: + +```C++ +int main() { + for (uint8_t i = 0 ; i < 16 ; ++i) { + std::cout << "num: " << std::bitset(i) + << " | bit_width: " << +std::bit_width(i) + << " | power of 2: " << std::has_single_bit(i) + << " | floor: " << +std::bit_floor(i) + << " | ceil: " << +std::bit_ceil(i) << '\n'; + } +} +``` + +With `` library now we can write: + + +```C++ +for (uint8_t i = 0; i < 16; ++i) { + std::cout << std::format("num: {} | bit_width: {} | power of 2: {} | floor: {} | ceil {}\n", + std::bitset(i).to_string(), + std::bit_width(i), + std::has_single_bit(i), + std::bit_floor(i), + std::bit_ceil(i)); +} +``` + + +___ + + +On day `25.05.2022` the newest `gcc 13` didn't support the library ``. Fortunately `clang 15` already supports it! `` library is very powerful, we can easily create any format we want and pass any values we need: + +```C++ +void raw_write_to_log(std::string_view users_fmt, std::format_args&& args) { + constinit static int line{}; + std::clog << std::format("{:04} : ", line++) << std::vformat(users_fmt, args) << '\n'; +} + +template +constexpr void log(Args&&... args) { + // Generate formatting string "{} "... + std::array braces{}; + constexpr const char c[] = "{} "; + for (auto i{0u}; i != braces.size() - 1; ++i) { + braces[i] = c[i % 3]; + } + braces.back() = '\0'; + + raw_write_to_log(braces.data(), std::make_format_args(std::forward(args)...)); +} + +int main() +{ + std::string str{"Printable"}; + log("You", "Can", "Pass", "Any", "Number", "Of", "Arguments"); + log("Everything", "Which", "Can", "Be", str); + log(1, 4.5, 1234); +} +``` + +```bash +0000 : You Can Pass Any Number Of Arguments +0001 : Everything Which Can Be Printable +0002 : 1 4.5 1234 +``` + + +___ + + +## Limitations + +We need to wait to specify how we should specify custom object formatting. Currently on cppreference we can see an example, but looking very ugly and don't compile on `clang 15`. + +```C++ +#include +#include + +// A wrapper for type T +template +struct Box { + T value; +}; + +// The wrapper Box can be formatted using the format specification of the wrapped value +template +struct std::formatter, CharT> : std::formatter { + // parse() is inherited from the base class + + // Define format() by calling the base class implementation with the wrapped value + template + auto format(Box t, FormatContext& fc) const { + return std::formatter::format(t.value, fc); + } +}; + +int main() { + Box v = { 42 }; + std::cout << std::format("{:#x}", v); +} +``` + + +___ + + +But to make you more interested in this library check out more possibilities: + +```C++ +int main() +{ + std::string buffer; + + std::format_to( + std::back_inserter(buffer), + "Hello, C++{}!\n", // formater + "20", // args + "More args, make no error :)"); + + std::cout << buffer << '\n'; +} +``` + + +```bash +Hello, C++20! +``` + + diff --git a/AdvancedCppV2/Presentation/moder_cpp_intro.md b/AdvancedCppV2/Presentation/moder_cpp_intro.md new file mode 100644 index 0000000..9b31245 --- /dev/null +++ b/AdvancedCppV2/Presentation/moder_cpp_intro.md @@ -0,0 +1,39 @@ +# Timeline of C++ (1) + + +* C++98: + * Templates + * I/O streams + * String + * STL containers, iterators, algorithms +* C++11: + * Smart pointers + * Move semantic + * Lambda expressions + * Unified initialization + * Auto deduction + * Constexpr + * Multithreading and new model of memory + * Regular expressions + * Hash tables +___ + + +## Timeline of C++ (2) + +* C++14: + * Generic lambda + * Reader-write lock +* C++17: + * Parallel algorithms + * Filesystem library + * Fold expression + * constexpr if + * Structural binding + * any/ optional/ variant +* C++20: + * Modules + * Concepts + * Ranges + * Coroutines + * Other small features :) \ No newline at end of file diff --git a/AdvancedCppV2/Presentation/recap.md b/AdvancedCppV2/Presentation/recap.md new file mode 100644 index 0000000..38cd39b --- /dev/null +++ b/AdvancedCppV2/Presentation/recap.md @@ -0,0 +1,8 @@ + + +# Recap + +___ + +## What do you remember from today's session? + diff --git a/AdvancedCppV2/Presentation/smart_pointers_auto_ptr.md b/AdvancedCppV2/Presentation/smart_pointers_auto_ptr.md new file mode 100644 index 0000000..b3fcf84 --- /dev/null +++ b/AdvancedCppV2/Presentation/smart_pointers_auto_ptr.md @@ -0,0 +1,10 @@ + + +## `std::auto_ptr<>` - something to forget + +* C++98 provided std::auto_ptr<> +* Few fixes in C++03 +* Yet still it’s easy to use incorrectly… +* Deprecated since C++11 +* Removed since C++17 +* Do not use it, use std::unique_ptr<> instead diff --git a/AdvancedCppV2/Presentation/smart_pointers_best_practices.md b/AdvancedCppV2/Presentation/smart_pointers_best_practices.md new file mode 100644 index 0000000..427c097 --- /dev/null +++ b/AdvancedCppV2/Presentation/smart_pointers_best_practices.md @@ -0,0 +1,196 @@ + + +# Best practices + +___ + +## Best practices + +* Rule of 0, Rule of 5 +* Avoid explicit new +* Use std::make_shared() / std::make_unique() +* Avoid copying std::shared_ptr<> when this is not neccessary. +* Use references instead of pointers (as argument to function) +* Almost always use unique_ptr +* Use shared_ptr ONLY when you need to share ownership of object. + +___ + +## Rule of 0, Rule of 5 + +### Rule of 5 + +* If you need to implement one of those functions: + * destructor + * copy constructor + * copy assignment operator + * move constructor + * move assignment operator +* It probably means that you should implement them all, because you have manual resources management. + +### Rule of 0 + +* If you use RAII wrappers on resources, you don’t need to implement any of Rule of 5 functions. + +___ + +## Avoid explicit `new` + +* Smart pointers eliminate the need to use delete explicitly +* To be symmetrical, do not use new as well +* Allocate using: + * std::make_unique() + * std::make_shared() +* use new only when you need to create ptr with custom deleter + +___ + + + +### Use `std::make_shared()` / `std::make_unique()` + +* What is a problem here? + +```cpp +struct MyData { int value; }; +using Ptr = std::shared_ptr; +void sink(Ptr oldData, Ptr newData); + +void use(void) { + sink(Ptr{new MyData{41}}, Ptr{new MyData{42}}); +} +``` + + +* Hint: this version is not problematic + +```cpp +struct MyData { int value; }; +using Ptr = std::shared_ptr; +void sink(Ptr oldData, Ptr newData); + +void use(void) { + Ptr oldData{new MyData{41}}; + Ptr newData{new MyData{42}}; + sink(std::move(oldData), std::move(newData)); +} +``` + + +___ + +### Allocation deconstructed + +`auto p = new MyData(10);` means: + +* allocate sizeof(MyData) bytes +* run MyData constructor +* assign address of allocated memory to p + +Order of evaluation of any part of any expression, including order of evaluation of function arguments is **unspecified**. The compiler can evaluate operands and other subexpressions in any order, and may choose another order when the same expression is evaluated again. There is no concept of left-to-right or right-to-left evaluation in C++. This is not a problem since C++17 due to the changes in the evaluation order of function arguments. Specifically, each argument to a function is required to fully execute before evaluation of other arguments. + + + +___ + + +### Unspecified order of evaluation + +* How about two such operations (before C++17)? + +| first operation (A) | second operation (B) | +| :-------------------------------------------- | :-------------------------------------------- | +| (1) allocate `sizeof(MyData)` bytes | (1) allocate `sizeof(MyData)` bytes | +| (2) run `MyData` constructor | (2) run `MyData` constructor | +| (3) assign address of allocated memory to `p` | (3) assign address of allocated memory to `p` | + +* Unspecified order of evaluation means that order can be for example: + * A1, A2, B1, B2, A3, B3 +* What if B2 throws an exception? + +___ + +### Use `std::make_shared()` / `std::make_unique()` + +* std::make_shared() / std::make_unique() resolves this problem + +```cpp +struct MyData{ int value; }; +using Ptr = std::shared_ptr; +void sink(Ptr oldData, Ptr newData); + +void use() { + sink(std::make_shared(41), std::make_shared(42)); +} +``` + + +* Fixes previous bug +* Does not repeat a constructed type +* Does not use explicit new +* Optimizes memory usage (only for std::make_shared()) + +___ + +## Copying `std::shared_ptr<>` + +```cpp +void foo(std::shared_ptr p); + +void bar(std::shared_ptr p) { + foo(p); +} +``` + +* requires counters incrementing / decrementing +* atomics / locks are not free +* will call destructors + +##### Can be better? + + +___ + +## Copying `std::shared_ptr<>` + +```cpp +void foo(const std::shared_ptr & p); + +void bar(const std::shared_ptr & p) { + foo(p); +} +``` + +* as fast as pointer passing +* no extra operations +* not safe in multithreaded applications + +___ + +### Use references instead of pointers + +* What is the difference between a pointer and a reference? + * reference cannot be empty + * reference, once assigned cannot point to anything else +* Priorities of usage (if possible): + * (const) T& + * std::unique_ptr<T> + * std::shared_ptr<T> + * T* + +___ + +## Exercise: List + +Take a look at `List.cpp` file, where simple (and buggy) single-linked list is implemented. + +* `pushFront` method adds a new `Node` at the begining of the list. +* `findByValue` method iterates over the list and returns the first Node with matching `value` or `nullptr`. + +1. Compile and run List application +2. Fix memory leaks without introducing smart pointers +3. Fix memory leaks with smart pointers. What kind of pointers needs to be applied and why? +4. Add function to add a node at the end of the list (try to do this with time complexity O(1)) +5. Add function to delete node with provided value. + + \ No newline at end of file diff --git a/AdvancedCppV2/Presentation/smart_pointers_efficiency.md b/AdvancedCppV2/Presentation/smart_pointers_efficiency.md new file mode 100644 index 0000000..17240ad --- /dev/null +++ b/AdvancedCppV2/Presentation/smart_pointers_efficiency.md @@ -0,0 +1,181 @@ + + +# Efficiency + +___ + +## Raw pointer + +```cpp +#include +#include + +struct Data { + char tab_[42]; +}; + +int main(void) { + constexpr unsigned size = 10u * 1000u * 1000u; + std::vector v; + v.reserve(size); + for (unsigned i = 0; i < size; ++i) { + auto p = new Data; + v.push_back(std::move(p)); + } + for (auto p: v) + delete p; +} +``` + +___ + +## Unique pointer + +```cpp +#include +#include + +struct Data { + char tab_[42]; +}; + +int main(void) { + constexpr unsigned size = 10u * 1000u * 1000u; + std::vector> v; + v.reserve(size); + for (unsigned i = 0; i < size; ++i) { + std::unique_ptr p{new Data}; + v.push_back(std::move(p)); + } +} +``` + +___ + +## Shared pointer + +```cpp +#include +#include + +struct Data { + char tab_[42]; +}; + +int main(void) { + constexpr unsigned size = 10u * 1000u * 1000u; + std::vector> v; + v.reserve(size); + for (unsigned i = 0; i < size; ++i) { + std::shared_ptr p{new Data}; + v.push_back(std::move(p)); + } +} +``` + +___ + +## Shared pointer – `make_shared` + +```cpp +#include +#include + +struct Data { + char tab_[42]; +}; + +int main(void) { + constexpr unsigned size = 10u * 1000u * 1000u; + std::vector> v; + v.reserve(size); + for (unsigned i = 0; i < size; ++i) { + auto p = std::make_shared(); + v.push_back(std::move(p)); + } +} +``` + +___ + +## Weak pointer + +```cpp +#include +#include + +struct Data { + char tab_[42]; +}; + +int main(void) { + constexpr unsigned size = 10u * 1000u * 1000u; + std::vector> vs; + std::vector> vw; + vs.reserve(size); + vw.reserve(size); + for (unsigned i = 0; i < size; ++i) { + std::shared_ptr p{new Data}; + std::weak_ptr w{p}; + vs.push_back(std::move(p)); + vw.push_back(std::move(w)); + } +} +``` + +___ + +## Measurements + +* gcc-4.8.2 +* compilation with –std=c++11 –O3 –DNDEBUG +* measuring with: + * time (real) + * htop (mem) + * valgrind (allocations count) + +___ + +## Results + +| test name | time [s] | allocations | memory [MB] | +|:--------------:|:--------:|:-----------:|:-----------:| +| raw pointer | 0.54 | 10 000 001 | 686 | +| unique pointer | 0.56 | 10 000 001 | 686 | +| shared pointer | 1.00 | 20 000 001 | 1072 | +| make shared | 0.76 | 10 000 001 | 914 | +| weak pointer | 1.28 | 20 000 002 | 1222 | + +___ + +## Conclusions + +* RAII + * acquire resource in constructor + * release resource in destructor +* Rule of 5, Rule of 0 +* Smart pointers: + * std::unique_ptr – primary choice, no overhead, can convert to std::shared_ptr + * std::shared_ptr – introduces memory and runtime overhead + * std::weak_ptr – breaking cycles, can convert to/from std::shared_ptr +* Create smart pointers with std::make_shared() and std::make_unique() +* Raw pointer should mean „access only” (no ownership) +* Use reference instead of pointers if possible + +___ + +## Post-work + +* Transform the list from List.cpp into double-linked list. You should implement: + * inserting Nodes at the beginning of the list + * searching elements in reverse + * Apply proper smart pointers for the reverse direction. +* Implement your own unique_ptr. Requirements: + * Templatized (should hold a pointer to a template type) + * RAII (acquire in constructor, release in destructor) + * Copying not allowed + * Moving allowed + * Member functions: operator*(), operator->(), get(), release(), reset() +* Read one of these articles on move semantics: + * Semantyka przenoszenia (in Polish) + * Move semantics and rvalue references in C++11 (in English) diff --git a/AdvancedCppV2/Presentation/smart_pointers_implementation_details.md b/AdvancedCppV2/Presentation/smart_pointers_implementation_details.md new file mode 100644 index 0000000..6f6274e --- /dev/null +++ b/AdvancedCppV2/Presentation/smart_pointers_implementation_details.md @@ -0,0 +1,122 @@ + + +# Implementation details + +___ + +### Implementation details – `std::unique_ptr<>` + +* Just a holding wrapper +* Holds an object pointer +* Constructor copies a pointer +* Call proper delete in destructor +* No copying +* Moving means: + * Copying original pointer to a new object + * Setting source pointer to nullptr + +___ + +### Implementation details – `std::shared_ptr<>` + +sharedptr2 + +* Holds an object pointer +* Holds 2 reference counters: + * shared pointers count + * weak pointers count +* Destructor: + * decrements shared-refs + * deletes user data when shared-refs == 0 + * deletes reference counters when shared-refs == 0 and weak-refs == 0 +* Extra space for a deleter + +___ + +### Implementation details – `std::shared_ptr<>` + +* Copying means: + * Copying pointers to the target + * Incrementing shared-refs + +sharedptr3 + +* Moving means: + * Copying pointers to the target + * Setting source pointers to nullptr + +sharedptr4 + +___ + +### Implementation details – `std::weak_ptr<>` + +* Holds an object pointer +* Holds 2 reference counters: + * shared pointers count + * weak pointers count +* Destructor: + * decrements weak-refs + * deletes reference counters when shared-refs == 0 and weak-refs == 0 + +sharedptr5 + +___ + +### Implementation details – `std::weak_ptr<>` + +* Copying means: + * Copying pointers to the target + * Incrementing weak-refs + +sharedptr6 + +* Moving means: + * Copying pointers to the target + * Setting source pointers to nullptr + +sharedptr7 + +___ + +### `std::weak_ptr<>` + `std::shared_ptr<>` + +* Having a shared pointer and a weak pointer + +sharedptr8 + +* After removing the shared pointer + +sharedptr9 + +___ + +## Making a `std::shared_ptr<>` + + + +
+
+ + +* std::shared_ptr<Data> p{new Data}; + * Perform two allocations: one for control block and second for data + * Before C++17 can make a problem with ordering of operations + * When all shared_ptr will be deleted but there is some weak_ptr allocated memory for data can be freed. + +sharedptr10 +
+ +
+ + +* auto p = std::make_shared<Data>(); + * Less memory (most likely) + * Only one allocation + * Cache-friendly + * When all shared_ptr will be deleted but there is some weak_ptr allocated memory for data cannot be freed + +sharedptr11 + +
+
\ No newline at end of file diff --git a/AdvancedCppV2/Presentation/smart_pointers_shared_ptr.md b/AdvancedCppV2/Presentation/smart_pointers_shared_ptr.md new file mode 100644 index 0000000..61bae62 --- /dev/null +++ b/AdvancedCppV2/Presentation/smart_pointers_shared_ptr.md @@ -0,0 +1,189 @@ + + +# `std::shared_ptr<>` + +___ + +### `std::shared_ptr<>` + +* one object == multiple owners +* last referrer destroys the object +* copying allowed +* moving allowed +* can use custom deleter +* can use custom allocator +* has a control block == impact on size of pointer end efficiency + +shared pointers + +___ + + +### `std::shared_ptr<>` usage (1) + +* Copying and moving is allowed + +
+
+ +```cpp +std::shared_ptr source(); +void sink(std::shared_ptr ptr); + +void simpleUsage() { + source(); + sink(source()); + auto ptr = source(); + sink(ptr); + sink(std::move(ptr)); + auto p1 = source(); + auto p2 = p1; + p2 = std::move(p1); + p1 = p2; + p1 = std::move(p2); +} + +``` + +
+ +
+ +```cpp +std::shared_ptr source(); +void sink(std::shared_ptr ptr); + +void collections() { + std::vector> v; + + v.push_back(source()); + + auto tmp = source(); + v.push_back(tmp); + v.push_back(std::move(tmp)); + + sink(v[0]); + sink(std::move(v[0])); +} +``` + +
+
+ +___ + + +### `std::shared_ptr<>` usage (2) + +```cpp +#include +#include +#include + +class Gadget {}; +std::map> gadgets; + +void foo() { + std::shared_ptr p1{new Gadget()}; // reference counter = 1 + { + auto p2 = p1; // copy (reference counter == 2) + gadgets.insert(make_pair("mp3", p2)); // copy (reference counter == 3) + p2->use(); + } // destruction of p2, reference counter = 2 +} // destruction of p1, reference counter = 1 + +int main() { + foo(); + gadgets.clear(); // reference counter = 0 - gadget is removed +} +``` +___ + +### Custom deleter + +* Don't change a type of shared_ptr because data is stored in control block +* Don't change a size of shared_ptr because data is stored in control block +* You can have a collection of shared_ptr which has different deleter + +
+
+ +```C++ +class Foo {}; + +void deleter1(Foo* const foo) { + std::cout << "Deleter1\n"; + delete foo; +} + +int main() { + std::vector> vec; + std::shared_ptr ptr1(new Foo(), deleter1); + vec.push_back(std::move(ptr1)); + + auto deleter2 = [](Foo* const foo) { + std::cout << "Deleter2\n"; + delete foo; + }; + vec.emplace_back(new Foo(), deleter2); +} +``` + +
+ +
+ +```Bash +Deleter1 +Deleter2 +``` + +
+ + +___ + +### Problem with shared_ptr + +Let's look at a short story: + +* Programmer1 : Why do you pass shared_ptr by copy? Passing by copy increment counter (slower then unique or raw ptr) +* Programmer2: Ok, so I will pass it by const reference instead! And avoid unnecessary incrementation of the control block. +* Programmer1: So if you don't need to copy it (don't need to have 2 owners) why don't use unique_ptr? +* Reassume: shared_ptr should be use only when given resource need to have few owners (very rare situation). In other case use always unique_ptr! + +___ + +### `std::shared_ptr<>` cyclic dependencies + +* What happens here? + +
+
+ +```cpp +#include + +struct Node { + std::shared_ptr child; + std::shared_ptr parent; +}; + +int main () { + auto root = std::shared_ptr(new Node); + auto child = std::shared_ptr(new Node); + + root->child = child; + child->parent = root; +} + + +``` + +
+ +
+ Memory leak! + kot + +
diff --git a/AdvancedCppV2/Presentation/smart_pointers_smart_ptrs.md b/AdvancedCppV2/Presentation/smart_pointers_smart_ptrs.md new file mode 100644 index 0000000..f8a2f5f --- /dev/null +++ b/AdvancedCppV2/Presentation/smart_pointers_smart_ptrs.md @@ -0,0 +1,21 @@ + + +# Smart pointers + +___ + +## Smart pointers + +* A smart pointer manages a pointer to a heap allocated object + + * Deletes the pointed-to object at the right time + * operator->() calls managed object methods + * operator.() calls smart pointer methods + * smart pointer to a base class can hold a pointer to a derived class + +* STL smart pointers: + + * std::unique_ptr<> + * std::shared_ptr<> + * std::weak_ptr<> + * std::auto_ptr<> - removed in C++17 diff --git a/AdvancedCppV2/Presentation/smart_pointers_summary.md b/AdvancedCppV2/Presentation/smart_pointers_summary.md new file mode 100644 index 0000000..8e7c232 --- /dev/null +++ b/AdvancedCppV2/Presentation/smart_pointers_summary.md @@ -0,0 +1,18 @@ + + +# Smart pointers - summary + +* #include <memory> +* std::unique_ptr<> for exclusive ownership +* std::shared_ptr<> for shared ownership +* std::weak_ptr<> for observation and breaking cycles + +___ + +## Exercise: ResourceFactory + +1. Compile and run ResourceFactory application +2. Put comments in places where you can spot some problems +3. How to remove elements from the collection (vector<Resource*> resources)? +4. Check memory leaks +5. Fix problems diff --git a/AdvancedCppV2/Presentation/smart_pointers_unique_ptr.md b/AdvancedCppV2/Presentation/smart_pointers_unique_ptr.md new file mode 100644 index 0000000..03a8590 --- /dev/null +++ b/AdvancedCppV2/Presentation/smart_pointers_unique_ptr.md @@ -0,0 +1,434 @@ + + +# `std::unique_ptr<>` + +___ + +## `std::unique_ptr<>` + +
+ +* one object == one owner +* destructor destroys the object +* copying not allowed +* moving allowed +* can use custom deleter +* 0 cost class -> no impact on efficiency + +
+ +unique pointers + +___ + +### `std::unique_ptr<>` usage + +* Old style approach vs modern approach + +
+
+ +```cpp +#include // old-style approach + + +struct Msg { + int getValue() { return 42; } +}; + +Msg* createMsg() { + return new Msg{}; +} + +int main() { + auto msg = createMsg(); + + std::cout << msg->getValue(); + delete msg; +} +``` + + +
+ +
+ +```cpp +#include // modern approach +#include + +struct Msg { + int getValue() { return 42; } +}; + +std::unique_ptr createMsg() { + return std::make_unique(); +} + +int main() { + // unique ownership + auto msg = createMsg(); + + std::cout << msg->getValue(); +} + +``` + + +
+ +___ + +### `std::unique_ptr<>` usage + +* Copying is not allowed +* Moving is allowed + +
+
+ +```cpp +std::unique_ptr source(void); +void sink(std::unique_ptr ptr); + +void simpleUsage() { + source(); + sink(source()); + auto ptr = source(); + // sink(ptr); // compilation error + sink(std::move(ptr)); + auto p1 = source(); + // auto p2 = p1; // compilation error + auto p2 = std::move(p1); + // p1 = p2; // compilation error + p1 = std::move(p2); +} +``` + + +
+ +
+ +```cpp +std::unique_ptr source(void); +void sink(std::unique_ptr ptr); + +void collections() { + std::vector> v; + v.push_back(source()); + + auto tmp = source(); + // v.push_back(tmp); // compilation error + v.push_back(std::move(tmp)); + + // sink(v[0]); // compilation error + sink(std::move(v[0])); + +} +``` + + +
+ +___ + +#### `std::unique_ptr<>` problem with containers + +
+ + What is wrong with this part of code? + + +```cpp +std::unique_ptr source(void); +void sink(std::unique_ptr ptr); + +void collections() { + std::vector> v; + v.push_back(source()); + + auto tmp = source(); + v.push_back(std::move(tmp)); + + sink(std::move(v[0])); + std::cout << *(v[0]) << '\n'; +} +``` + +
+ +___ + +#### `std::unique_ptr<>` cooperation with raw pointers + +```cpp +#include + +void legacyInterface(int*) {} +void deleteResource(int* p) { delete p; } +void referenceInterface(int&) {} + +int main() { + auto ptr = std::make_unique(5); + legacyInterface(ptr.get()); + deleteResource(ptr.release()); + ptr.reset(new int{10}); + referenceInterface(*ptr); + ptr.reset(); // ptr is a nullptr + return 0; +} +``` + +* get() – returns a raw pointer without releasing the ownership +* release() – returns a raw pointer and release the ownership +* reset() – replaces the manager object +* operator*() – dereferences pointer to the managed object + +___ + +### `std::make_unique()` + +```cpp +#include + +struct Msg { + Msg(int i) : value(i) {} + int value; +}; + +int main() { + auto ptr1 = std::unique_ptr(new Msg{5}); + auto ptr2 = std::make_unique(5); // equivalent to above + return 0; +} +``` + +`std::make_unique()` is a factory function that produce `unique_ptrs` + + +* added in C++14 for symmetrical operations on unique and shared pointers +* avoids bare new expression + +___ + +### `std::unique_ptr` + +```cpp +struct MyData {}; + +void processPointer(MyData* md) {} +void processElement(MyData md) {} + +using Array = std::unique_ptr; + +void use(void) +{ + Array tab{new MyData[42]}; + processPointer(tab.get()); + processElement(tab[13]); +} +``` + +* During destruction + * std::unique_ptr<T> calls delete + * std::unique_ptr<T[]> calls delete[] +* std::unique_ptr<T[]> has additional operator[] for accessing array element +* Usually std::vector<T> is a better choice + +___ + +## Exercise: Resource + +1. Compile and run Resource application +2. Check memory leaks under valgrind +3. Fix memory leaks with a proper usage of delete operator +4. Refactor the solution to use std::unique_ptr<> +5. Use std::make_unique() + +___ + +## Exercise: Converter + +1. Compile and run Converter application and check memory leaks under valgrind +2. Fix code using std::unique_ptr and std::make_unique +3. Find other issues and fix them (use good practise etc...) + +___ + +## Why virtual D'tor is so important (1)? + +```C++ +class Resource { +public: + explicit Resource(const std::string& str): str_(str) {} + + const std::string& str() const { + return str_; + } + +private: + std::string str_; +}; + +class Converter { +public: + Converter() { + std::cout << "C'tor converter\n"; + } + + virtual ~Converter() { + std::cout << "D'tor converter\n"; + } + + virtual void Convert(const std::unique_ptr& resource) const = 0; +}; + +class CurlyBracketConverter : public Converter { +public: + CurlyBracketConverter() { + std::cout << "C'tor CurlyBracketConverter\n"; + } + + ~CurlyBracketConverter() override { + std::cout << "D'tor CurlyBracketConverter\n"; + } + + void Convert(const std::unique_ptr& resource) const override { + std::cout << "{" << resource->str() << "}\n"; + } +}; + +class SquareBracketConverter : public Converter { +public: + SquareBracketConverter() { + std::cout << "C'tor SquareBracketConverter\n"; + } + + ~SquareBracketConverter() override { + std::cout << "D'tor SquareBracketConverter\n"; + } + + virtual void Convert(const std::unique_ptr& resource) const override{ + std::cout << "[" << resource->str() << "]\n"; + } +}; + +class Printer { +public: + explicit Printer(std::unique_ptr converter): converter_(std::move(converter)) {} + + void Print(const std::unique_ptr& resource) const { + converter_->Convert(resource); + } + +private: + std::unique_ptr converter_; +}; + +int main() { + auto resource = std::make_unique("Ala has a cat"); + Printer printer(std::make_unique()); + Printer printer2(std::make_unique()); + + return 0; +} +``` + + +___ + +## Why virtual D'tor is so important (2)? + +```C++ +C'tor converter +C'tor SquareBracketConverter +C'tor converter +C'tor CurlyBracketConverter +D'tor converter +D'tor converter +``` + + + + +Try to add virtual to your D'tor and check result + + + +```C++ +C'tor converter +C'tor SquareBracketConverter +C'tor converter +C'tor CurlyBracketConverter +D'tor CurlyBracketConverter +D'tor converter +D'tor SquareBracketConverter +D'tor converter +``` + + +___ + +## Custom Deleter + +* When there is a special way to delete object +* Type of unique_ptr change! + +
+
+ +```C++ +class Foo { +public: + Foo() { + std::cout << "Foo C'tor\n"; + } + + void print() const { + std::cout << "Foo!\n"; + } + +private: + // For some reason, we allow only this function to delete object + friend void deleteMe(Foo* const foo); + + ~Foo() { + std::cout << "Foo D'tor\n"; + } +}; + +void deleteMe(Foo* const foo) { + std::cout << "Delete object Foo!\n"; + delete foo; +} + +int main() { + // Can't use make unique, need to use unique_ptr C'tor + // unique_ptr(pointer __p, const deleter_type& __d) noexcept + std::unique_ptr ptr(new Foo, deleteMe); + ptr->print(); + + return 0; +} + +``` + + + +
+ +
+ + Output + +```C++ +Foo C'tor +Foo! +Delete object Foo! +Foo D'tor +``` + + + +
diff --git a/AdvancedCppV2/Presentation/smart_pointers_weak_ptr.md b/AdvancedCppV2/Presentation/smart_pointers_weak_ptr.md new file mode 100644 index 0000000..c50be6d --- /dev/null +++ b/AdvancedCppV2/Presentation/smart_pointers_weak_ptr.md @@ -0,0 +1,213 @@ + + +## Cyclic dependencies + +cyclic dependencies + +* Cyclic dependency is where you have class A with self-referencing member. +* Cyclic dependency is where you have two classes A and B where A has a reference to B which has a reference to A. +* How to fix it? + +___ + +### `std::weak_ptr<>` to the rescue + +* does not own an object +* observes only +* must be converted to std::shared_ptr<> to access the object +* can be created only from a std::shared_ptr<> + +
+ weak pointers +
+ +___ + +### `std::weak_ptr<>` usage + +
+
+ +```cpp +#include +#include + +struct Msg { int value; }; + +void checkMe(const std::weak_ptr & wp) { + std::shared_ptr p = wp.lock(); + if (p) + std::cout << p->value << '\n'; + else + std::cout << "Expired\n"; +} + +int main() { + auto sp = std::shared_ptr{new Msg{10}}; + auto wp = std::weak_ptr{sp}; + checkMe(wp); + sp.reset(); + checkMe(wp); +} +``` + +
+ +
+ +```bash +> ./a.out +10 +Expired +``` + +
+
+ +___ + +### `std::shared_ptr<>` cyclic dependencies + +* How to solve this problem? + +```cpp +#include + +struct Node { + std::shared_ptr child; + std::shared_ptr parent; +}; + +int main () { + auto root = std::shared_ptr(new Node); + auto child = std::shared_ptr(new Node); + root->child = child; + child->parent = root; +} +``` + +___ + +### Breaking cycle - solution + +* Use `std::weak_ptr` in one direction + +```cpp +#include +struct Node { + std::shared_ptr child; + std::weak_ptr parent; +}; + +int main () { + auto root = std::shared_ptr(new Node); + auto child = std::shared_ptr(new Node); + root->child = child; + child->parent = root; +} +``` + + +
+ +==148== All heap blocks were freed -- no leaks are possible + +
+ +___ + +### `std::weak_ptr<>` real life usage (1) + +```C++ +struct Image { + /* data */ +}; + +class Screen; + +class Downloader { +public: + void downloadImage(const std::string& url, std::function callback, std::weak_ptr weak_ptr) { + std::cout << "Start downloading!" << std::endl; + std::thread(&Downloader::download, this, url, callback, weak_ptr).detach(); + } + +private: + void download(const std::string& url, std::function callback, std::weak_ptr weak_ptr) { + // Simulate download process + std::cout << "Download in progress!" << std::endl; + std::this_thread::sleep_for(std::chrono::seconds(3)); + std::cout << "Download Finished!" << std::endl; + if (auto lock = weak_ptr.lock()) { + callback(Image{}); + } else { + std::cout << "Screen object expired!\n"; + } + } +}; + +class Screen : public std::enable_shared_from_this { +public: + Screen(Downloader* downloader) + : downloader_(downloader) {} + + void printImage(const std::string& url) { + std::cout << "Waiting for image download!" << std::endl; + downloader_->downloadImage( + url, [&](Image image) { onImageDownloaded(std::move(image)); }, weak_from_this()); + } + +private: + void onImageDownloaded(Image&& image) { + // Do some action on image + std::cout << "Got Image!\n"; + } + + Downloader* downloader_; +}; + +int main() { + auto downloader = std::make_unique(); + auto screen = std::make_shared(downloader.get()); + + screen->printImage("www.image.com/sth/special.img"); + std::this_thread::sleep_for(std::chrono::seconds(2)); + screen = nullptr; + std::this_thread::sleep_for(std::chrono::seconds(2)); +} +``` + + +___ + +### `std::weak_ptr<>` real life usage (2) + +Output: + +```Bash +Waiting for image download! +Start downloading! +Download in progress! +Download Finished! +Screen object expired! +``` + +When we delete line screen = nullptr; + +```Bash +Waiting for image download! +Start downloading! +Download in progress! +Download Finished! +Got Image! +``` + +___ + + +### `std::weak_ptr<>` real life usage (3) + +Use std::weak_ptr when: + +* Need to observe a lifetime of the object, without having an ownership +* Want to break cyclic dependencies diff --git a/AdvancedCppV2/Presentation/template_deduction_guides.md b/AdvancedCppV2/Presentation/template_deduction_guides.md new file mode 100644 index 0000000..6912c37 --- /dev/null +++ b/AdvancedCppV2/Presentation/template_deduction_guides.md @@ -0,0 +1,373 @@ +# Deduction guides +___ + +## Template deduction + +There are three different scenarios during template type deduction: + +* Handle by reference or pointer: T& or T* with or without const or volatile +* Handle by value: T with or without const or volatile +* Handle by universal reference: T&& can't use const or volatile here. + +___ + +## Pass by reference + +

+template <typename T>
+void function(T& arg) {}
+
+template <typename T>
+void constFunction(const T& arg) {}
+
+void foo(int) {}
+
+int main() {
+    int a = 4;
+    const int b = 5;
+    const int& c = a;
+    int arr[] = {1,2};
+
+    function(a);        // T -> int | arg -> int&
+    function(5);        // Not compile!
+    function(b);        // T -> const int | arg -> const int&
+    function(c);        // T -> const int | arg -> const int&
+    function(foo);      // T -> void(int) | arg -> void(&)(int)
+    function(arr);      // T -> int[2] | arg -> int(&)[2]
+    constFunction(a);   // T -> int | arg -> const int&
+    constFunction(5);   // T -> int | arg -> const int&
+    constFunction(b);   // T -> int | arg -> const int&
+    constFunction(c);   // T -> int | arg -> const int&
+    constFunction(foo); // T -> void(int) | arg -> const void(&)(int)
+    constFunction(arr); // T -> int[2] | arg -> const int(&)[2]
+}
+
+ + +___ + +## Pass by value + +

+template <typename T>
+void function(T arg) {}
+
+void foo(int) {}
+
+int main() {
+    int a = 4;
+    const int b = 5;
+    const int& c = a;
+    int arr[] = {1,2};
+    char name[] = "Mateusz";
+    const char* str = name;
+    const char* const ptr = name;
+
+    function(a);        // T -> int | arg -> int
+    function(5);        // T -> int | arg -> int
+    function(b);        // T -> int | arg -> int
+    function(c);        // T -> int | arg -> int
+    function(foo);      // T -> void(*)(int) | arg -> void(*)(int))
+    function(arr);      // T -> int* | arg -> int*
+    function(str);      // T -> const char* | arg -> const char*
+    function(ptr);      // T -> const char* | arg -> const char*
+}
+
+ + +___ + +## Pass by universal reference + +

+template <typename T>
+void function(T&& arg) {}
+
+void foo(int) {}
+
+int main() {
+    int a = 4;
+    const int b = 5;
+    const int& c = a;
+    int arr[] = {1,2};
+    char name[] = "Mateusz";
+    const char cstr[] = "Mateusz";
+    const char* str = name;
+    const char* const ptr = name;
+
+    function(a);              // T -> int& | arg -> int&
+    function(5);              // T -> int | arg -> int&&
+    function(b);              // T -> const int& | arg -> const int&
+    function(c);              // T -> const int& | arg -> const int&
+    function(foo);            // T -> void(&)(int) | arg -> void(&)(int))
+    function(arr);            // T -> int(&)[2] | arg -> int(&)[2]
+    function(cstr);           // T -> const char(&)[8] | arg -> const char(&)[8]
+    function(str);            // T -> const char(*&) | arg -> const char(*&)
+    function(std::move(str)); // T -> const char(*) | arg -> const char(*&&)
+    function(ptr);            // T -> const char(*const &) | arg -> const char(*const &)
+}
+
+ + +___ + +## Pass by universal reference - special treatment + +When template parameter gets argument by universal reference, deducted type `T` doesn't remove the reference for `l-values`. +In other words: `r-values` are treated as they are passed by value, but `l-values` are treated as a reference. + +This is partially true. Scott Meyers said this is an abstraction layer. The real truth is reference collapsing: + +* T& & -> T& +* T& && -> T& +* T&& & -> T& +* T&& && -> T&& + +___ + +## auto deduction + +`auto` deduction works similar to templates, but there is one exception, which you should remember from previous slajds. + +
+
+ +```C++ +auto val = 5; +``` +is equal to + +```C++ +template +void foo(T val); +``` +
+ +
+ +```C++ +const auto& val = 5; +``` +is equal to + +```C++ +template +void foo(const T& val); +``` +
+ +
+ +```C++ +auto&& val = 5; +``` +is equal to + +```C++ +template +void foo(T&& val); +``` +
+ +
+___ + +## auto deduction - one exception + +```C++ +template +void foo(T t) {} + +auto val = {1, 2, 3, 4}; // std::initializer_list +foo({1, 2, 3, 4}); // deduction failed! +``` + +Need to explicity use `initializer_list` + + +```C++ +template +void foo(std::initializer_list t) {} + +auto val = {1, 2, 3, 4}; // std::initializer_list +foo({1, 2, 3, 4}); // std::initializer_list +``` + +___ + +## auto in generic lambda + +In generic lambda `auto` uses the same deduction rules like for templates not for `auto`! This happens because, lambda is struct, so generic lambda is a template structure. + +
+ +```C++ +auto lambda = [](auto&& first, const auto& second, auto third) {} +``` +is equal to + +```C++ +struct Lmabda { + template + auto operator()(X&& x, const Y& y, Z z) const { + + } +}; +``` +
+ + +___ + +## std::forward once more + +If we want to perfect forward some value in template you will write: + + +```C++ +template +void fun(T&& t) { + other(std::forward(t)); +} +``` + +But how to do this in lambda? We know that generic lambda is a teplate, but we don't have an access to `T`! + + +```C++ +auto lambda = [](auto&& t) { + other(std::forward(t)); +}; +``` + +___ + +## decltype + +Decltype return a type of variable, without removing `references` or `const`/ `volatile` qualifiers + +```C++ +int x = 5; +decltype(x) y; // int + +const int num = 20; +decltype(num) num2 = 30; // const int + +const int& ref = num; +decltype(ref) ref2 = x; // const int& + +const char name[] = "Mateusz"; +decltype(name) name2 = "Scott"; // const char[] + +decltype(foo) fun; // void fun(int, const string& + +auto pred = [](int num){ return num % 1 == 0; }; +decltype(pred(20)) val; // bool + +std::vector vec{1}; +decltype(vec.begin()) it; // std::vector::iterator +decltype(vec[0]) // int& +``` + + +___ + +## decltype - one problem + +What is wrong with this snippet of code? + +```C++ +void authorize() {} + +template +auto authorizeAndAccess(C& container, size_t index) { + authorize(); + return container[index]; +} + +int main() { + std::vector vec{1,2,3}; + authorizeAndAccess(vec, 2) = 10; + std::cout << vec[2] << '\n'; +} +``` + + +```C++ +error: lvalue required as left operand of assignment authorizeAndAccess(vec, 2) = 10; +``` + + +___ + +## decltype - partial solution + +The same result we can achieve by using `decltype(auto)`. + + +```C++ +void authorize() {} + +template +auto authorizeAndAccess(C& container, size_t index) -> decltype(container[index]) { + authorize(); + return container[index]; +} + +int main() { + std::vector vec{1,2,3}; + authorizeAndAccess(vec, 2) = 10; + std::cout << vec[2] << '\n'; +} +``` + + +___ + +## decltype - when solution make another trouble + +What is wrong now? + + +```C++ +void authorize() {} + +template +decltype(auto) authorizeAndAccess(C& container, size_t index) { + authorize(); + return container[index]; +} + +int main() { + const auto res = authorizeAndAccess(std::vector{5, 8, 12, 16}, 2); + std::cout << std::boolalpha << "res: " << res << '\n'; +} +``` + + +```C++ +cannot bind non-const lvalue reference of type ‘std::vector&’ to an rvalue of type ‘std::vector’ +const auto res = authorizeAndAccess(std::vector{5, 8, 12, 16}, 2); +``` + + + +___ + +## decltype - final fix + +```C++ +void authorize() {} + +template +decltype(auto) authorizeAndAccess(C&& container, size_t index) { + authorize(); + return std::forward(container)[index]; +} + +int main() { + const auto res = authorizeAndAccess(std::vector{5, 8, 12, 16}, 2); + std::cout << std::boolalpha << "res: " << res << '\n'; // will print 12 +} +``` + \ No newline at end of file diff --git a/AdvancedCppV2/Presentation/templates_basic.md b/AdvancedCppV2/Presentation/templates_basic.md new file mode 100644 index 0000000..ccb8f0a --- /dev/null +++ b/AdvancedCppV2/Presentation/templates_basic.md @@ -0,0 +1,257 @@ +# Template functions + +___ + +## Examples + +Let's assume that we have a function below: + +```c++ +int add(int first, int second) { + return first + second; +} +``` + +If we want to have a function that takes doubles as well, we need to write: + + +```c++ +double add(double first, double second) { + return first + second; +} +``` + + +And if we want a function that can take complex or any other numbers we would need to write: + + +```c++ +std::complex add(std::complex first, std::complex second) { + return first + second; +} +``` + + +You can clearly see that we have a code duplication here. + + +___ + +## Avoiding code duplication + +Instead of writing so many functions we can have only one - template function: + +```c++ +template +Type add(Type first, Type second) { + return first + second; +} +``` + + +Instead of `Type`, you can have any name you wish. Typically you will see just `T` as a typename, but it is better to have a longer name than only one character, especially, when there is more than only one template parameter. Now, you can use this function like this: + + +```c++ +auto resultI = add(4, 5); // resultI type is int +auto resultD = add(4.0, 5.0); // resultD type is double +auto resultC = add>({1, 2}, {2, 3}); // resultC type is std::complex +``` + + +You can play with the code [here](https://ideone.com/fork/NU0L8k) + + +___ + +## Function template type deduction + +There is a function template types deduction in C++. It means that you can skip part with angle braces `<>` and write previous example like this: + +```c++ +auto resultI = add(4, 5); // resultI type is int +auto resultD = add(4.0, 5.0); // resultD type is double +auto resultC = add({1, 2}, {2, 3}); // error, does not compile +``` + +`resultC` will not compile, because in this case compiler will not know what is the type of `{1, 2}` or `{2, 3}`. `std::initializer_list` can never be a result of parameter type deduction in templates. +In this case we have to type it explicitly: + + +```c++ +auto resultC = add(std::complex{1, 2}, std::complex{2, 3}); +``` + + +or + + +```c++ +auto resultC = add>({1, 2}, {2, 3}); +``` + + +___ + +## Exercise + +Write a function that creates `std::complex` number from two provided numbers. If the types of numbers are different, it should create `std::complex` of the first parameter. Usage: + +```c++ +std::complex a = makeComplex(4, 5); // both ints +std::complex b = makeComplex(3.0, 2.0); // both doubles +std::complex c = makeComplex(1, 5.0); // int, double -> takes int +``` + +___ + + +## Multiple template parameters + +The compiler itself deduce which template function parameters should be used. However, if you write the code like this: + +```c++ +auto resultC = add(4, 5.0); // error: int + double +``` + + +We will have a compilation error. The compiler will not deduce parameter, because our template function takes only one type, and both parameters have to be of the same type. We can fix this by adding a new version of the template of add function. + + +```c++ +template +TypeA add(TypeA first, TypeB second) { + return first + second; +} +``` + + +Now the code should work: + + +```c++ +auto resultC = add(4, 5.0); // resultC type is int +``` + + +The output type is the same as the first argument type because it was defined in the template function above as `TypeA`. + + +___ + +## `typeid` + +Generally, you can freely use template types inside functions. For example, you can create new variables of provided types: + +```cpp +#include + +template +void showType() { + T value; + std::cout << "Type: " << typeid(value).name() << std::endl; +} +``` + + +You can use `typeid().name()` to print variable type. You need to include the `typeinfo` header for this. The output is implementation-defined. + + +You can also notice, that instead of the `typename` keyword, you can also use the `class` keyword. They are interchangeable. + + +```cpp +template == template != template +``` + + +___ + + +## No matching function + +In previous case if you want to use `showType()` function without providing explicit templates, the code will not compile: + +```c++ +int main() { + showType(); + return 0; +} +``` + +```bash +prog.cpp: In function ‘int main()’: +prog.cpp:15:12: error: no matching function for call to showType()’ + showType(); + ^ +prog.cpp:7:6: note: candidate: template void showType() + void showType() + ^~~~~~~~~ +prog.cpp:7:6: note: template argument deduction/substitution failed: +prog.cpp:15:12: note: couldn't deduce template parameter ‘T’ + showType(); +``` + +___ + +## Template function parameter type deduction + +The compiler cannot deduce parameters, because the functions do not take any parameters. You need to provide the type explicitly: + +
+ +
+ +```c++ +int main() { + showType(); + return 0; +} +``` + +
+ +or + +
+ +```c++ +int main() { + showType>(); + return 0; +} +``` + +
+ +
+ + +You can also play with the code [here](https://ideone.com/fork/oZZybw) + + +___ + +## STL example + +```cpp +template +InputIt find_if(InputIt first, InputIt last, UnaryPredicate p) +{ + for(; first != last; ++first) { + if(p(*first)) { + return first; + } + } + return last; +} +``` + +```cpp +std::vector> v{{-3, 1}, {2, 3}, {4, -5}}; +auto it = std::find_if(begin(v), end(v), [](auto& e){ return e.first == 2; }); +if(it != std::end(v)) { + /* ... */ +} +``` + diff --git a/AdvancedCppV2/Presentation/templates_class.md b/AdvancedCppV2/Presentation/templates_class.md new file mode 100644 index 0000000..9967fb4 --- /dev/null +++ b/AdvancedCppV2/Presentation/templates_class.md @@ -0,0 +1,99 @@ +# Template classes + +___ + +## Template class example + +Template classes are as well used to avoid code duplication, as to create so-called meta-programs within them. Here is an example of a simple template class and its usage: + + +```c++ +#include + +template +class SomeClass { +public: + T getValue() { return value; } +private: + T value = {}; + U* ptr = nullptr; +}; + +int main() { + SomeClass sc; + std::cout << sc.getValue() << std::endl; + return 0; +} +``` + + +___ + +## Template classes in STL + +Template classes are heavily used in STL. For example `std::vector`, `std::list` and other containers are template classes and if you want to use them, you do it like here: + + +```c++ +std::vector v = {1, 2, 3}; +std::list l{'c', 'd', 'b'}; +``` + + +___ + + +## Template type deduction for classes (C++17) + +Template types can also be automatically deduced by the compiler thanks to... template functions. + + +The compiler uses class constructors to achieve that. + + +From C++17 you can write a code like this: + + +```c++ +std::vector v = {1, 2, 3}; // std::vector is deduced +std::list l{'c', 'd', 'b'}; // std::list is deduced +``` + + +That's not gonna work: + + +```cpp +// std::vector v1; // compilation error, vector of what? +// std::vector v2(10) // compilation error, 10 elements of what? +// clang error: no viable constructor or deduction guide for deduction of +// template arguments of 'vector' +// g++ error: class template argument deduction failed: +// no matching function for call to 'vector()' +``` + + +___ + +## Exercise - `VectorMap` + +Write a template class `VectorMap` that represents an over-engineered `std::map`. + +Inside, it should hold 2 `std::vectors` of the same size, each with different types. The first vector should hold keys, the other one values. + +Elements at the same position in both vectors should create a pair like `1` and `'c'` below. + +```c++ +VectorMap map; +map.insert(1, 'c'); +map[1] = 'e'; // replaces value under 1 +std::cout << map[1]; // prints 'e' +map.at(2); // throw std::out_of_range +``` + +Implement the mentioned above `insert()`, `operator[]`, `at()` methods. + +Do not bother about duplicated keys for now. +You can also try to implement additional methods from the `std::map` interface 🙂 + +Use [cppreference](http://en.cppreference.com/w/cpp/container/map). diff --git a/AdvancedCppV2/Presentation/templates_knowledge_check.md b/AdvancedCppV2/Presentation/templates_knowledge_check.md new file mode 100644 index 0000000..cc22eb1 --- /dev/null +++ b/AdvancedCppV2/Presentation/templates_knowledge_check.md @@ -0,0 +1,95 @@ + + +# Templates +___ + +## Knowledge check + +### Template type deduction + +

+template <typename T>
+void copy(T arg) {}
+
+template <typename T>
+void reference(T& arg) {}
+
+template <typename T>
+void universal_reference(T&& arg) {}
+
+int main() {
+    int number = 4;
+    copy(number);       // int
+    copy(5);            // int
+    reference(number);  // int&
+    reference(5);       // candidate function [with T = int] not viable: expects an l-value for 1st argument
+    universal_reference(number);            // int&
+    universal_reference(std::move(number)); // int&&
+    universal_reference(5);                 // int&&
+}
+
+ +___ + +## Knowledge check + +```cpp +void foo(int && a); // r +void foo(int & a); // l + +int a = 5; +``` + +Which of above functions will be called by below snippets? + +* foo(4); + * r +* foo(a); + * l +* foo(std::move(a)); + * r +* foo(std::move(4)); + * r (move is redundant) + +___ + +## Knowledge check + +```cpp +template +void foo(T && a); // r + +template +void foo(T & a); // l + +int a = 5; +``` + +Which of above functions will be called by below snippets? + +* foo(4); + * r +* foo(a); + * l +* foo(std::move(a)); + * r + +___ + +## Knowledge check + +```cpp +template +void foo(T && a); // r + +int a = 5; +``` + +What will happen now? + +* foo(4); + * r +* foo(a); + * r +* foo(std::move(a)); + * r diff --git a/AdvancedCppV2/Presentation/templates_partial_spec.md b/AdvancedCppV2/Presentation/templates_partial_spec.md new file mode 100644 index 0000000..12ba203 --- /dev/null +++ b/AdvancedCppV2/Presentation/templates_partial_spec.md @@ -0,0 +1,66 @@ +# Partial specialization +___ + +## Template function partial specialization + +In C++ we cannot partially specialize functions. + +___ + + +## Template class partial specialization + +In C++ we can specialize classes partially. It means that we need to leave at least one template parameter. + +```cpp +// primary template +template +class A {}; + +// partial specialization with T1 = int +template +class A {}; + +// partial specialization with T1 = int and T2 = double +template +class A {}; + +// partial specialization with T1 = int and T3 = char +template +class A {}; + +// full specialization with T1 = T2 = double and T3 = int +template <> +class A {}; +``` + +___ + + +## Advanced partial specialization + +```cpp +template +class A {}; // primary template + +template +class A {}; // #1: partial specialization where T2 is a pointer to T1 + +template +class A {}; // #2: partial specialization where T1 is a pointer + +template +class A {}; // #3: partial specialization where T1 is int, I is double, + // and T2 is a pointer + +template +class A {}; // #4: partial specialization where T2 is a pointer +``` + +___ + +## Exercise + +Write a partial specialization of `VectorMap` for boolean keys. We can have only 2 values for boolean keys. There is no need to keep vectors inside. + +Implement properly all currently available functions. diff --git a/AdvancedCppV2/Presentation/templates_specjalization.md b/AdvancedCppV2/Presentation/templates_specjalization.md new file mode 100644 index 0000000..e80756c --- /dev/null +++ b/AdvancedCppV2/Presentation/templates_specjalization.md @@ -0,0 +1,146 @@ +# Specialization + +___ + + +## Function specialization + +If we want to have the same function name, but we want our code to behave differently for some types, we can create a specialization. + + +```cpp +//generic function +template +void print(T arg) { + std::cout << arg << '\n'; +} +``` + + +```cpp +// specialization for `T = double` +template <> +void print(double arg) { + std::cout << std::setprecision(10) << arg << '\n'; +} +``` + + +```cpp +// better: overload +void print(double arg) { + std::cout << std::setprecision(10) << arg << '\n'; +} +``` + + +Tip: do not use function specializations. Always prefer function overloads. + + +Template function specializations do not take part in overload resolution. Only the exact type match is considered. + + +Above specialization does not work for `float`. Overload does. + +___ + +## Class specialization + +A class can have not only different behaviour (different methods implementations) but also different layouts. You can have completely different fields and/or their values. + + +___ + + +## Specialization example #1 - methods + +```c++ +#include + +template // primary template +struct is_int { + bool get() const { return false; } +}; + +template<> // explicit specialization for T = int +struct is_int { + bool get() const { return true; } +}; + + +int main() { + is_int iic; + is_int iii; + std::cout << iic.get() << '\n'; // prints 0 (false) + std::cout << iii.get() << '\n'; // prints 1 (true) + return 0; +} +``` + + +___ + + +## Specialization example #2 - field values + +```c++ +#include + +template // primary template +struct is_int { + static constexpr bool value = false; +}; + +template<> // explicit specialization for T = int +struct is_int { + static constexpr bool value = true; +}; + + +int main() { + std::cout << is_int::value << '\n'; // prints 0 (false) + std::cout << is_int::value << '\n'; // prints 1 (true) + return 0; +} +``` + + +You can play with the code [here](https://ideone.com/fork/LEIx7e) + +___ + + +## Specialization example #3 - <type_traits> + +To achieve the last behavior, we can use `std::false_type` and `std::true_type`. The below code is equivalent to the one from the previous example. + +```c++ +#include +using namespace std; + +template // primary template +struct is_int : std::false_type +{}; + +template<> // explicit specialization for T = int +struct is_int : std::true_type +{}; + +int main() { + std::cout << is_int::value << std::endl; // prints 0 (false) + std::cout << is_int::value << std::endl; // prints 1 (true) + return 0; +} +``` + +The interactive version of this code is [here](https://ideone.com/fork/GaTh0B) + +___ + +### Exercise - `is_int_key` + +In `VectorMap` write a class constant `is_int_key` that holds a boolean value. It should be `true` when the key is `int` and `false` otherwise. + +Generally, it should do the same job as the `isIntKey()` method, but we want to have it available even without having an object. + +Take a look in the `` library for that. It should be useful 🙂 diff --git a/AdvancedCppV2/Presentation/templates_typetraits.md b/AdvancedCppV2/Presentation/templates_typetraits.md new file mode 100644 index 0000000..3ffba5d --- /dev/null +++ b/AdvancedCppV2/Presentation/templates_typetraits.md @@ -0,0 +1,66 @@ +# `` + +___ + +## Constraints + +`` library is used to examine type properties. It is usually used in templates to gain some knowledge about provided types. + + +We can for example constrain our templates to work only with some specific types. The common practice is using it together with `static_assert`. + + +```cpp +#include + +template +class Choice { + static_assert(std::is_enum::value, "You need to provide an enum"); + + E choice; +public: + Choice(E arg) { /* ... */ } +}; +``` + + +___ + +## [`` on cppreference](https://en.cppreference.com/w/cpp/types#Type_traits) + +___ + +## Advanced constraints + +* [SFINAE](https://en.cppreference.com/w/cpp/language/sfinae) +* [`constexpr if`](https://en.cppreference.com/w/cpp/language/if#Constexpr_if) +* [named requirements](https://en.cppreference.com/w/cpp/named_req) (C++20) +* [`concept`](https://en.cppreference.com/w/cpp/concepts) (C++20) + +```cpp +template +concept copy_constructible = + std::move_constructible && + std::constructible_from && std::convertible_to && + std::constructible_from && std::convertible_to && + std::constructible_from && std::convertible_to; +``` + + +___ + +## Exercise - `static_assert` + +Add a constraint to our `VectorMap`. + +Do not allow to create an object when `ValueType` does not have a default constructor. + +Use `static_assert` and proper trait from [``](https://en.cppreference.com/w/cpp/types#Type_traits) library. + +Check if it works properly. + +## Exercise - `isIntKey()` + +Write a function `isIntKey()` in `VectorMap`. It should return `true` when the KeyType is `int` and `false` otherwise. + +Check the [``](https://en.cppreference.com/w/cpp/types#Type_traits) library for some inspiration 🙂 diff --git a/AdvancedCppV2/Presentation/templates_variable.md b/AdvancedCppV2/Presentation/templates_variable.md new file mode 100644 index 0000000..68cbb2a --- /dev/null +++ b/AdvancedCppV2/Presentation/templates_variable.md @@ -0,0 +1,66 @@ +# Variable templates (C++17) +___ + +## Why? + +Eg. different precision + + +```cpp +template +constexpr T pi = T(3.1415926535897932385L); + +template +T circular_area(T r) { return pi * r * r; } +``` + + +But it is really rarely used. + + +___ + + +## Specialization example #2 - field values + +Remember this code? + + +```c++ [] +#include + +template // primary template +struct is_int { + static constexpr bool value = false; +}; + +template<> // explicit specialization for T = int +struct is_int { + static constexpr bool value = true; +}; + +template +constexpr bool is_int_v = is_int::value; + +int main() { + std::cout << is_int_v << '\n'; // prints 0 (false) + std::cout << is_int_v << '\n'; // prints 1 (true) + return 0; +} +``` + + +We mainly use template variables as helpers to class template field values. + + +___ + +Check out [`type_traits` on cppreference.com](https://en.cppreference.com/w/cpp/header/type_traits) + +Every trait has a corresponding helper variable template. + +___ + +## Exercise + +Write a variable template `is_int_key_v`. It should return a value of the `is_int_key` field in a given template type. diff --git a/AdvancedCppV2/README.md b/AdvancedCppV2/README.md new file mode 100644 index 0000000..d7e1e31 --- /dev/null +++ b/AdvancedCppV2/README.md @@ -0,0 +1,16 @@ +# AdvancedCpp + +## Run presentation + +in main directory: +- npm install +- npm start + +Run you browser on localhost. eg: http://localhost:8000/ + +## Navigation through presentation: + +- space -> next info +- arrow up -> next info +- arrow down -> prev info +- esc go to preview diff --git a/AdvancedCppV2/bower.json b/AdvancedCppV2/bower.json new file mode 100644 index 0000000..bc825ab --- /dev/null +++ b/AdvancedCppV2/bower.json @@ -0,0 +1,24 @@ +{ + "name": "reveal.js", + "version": "3.9.2", + "main": [ + "js/reveal.js", + "css/reveal.css" + ], + "homepage": "http://revealjs.com", + "license": "MIT", + "description": "The HTML Presentation Framework", + "authors": [ + "Hakim El Hattab " + ], + "repository": { + "type": "git", + "url": "git://github.com/hakimel/reveal.js.git" + }, + "ignore": [ + "**/.*", + "node_modules", + "bower_components", + "test" + ] +} \ No newline at end of file diff --git a/AdvancedCppV2/css/print/paper.css b/AdvancedCppV2/css/print/paper.css new file mode 100644 index 0000000..27d19dd --- /dev/null +++ b/AdvancedCppV2/css/print/paper.css @@ -0,0 +1,203 @@ +/* Default Print Stylesheet Template + by Rob Glazebrook of CSSnewbie.com + Last Updated: June 4, 2008 + + Feel free (nay, compelled) to edit, append, and + manipulate this file as you see fit. */ + + +@media print { + + /* SECTION 1: Set default width, margin, float, and + background. This prevents elements from extending + beyond the edge of the printed page, and prevents + unnecessary background images from printing */ + html { + background: #fff; + width: auto; + height: auto; + overflow: visible; + } + body { + background: #fff; + font-size: 20pt; + width: auto; + height: auto; + border: 0; + margin: 0 5%; + padding: 0; + overflow: visible; + float: none !important; + } + + /* SECTION 2: Remove any elements not needed in print. + This would include navigation, ads, sidebars, etc. */ + .nestedarrow, + .controls, + .fork-reveal, + .share-reveal, + .state-background, + .reveal .progress, + .reveal .backgrounds, + .reveal .slide-number { + display: none !important; + } + + /* SECTION 3: Set body font face, size, and color. + Consider using a serif font for readability. */ + body, p, td, li, div { + font-size: 20pt!important; + font-family: Georgia, "Times New Roman", Times, serif !important; + color: #000; + } + + /* SECTION 4: Set heading font face, sizes, and color. + Differentiate your headings from your body text. + Perhaps use a large sans-serif for distinction. */ + h1,h2,h3,h4,h5,h6 { + color: #000!important; + height: auto; + line-height: normal; + font-family: Georgia, "Times New Roman", Times, serif !important; + text-shadow: 0 0 0 #000 !important; + text-align: left; + letter-spacing: normal; + } + /* Need to reduce the size of the fonts for printing */ + h1 { font-size: 28pt !important; } + h2 { font-size: 24pt !important; } + h3 { font-size: 22pt !important; } + h4 { font-size: 22pt !important; font-variant: small-caps; } + h5 { font-size: 21pt !important; } + h6 { font-size: 20pt !important; font-style: italic; } + + /* SECTION 5: Make hyperlinks more usable. + Ensure links are underlined, and consider appending + the URL to the end of the link for usability. */ + a:link, + a:visited { + color: #000 !important; + font-weight: bold; + text-decoration: underline; + } + /* + .reveal a:link:after, + .reveal a:visited:after { + content: " (" attr(href) ") "; + color: #222 !important; + font-size: 90%; + } + */ + + + /* SECTION 6: more reveal.js specific additions by @skypanther */ + ul, ol, div, p { + visibility: visible; + position: static; + width: auto; + height: auto; + display: block; + overflow: visible; + margin: 0; + text-align: left !important; + } + .reveal pre, + .reveal table { + margin-left: 0; + margin-right: 0; + } + .reveal pre code { + padding: 20px; + border: 1px solid #ddd; + } + .reveal blockquote { + margin: 20px 0; + } + .reveal .slides { + position: static !important; + width: auto !important; + height: auto !important; + + left: 0 !important; + top: 0 !important; + margin-left: 0 !important; + margin-top: 0 !important; + padding: 0 !important; + zoom: 1 !important; + + overflow: visible !important; + display: block !important; + + text-align: left !important; + -webkit-perspective: none; + -moz-perspective: none; + -ms-perspective: none; + perspective: none; + + -webkit-perspective-origin: 50% 50%; + -moz-perspective-origin: 50% 50%; + -ms-perspective-origin: 50% 50%; + perspective-origin: 50% 50%; + } + .reveal .slides section { + visibility: visible !important; + position: static !important; + width: auto !important; + height: auto !important; + display: block !important; + overflow: visible !important; + + left: 0 !important; + top: 0 !important; + margin-left: 0 !important; + margin-top: 0 !important; + padding: 60px 20px !important; + z-index: auto !important; + + opacity: 1 !important; + + page-break-after: always !important; + + -webkit-transform-style: flat !important; + -moz-transform-style: flat !important; + -ms-transform-style: flat !important; + transform-style: flat !important; + + -webkit-transform: none !important; + -moz-transform: none !important; + -ms-transform: none !important; + transform: none !important; + + -webkit-transition: none !important; + -moz-transition: none !important; + -ms-transition: none !important; + transition: none !important; + } + .reveal .slides section.stack { + padding: 0 !important; + } + .reveal section:last-of-type { + page-break-after: avoid !important; + } + .reveal section .fragment { + opacity: 1 !important; + visibility: visible !important; + + -webkit-transform: none !important; + -moz-transform: none !important; + -ms-transform: none !important; + transform: none !important; + } + .reveal section img { + display: block; + margin: 15px 0px; + background: rgba(255,255,255,1); + border: 1px solid #666; + box-shadow: none; + } + + .reveal section small { + font-size: 0.8em; + } + +} diff --git a/AdvancedCppV2/css/print/pdf.css b/AdvancedCppV2/css/print/pdf.css new file mode 100644 index 0000000..bf96ed1 --- /dev/null +++ b/AdvancedCppV2/css/print/pdf.css @@ -0,0 +1,165 @@ +/** + * This stylesheet is used to print reveal.js + * presentations to PDF. + * + * https://github.com/hakimel/reveal.js#pdf-export + */ + +* { + -webkit-print-color-adjust: exact; +} + +body { + margin: 0 auto !important; + border: 0; + padding: 0; + float: none !important; + overflow: visible; +} + +html { + width: 100%; + height: 100%; + overflow: visible; +} + +/* Remove any elements not needed in print. */ +.nestedarrow, +.reveal .controls, +.reveal .progress, +.reveal .playback, +.reveal.overview, +.fork-reveal, +.share-reveal, +.state-background { + display: none !important; +} + +h1, h2, h3, h4, h5, h6 { + text-shadow: 0 0 0 #000 !important; +} + +.reveal pre code { + overflow: hidden !important; + font-family: Courier, 'Courier New', monospace !important; +} + +ul, ol, div, p { + visibility: visible; + position: static; + width: auto; + height: auto; + display: block; + overflow: visible; + margin: auto; +} +.reveal { + width: auto !important; + height: auto !important; + overflow: hidden !important; +} +.reveal .slides { + position: static; + width: 100% !important; + height: auto !important; + zoom: 1 !important; + pointer-events: initial; + + left: auto; + top: auto; + margin: 0 !important; + padding: 0 !important; + + overflow: visible; + display: block; + + perspective: none; + perspective-origin: 50% 50%; +} + +.reveal .slides .pdf-page { + position: relative; + overflow: hidden; + z-index: 1; + + page-break-after: always; +} + +.reveal .slides section { + visibility: visible !important; + display: block !important; + position: absolute !important; + + margin: 0 !important; + padding: 0 !important; + box-sizing: border-box !important; + min-height: 1px; + + opacity: 1 !important; + + transform-style: flat !important; + transform: none !important; +} + +.reveal section.stack { + position: relative !important; + margin: 0 !important; + padding: 0 !important; + page-break-after: avoid !important; + height: auto !important; + min-height: auto !important; +} + +.reveal img { + box-shadow: none; +} + +.reveal .roll { + overflow: visible; + line-height: 1em; +} + +/* Slide backgrounds are placed inside of their slide when exporting to PDF */ +.reveal .slide-background { + display: block !important; + position: absolute; + top: 0; + left: 0; + width: 100%; + height: 100%; + z-index: auto !important; +} + +/* Display slide speaker notes when 'showNotes' is enabled */ +.reveal.show-notes { + max-width: none; + max-height: none; +} +.reveal .speaker-notes-pdf { + display: block; + width: 100%; + height: auto; + max-height: none; + top: auto; + right: auto; + bottom: auto; + left: auto; + z-index: 100; +} + +/* Layout option which makes notes appear on a separate page */ +.reveal .speaker-notes-pdf[data-layout="separate-page"] { + position: relative; + color: inherit; + background-color: transparent; + padding: 20px; + page-break-after: always; + border: 0; +} + +/* Display slide numbers when 'slideNumber' is enabled */ +.reveal .slide-number-pdf { + display: block; + position: absolute; + font-size: 14px; +} diff --git a/AdvancedCppV2/css/reset.css b/AdvancedCppV2/css/reset.css new file mode 100644 index 0000000..e238539 --- /dev/null +++ b/AdvancedCppV2/css/reset.css @@ -0,0 +1,30 @@ +/* http://meyerweb.com/eric/tools/css/reset/ + v4.0 | 20180602 + License: none (public domain) +*/ + +html, body, div, span, applet, object, iframe, +h1, h2, h3, h4, h5, h6, p, blockquote, pre, +a, abbr, acronym, address, big, cite, code, +del, dfn, em, img, ins, kbd, q, s, samp, +small, strike, strong, sub, sup, tt, var, +b, u, i, center, +dl, dt, dd, ol, ul, li, +fieldset, form, label, legend, +table, caption, tbody, tfoot, thead, tr, th, td, +article, aside, canvas, details, embed, +figure, figcaption, footer, header, hgroup, +main, menu, nav, output, ruby, section, summary, +time, mark, audio, video { + margin: 0; + padding: 0; + border: 0; + font-size: 100%; + font: inherit; + vertical-align: baseline; +} +/* HTML5 display-role reset for older browsers */ +article, aside, details, figcaption, figure, +footer, header, hgroup, main, menu, nav, section { + display: block; +} \ No newline at end of file diff --git a/AdvancedCppV2/css/reveal.css b/AdvancedCppV2/css/reveal.css new file mode 100644 index 0000000..b4bc4fd --- /dev/null +++ b/AdvancedCppV2/css/reveal.css @@ -0,0 +1,1606 @@ +/*! + * reveal.js + * http://revealjs.com + * MIT licensed + * + * Copyright (C) 2020 Hakim El Hattab, http://hakim.se + */ +/********************************************* + * GLOBAL STYLES + *********************************************/ +html { + width: 100%; + height: 100%; + height: 100vh; + height: calc( var(--vh, 1vh) * 100); + overflow: hidden; } + +body { + height: 100%; + overflow: hidden; + position: relative; + line-height: 1; + margin: 0; + background-color: #fff; + color: #000; } + +/********************************************* + * VIEW FRAGMENTS + *********************************************/ +.reveal .slides section .fragment { + opacity: 0; + visibility: hidden; + transition: all .2s ease; } + .reveal .slides section .fragment.visible { + opacity: 1; + visibility: inherit; } + +.reveal .slides section .fragment.grow { + opacity: 1; + visibility: inherit; } + .reveal .slides section .fragment.grow.visible { + -webkit-transform: scale(1.3); + transform: scale(1.3); } + +.reveal .slides section .fragment.shrink { + opacity: 1; + visibility: inherit; } + .reveal .slides section .fragment.shrink.visible { + -webkit-transform: scale(0.7); + transform: scale(0.7); } + +.reveal .slides section .fragment.zoom-in { + -webkit-transform: scale(0.1); + transform: scale(0.1); } + .reveal .slides section .fragment.zoom-in.visible { + -webkit-transform: none; + transform: none; } + +.reveal .slides section .fragment.fade-out { + opacity: 1; + visibility: inherit; } + .reveal .slides section .fragment.fade-out.visible { + opacity: 0; + visibility: hidden; } + +.reveal .slides section .fragment.semi-fade-out { + opacity: 1; + visibility: inherit; } + .reveal .slides section .fragment.semi-fade-out.visible { + opacity: 0.5; + visibility: inherit; } + +.reveal .slides section .fragment.strike { + opacity: 1; + visibility: inherit; } + .reveal .slides section .fragment.strike.visible { + text-decoration: line-through; } + +.reveal .slides section .fragment.fade-up { + -webkit-transform: translate(0, 40px); + transform: translate(0, 40px); } + .reveal .slides section .fragment.fade-up.visible { + -webkit-transform: translate(0, 0); + transform: translate(0, 0); } + +.reveal .slides section .fragment.fade-down { + -webkit-transform: translate(0, -40px); + transform: translate(0, -40px); } + .reveal .slides section .fragment.fade-down.visible { + -webkit-transform: translate(0, 0); + transform: translate(0, 0); } + +.reveal .slides section .fragment.fade-right { + -webkit-transform: translate(-40px, 0); + transform: translate(-40px, 0); } + .reveal .slides section .fragment.fade-right.visible { + -webkit-transform: translate(0, 0); + transform: translate(0, 0); } + +.reveal .slides section .fragment.fade-left { + -webkit-transform: translate(40px, 0); + transform: translate(40px, 0); } + .reveal .slides section .fragment.fade-left.visible { + -webkit-transform: translate(0, 0); + transform: translate(0, 0); } + +.reveal .slides section .fragment.fade-in-then-out, +.reveal .slides section .fragment.current-visible { + opacity: 0; + visibility: hidden; } + .reveal .slides section .fragment.fade-in-then-out.current-fragment, + .reveal .slides section .fragment.current-visible.current-fragment { + opacity: 1; + visibility: inherit; } + +.reveal .slides section .fragment.fade-in-then-semi-out { + opacity: 0; + visibility: hidden; } + .reveal .slides section .fragment.fade-in-then-semi-out.visible { + opacity: 0.5; + visibility: inherit; } + .reveal .slides section .fragment.fade-in-then-semi-out.current-fragment { + opacity: 1; + visibility: inherit; } + +.reveal .slides section .fragment.highlight-red, +.reveal .slides section .fragment.highlight-current-red, +.reveal .slides section .fragment.highlight-green, +.reveal .slides section .fragment.highlight-current-green, +.reveal .slides section .fragment.highlight-blue, +.reveal .slides section .fragment.highlight-current-blue { + opacity: 1; + visibility: inherit; } + +.reveal .slides section .fragment.highlight-red.visible { + color: #ff2c2d; } + +.reveal .slides section .fragment.highlight-green.visible { + color: #216428; } + +.reveal .slides section .fragment.highlight-blue.visible { + color: #1b91ff; } + +.reveal .slides section .fragment.highlight-current-red.current-fragment { + color: #ff2c2d; } + +.reveal .slides section .fragment.highlight-current-green.current-fragment { + color: #17ff2e; } + +.reveal .slides section .fragment.highlight-current-blue.current-fragment { + color: #1b91ff; } + +/********************************************* + * DEFAULT ELEMENT STYLES + *********************************************/ +/* Fixes issue in Chrome where italic fonts did not appear when printing to PDF */ +.reveal:after { + content: ''; + font-style: italic; } + +.reveal iframe { + z-index: 1; } + +/** Prevents layering issues in certain browser/transition combinations */ +.reveal a { + position: relative; } + +.reveal .stretch { + max-width: none; + max-height: none; } + +.reveal pre.stretch code { + height: 100%; + max-height: 100%; + box-sizing: border-box; } + +/********************************************* + * CONTROLS + *********************************************/ +@-webkit-keyframes bounce-right { + 0%, 10%, 25%, 40%, 50% { + -webkit-transform: translateX(0); + transform: translateX(0); } + 20% { + -webkit-transform: translateX(10px); + transform: translateX(10px); } + 30% { + -webkit-transform: translateX(-5px); + transform: translateX(-5px); } } +@keyframes bounce-right { + 0%, 10%, 25%, 40%, 50% { + -webkit-transform: translateX(0); + transform: translateX(0); } + 20% { + -webkit-transform: translateX(10px); + transform: translateX(10px); } + 30% { + -webkit-transform: translateX(-5px); + transform: translateX(-5px); } } + +@-webkit-keyframes bounce-down { + 0%, 10%, 25%, 40%, 50% { + -webkit-transform: translateY(0); + transform: translateY(0); } + 20% { + -webkit-transform: translateY(10px); + transform: translateY(10px); } + 30% { + -webkit-transform: translateY(-5px); + transform: translateY(-5px); } } + +@keyframes bounce-down { + 0%, 10%, 25%, 40%, 50% { + -webkit-transform: translateY(0); + transform: translateY(0); } + 20% { + -webkit-transform: translateY(10px); + transform: translateY(10px); } + 30% { + -webkit-transform: translateY(-5px); + transform: translateY(-5px); } } + +.reveal .controls { + display: none; + position: absolute; + top: auto; + bottom: 12px; + right: 12px; + left: auto; + z-index: 11; + color: #000; + pointer-events: none; + font-size: 10px; } + .reveal .controls button { + position: absolute; + padding: 0; + background-color: transparent; + border: 0; + outline: 0; + cursor: pointer; + color: currentColor; + -webkit-transform: scale(0.9999); + transform: scale(0.9999); + transition: color 0.2s ease, opacity 0.2s ease, -webkit-transform 0.2s ease; + transition: color 0.2s ease, opacity 0.2s ease, transform 0.2s ease; + z-index: 2; + pointer-events: auto; + font-size: inherit; + visibility: hidden; + opacity: 0; + -webkit-appearance: none; + -webkit-tap-highlight-color: rgba(0, 0, 0, 0); } + .reveal .controls .controls-arrow:before, + .reveal .controls .controls-arrow:after { + content: ''; + position: absolute; + top: 0; + left: 0; + width: 2.6em; + height: 0.5em; + border-radius: 0.25em; + background-color: currentColor; + transition: all 0.15s ease, background-color 0.8s ease; + -webkit-transform-origin: 0.2em 50%; + transform-origin: 0.2em 50%; + will-change: transform; } + .reveal .controls .controls-arrow { + position: relative; + width: 3.6em; + height: 3.6em; } + .reveal .controls .controls-arrow:before { + -webkit-transform: translateX(0.5em) translateY(1.55em) rotate(45deg); + transform: translateX(0.5em) translateY(1.55em) rotate(45deg); } + .reveal .controls .controls-arrow:after { + -webkit-transform: translateX(0.5em) translateY(1.55em) rotate(-45deg); + transform: translateX(0.5em) translateY(1.55em) rotate(-45deg); } + .reveal .controls .controls-arrow:hover:before { + -webkit-transform: translateX(0.5em) translateY(1.55em) rotate(40deg); + transform: translateX(0.5em) translateY(1.55em) rotate(40deg); } + .reveal .controls .controls-arrow:hover:after { + -webkit-transform: translateX(0.5em) translateY(1.55em) rotate(-40deg); + transform: translateX(0.5em) translateY(1.55em) rotate(-40deg); } + .reveal .controls .controls-arrow:active:before { + -webkit-transform: translateX(0.5em) translateY(1.55em) rotate(36deg); + transform: translateX(0.5em) translateY(1.55em) rotate(36deg); } + .reveal .controls .controls-arrow:active:after { + -webkit-transform: translateX(0.5em) translateY(1.55em) rotate(-36deg); + transform: translateX(0.5em) translateY(1.55em) rotate(-36deg); } + .reveal .controls .navigate-left { + right: 6.4em; + bottom: 3.2em; + -webkit-transform: translateX(-10px); + transform: translateX(-10px); } + .reveal .controls .navigate-right { + right: 0; + bottom: 3.2em; + -webkit-transform: translateX(10px); + transform: translateX(10px); } + .reveal .controls .navigate-right .controls-arrow { + -webkit-transform: rotate(180deg); + transform: rotate(180deg); } + .reveal .controls .navigate-right.highlight { + -webkit-animation: bounce-right 2s 50 both ease-out; + animation: bounce-right 2s 50 both ease-out; } + .reveal .controls .navigate-up { + right: 3.2em; + bottom: 6.4em; + -webkit-transform: translateY(-10px); + transform: translateY(-10px); } + .reveal .controls .navigate-up .controls-arrow { + -webkit-transform: rotate(90deg); + transform: rotate(90deg); } + .reveal .controls .navigate-down { + right: 3.2em; + bottom: -1.4em; + padding-bottom: 1.4em; + -webkit-transform: translateY(10px); + transform: translateY(10px); } + .reveal .controls .navigate-down .controls-arrow { + -webkit-transform: rotate(-90deg); + transform: rotate(-90deg); } + .reveal .controls .navigate-down.highlight { + -webkit-animation: bounce-down 2s 50 both ease-out; + animation: bounce-down 2s 50 both ease-out; } + .reveal .controls[data-controls-back-arrows="faded"] .navigate-left.enabled, + .reveal .controls[data-controls-back-arrows="faded"] .navigate-up.enabled { + opacity: 0.3; } + .reveal .controls[data-controls-back-arrows="faded"] .navigate-left.enabled:hover, + .reveal .controls[data-controls-back-arrows="faded"] .navigate-up.enabled:hover { + opacity: 1; } + .reveal .controls[data-controls-back-arrows="hidden"] .navigate-left.enabled, + .reveal .controls[data-controls-back-arrows="hidden"] .navigate-up.enabled { + opacity: 0; + visibility: hidden; } + .reveal .controls .enabled { + visibility: visible; + opacity: 0.9; + cursor: pointer; + -webkit-transform: none; + transform: none; } + .reveal .controls .enabled.fragmented { + opacity: 0.5; } + .reveal .controls .enabled:hover, + .reveal .controls .enabled.fragmented:hover { + opacity: 1; } + +.reveal[data-navigation-mode="linear"].has-horizontal-slides .navigate-up, +.reveal[data-navigation-mode="linear"].has-horizontal-slides .navigate-down { + display: none; } + +.reveal[data-navigation-mode="linear"].has-horizontal-slides .navigate-left, +.reveal:not(.has-vertical-slides) .controls .navigate-left { + bottom: 1.4em; + right: 5.5em; } + +.reveal[data-navigation-mode="linear"].has-horizontal-slides .navigate-right, +.reveal:not(.has-vertical-slides) .controls .navigate-right { + bottom: 1.4em; + right: 0.5em; } + +.reveal:not(.has-horizontal-slides) .controls .navigate-up { + right: 1.4em; + bottom: 5em; } + +.reveal:not(.has-horizontal-slides) .controls .navigate-down { + right: 1.4em; + bottom: 0.5em; } + +.reveal.has-dark-background .controls { + color: #fff; } + +.reveal.has-light-background .controls { + color: #000; } + +.reveal.no-hover .controls .controls-arrow:hover:before, +.reveal.no-hover .controls .controls-arrow:active:before { + -webkit-transform: translateX(0.5em) translateY(1.55em) rotate(45deg); + transform: translateX(0.5em) translateY(1.55em) rotate(45deg); } + +.reveal.no-hover .controls .controls-arrow:hover:after, +.reveal.no-hover .controls .controls-arrow:active:after { + -webkit-transform: translateX(0.5em) translateY(1.55em) rotate(-45deg); + transform: translateX(0.5em) translateY(1.55em) rotate(-45deg); } + +@media screen and (min-width: 500px) { + .reveal .controls[data-controls-layout="edges"] { + top: 0; + right: 0; + bottom: 0; + left: 0; } + .reveal .controls[data-controls-layout="edges"] .navigate-left, + .reveal .controls[data-controls-layout="edges"] .navigate-right, + .reveal .controls[data-controls-layout="edges"] .navigate-up, + .reveal .controls[data-controls-layout="edges"] .navigate-down { + bottom: auto; + right: auto; } + .reveal .controls[data-controls-layout="edges"] .navigate-left { + top: 50%; + left: 0.8em; + margin-top: -1.8em; } + .reveal .controls[data-controls-layout="edges"] .navigate-right { + top: 50%; + right: 0.8em; + margin-top: -1.8em; } + .reveal .controls[data-controls-layout="edges"] .navigate-up { + top: 0.8em; + left: 50%; + margin-left: -1.8em; } + .reveal .controls[data-controls-layout="edges"] .navigate-down { + bottom: -0.3em; + left: 50%; + margin-left: -1.8em; } } + +/********************************************* + * PROGRESS BAR + *********************************************/ +.reveal .progress { + position: absolute; + display: none; + height: 3px; + width: 100%; + bottom: 0; + left: 0; + z-index: 10; + background-color: rgba(0, 0, 0, 0.2); + color: #fff; } + +.reveal .progress:after { + content: ''; + display: block; + position: absolute; + height: 10px; + width: 100%; + top: -10px; } + +.reveal .progress span { + display: block; + height: 100%; + width: 0px; + background-color: currentColor; + transition: width 800ms cubic-bezier(0.26, 0.86, 0.44, 0.985); } + +/********************************************* + * SLIDE NUMBER + *********************************************/ +.reveal .slide-number { + position: absolute; + display: block; + right: 8px; + bottom: 8px; + z-index: 31; + font-family: Helvetica, sans-serif; + font-size: 12px; + line-height: 1; + color: #fff; + background-color: rgba(0, 0, 0, 0.4); + padding: 5px; } + +.reveal .slide-number a { + color: currentColor; } + +.reveal .slide-number-delimiter { + margin: 0 3px; } + +/********************************************* + * SLIDES + *********************************************/ +.reveal { + position: relative; + width: 100%; + height: 100%; + overflow: hidden; + -ms-touch-action: pinch-zoom; + touch-action: pinch-zoom; } + +.reveal .slides { + position: absolute; + width: 100%; + height: 100%; + top: 0; + right: 0; + bottom: 0; + left: 0; + margin: auto; + pointer-events: none; + overflow: visible; + z-index: 1; + text-align: center; + -webkit-perspective: 600px; + perspective: 600px; + -webkit-perspective-origin: 50% 40%; + perspective-origin: 50% 40%; } + +.reveal .slides > section { + -webkit-perspective: 600px; + perspective: 600px; } + +.reveal .slides > section, +.reveal .slides > section > section { + display: none; + position: absolute; + width: 100%; + padding: 20px 0px; + pointer-events: auto; + z-index: 10; + -webkit-transform-style: flat; + transform-style: flat; + transition: -webkit-transform-origin 800ms cubic-bezier(0.26, 0.86, 0.44, 0.985), -webkit-transform 800ms cubic-bezier(0.26, 0.86, 0.44, 0.985), visibility 800ms cubic-bezier(0.26, 0.86, 0.44, 0.985), opacity 800ms cubic-bezier(0.26, 0.86, 0.44, 0.985); + transition: transform-origin 800ms cubic-bezier(0.26, 0.86, 0.44, 0.985), transform 800ms cubic-bezier(0.26, 0.86, 0.44, 0.985), visibility 800ms cubic-bezier(0.26, 0.86, 0.44, 0.985), opacity 800ms cubic-bezier(0.26, 0.86, 0.44, 0.985); } + +/* Global transition speed settings */ +.reveal[data-transition-speed="fast"] .slides section { + transition-duration: 400ms; } + +.reveal[data-transition-speed="slow"] .slides section { + transition-duration: 1200ms; } + +/* Slide-specific transition speed overrides */ +.reveal .slides section[data-transition-speed="fast"] { + transition-duration: 400ms; } + +.reveal .slides section[data-transition-speed="slow"] { + transition-duration: 1200ms; } + +.reveal .slides > section.stack { + padding-top: 0; + padding-bottom: 0; + pointer-events: none; + height: 100%; } + +.reveal .slides > section.present, +.reveal .slides > section > section.present { + display: block; + z-index: 11; + opacity: 1; } + +.reveal .slides > section:empty, +.reveal .slides > section > section:empty, +.reveal .slides > section[data-background-interactive], +.reveal .slides > section > section[data-background-interactive] { + pointer-events: none; } + +.reveal.center, +.reveal.center .slides, +.reveal.center .slides section { + min-height: 0 !important; } + +/* Don't allow interaction with invisible slides */ +.reveal .slides > section.future, +.reveal .slides > section > section.future, +.reveal .slides > section.past, +.reveal .slides > section > section.past { + pointer-events: none; } + +.reveal.overview .slides > section, +.reveal.overview .slides > section > section { + pointer-events: auto; } + +.reveal .slides > section.past, +.reveal .slides > section.future, +.reveal .slides > section > section.past, +.reveal .slides > section > section.future { + opacity: 0; } + +/********************************************* + * Mixins for readability of transitions + *********************************************/ +/********************************************* + * SLIDE TRANSITION + * Aliased 'linear' for backwards compatibility + *********************************************/ +.reveal.slide section { + -webkit-backface-visibility: hidden; + backface-visibility: hidden; } + +.reveal .slides > section[data-transition=slide].past, +.reveal .slides > section[data-transition~=slide-out].past, +.reveal.slide .slides > section:not([data-transition]).past { + -webkit-transform: translate(-150%, 0); + transform: translate(-150%, 0); } + +.reveal .slides > section[data-transition=slide].future, +.reveal .slides > section[data-transition~=slide-in].future, +.reveal.slide .slides > section:not([data-transition]).future { + -webkit-transform: translate(150%, 0); + transform: translate(150%, 0); } + +.reveal .slides > section > section[data-transition=slide].past, +.reveal .slides > section > section[data-transition~=slide-out].past, +.reveal.slide .slides > section > section:not([data-transition]).past { + -webkit-transform: translate(0, -150%); + transform: translate(0, -150%); } + +.reveal .slides > section > section[data-transition=slide].future, +.reveal .slides > section > section[data-transition~=slide-in].future, +.reveal.slide .slides > section > section:not([data-transition]).future { + -webkit-transform: translate(0, 150%); + transform: translate(0, 150%); } + +.reveal.linear section { + -webkit-backface-visibility: hidden; + backface-visibility: hidden; } + +.reveal .slides > section[data-transition=linear].past, +.reveal .slides > section[data-transition~=linear-out].past, +.reveal.linear .slides > section:not([data-transition]).past { + -webkit-transform: translate(-150%, 0); + transform: translate(-150%, 0); } + +.reveal .slides > section[data-transition=linear].future, +.reveal .slides > section[data-transition~=linear-in].future, +.reveal.linear .slides > section:not([data-transition]).future { + -webkit-transform: translate(150%, 0); + transform: translate(150%, 0); } + +.reveal .slides > section > section[data-transition=linear].past, +.reveal .slides > section > section[data-transition~=linear-out].past, +.reveal.linear .slides > section > section:not([data-transition]).past { + -webkit-transform: translate(0, -150%); + transform: translate(0, -150%); } + +.reveal .slides > section > section[data-transition=linear].future, +.reveal .slides > section > section[data-transition~=linear-in].future, +.reveal.linear .slides > section > section:not([data-transition]).future { + -webkit-transform: translate(0, 150%); + transform: translate(0, 150%); } + +/********************************************* + * CONVEX TRANSITION + * Aliased 'default' for backwards compatibility + *********************************************/ +.reveal .slides section[data-transition=default].stack, +.reveal.default .slides section.stack { + -webkit-transform-style: preserve-3d; + transform-style: preserve-3d; } + +.reveal .slides > section[data-transition=default].past, +.reveal .slides > section[data-transition~=default-out].past, +.reveal.default .slides > section:not([data-transition]).past { + -webkit-transform: translate3d(-100%, 0, 0) rotateY(-90deg) translate3d(-100%, 0, 0); + transform: translate3d(-100%, 0, 0) rotateY(-90deg) translate3d(-100%, 0, 0); } + +.reveal .slides > section[data-transition=default].future, +.reveal .slides > section[data-transition~=default-in].future, +.reveal.default .slides > section:not([data-transition]).future { + -webkit-transform: translate3d(100%, 0, 0) rotateY(90deg) translate3d(100%, 0, 0); + transform: translate3d(100%, 0, 0) rotateY(90deg) translate3d(100%, 0, 0); } + +.reveal .slides > section > section[data-transition=default].past, +.reveal .slides > section > section[data-transition~=default-out].past, +.reveal.default .slides > section > section:not([data-transition]).past { + -webkit-transform: translate3d(0, -300px, 0) rotateX(70deg) translate3d(0, -300px, 0); + transform: translate3d(0, -300px, 0) rotateX(70deg) translate3d(0, -300px, 0); } + +.reveal .slides > section > section[data-transition=default].future, +.reveal .slides > section > section[data-transition~=default-in].future, +.reveal.default .slides > section > section:not([data-transition]).future { + -webkit-transform: translate3d(0, 300px, 0) rotateX(-70deg) translate3d(0, 300px, 0); + transform: translate3d(0, 300px, 0) rotateX(-70deg) translate3d(0, 300px, 0); } + +.reveal .slides section[data-transition=convex].stack, +.reveal.convex .slides section.stack { + -webkit-transform-style: preserve-3d; + transform-style: preserve-3d; } + +.reveal .slides > section[data-transition=convex].past, +.reveal .slides > section[data-transition~=convex-out].past, +.reveal.convex .slides > section:not([data-transition]).past { + -webkit-transform: translate3d(-100%, 0, 0) rotateY(-90deg) translate3d(-100%, 0, 0); + transform: translate3d(-100%, 0, 0) rotateY(-90deg) translate3d(-100%, 0, 0); } + +.reveal .slides > section[data-transition=convex].future, +.reveal .slides > section[data-transition~=convex-in].future, +.reveal.convex .slides > section:not([data-transition]).future { + -webkit-transform: translate3d(100%, 0, 0) rotateY(90deg) translate3d(100%, 0, 0); + transform: translate3d(100%, 0, 0) rotateY(90deg) translate3d(100%, 0, 0); } + +.reveal .slides > section > section[data-transition=convex].past, +.reveal .slides > section > section[data-transition~=convex-out].past, +.reveal.convex .slides > section > section:not([data-transition]).past { + -webkit-transform: translate3d(0, -300px, 0) rotateX(70deg) translate3d(0, -300px, 0); + transform: translate3d(0, -300px, 0) rotateX(70deg) translate3d(0, -300px, 0); } + +.reveal .slides > section > section[data-transition=convex].future, +.reveal .slides > section > section[data-transition~=convex-in].future, +.reveal.convex .slides > section > section:not([data-transition]).future { + -webkit-transform: translate3d(0, 300px, 0) rotateX(-70deg) translate3d(0, 300px, 0); + transform: translate3d(0, 300px, 0) rotateX(-70deg) translate3d(0, 300px, 0); } + +/********************************************* + * CONCAVE TRANSITION + *********************************************/ +.reveal .slides section[data-transition=concave].stack, +.reveal.concave .slides section.stack { + -webkit-transform-style: preserve-3d; + transform-style: preserve-3d; } + +.reveal .slides > section[data-transition=concave].past, +.reveal .slides > section[data-transition~=concave-out].past, +.reveal.concave .slides > section:not([data-transition]).past { + -webkit-transform: translate3d(-100%, 0, 0) rotateY(90deg) translate3d(-100%, 0, 0); + transform: translate3d(-100%, 0, 0) rotateY(90deg) translate3d(-100%, 0, 0); } + +.reveal .slides > section[data-transition=concave].future, +.reveal .slides > section[data-transition~=concave-in].future, +.reveal.concave .slides > section:not([data-transition]).future { + -webkit-transform: translate3d(100%, 0, 0) rotateY(-90deg) translate3d(100%, 0, 0); + transform: translate3d(100%, 0, 0) rotateY(-90deg) translate3d(100%, 0, 0); } + +.reveal .slides > section > section[data-transition=concave].past, +.reveal .slides > section > section[data-transition~=concave-out].past, +.reveal.concave .slides > section > section:not([data-transition]).past { + -webkit-transform: translate3d(0, -80%, 0) rotateX(-70deg) translate3d(0, -80%, 0); + transform: translate3d(0, -80%, 0) rotateX(-70deg) translate3d(0, -80%, 0); } + +.reveal .slides > section > section[data-transition=concave].future, +.reveal .slides > section > section[data-transition~=concave-in].future, +.reveal.concave .slides > section > section:not([data-transition]).future { + -webkit-transform: translate3d(0, 80%, 0) rotateX(70deg) translate3d(0, 80%, 0); + transform: translate3d(0, 80%, 0) rotateX(70deg) translate3d(0, 80%, 0); } + +/********************************************* + * ZOOM TRANSITION + *********************************************/ +.reveal .slides section[data-transition=zoom], +.reveal.zoom .slides section:not([data-transition]) { + transition-timing-function: ease; } + +.reveal .slides > section[data-transition=zoom].past, +.reveal .slides > section[data-transition~=zoom-out].past, +.reveal.zoom .slides > section:not([data-transition]).past { + visibility: hidden; + -webkit-transform: scale(16); + transform: scale(16); } + +.reveal .slides > section[data-transition=zoom].future, +.reveal .slides > section[data-transition~=zoom-in].future, +.reveal.zoom .slides > section:not([data-transition]).future { + visibility: hidden; + -webkit-transform: scale(0.2); + transform: scale(0.2); } + +.reveal .slides > section > section[data-transition=zoom].past, +.reveal .slides > section > section[data-transition~=zoom-out].past, +.reveal.zoom .slides > section > section:not([data-transition]).past { + -webkit-transform: scale(16); + transform: scale(16); } + +.reveal .slides > section > section[data-transition=zoom].future, +.reveal .slides > section > section[data-transition~=zoom-in].future, +.reveal.zoom .slides > section > section:not([data-transition]).future { + -webkit-transform: scale(0.2); + transform: scale(0.2); } + +/********************************************* + * CUBE TRANSITION + * + * WARNING: + * this is deprecated and will be removed in a + * future version. + *********************************************/ +.reveal.cube .slides { + -webkit-perspective: 1300px; + perspective: 1300px; } + +.reveal.cube .slides section { + padding: 30px; + min-height: 700px; + -webkit-backface-visibility: hidden; + backface-visibility: hidden; + box-sizing: border-box; + -webkit-transform-style: preserve-3d; + transform-style: preserve-3d; } + +.reveal.center.cube .slides section { + min-height: 0; } + +.reveal.cube .slides section:not(.stack):before { + content: ''; + position: absolute; + display: block; + width: 100%; + height: 100%; + left: 0; + top: 0; + background: rgba(0, 0, 0, 0.1); + border-radius: 4px; + -webkit-transform: translateZ(-20px); + transform: translateZ(-20px); } + +.reveal.cube .slides section:not(.stack):after { + content: ''; + position: absolute; + display: block; + width: 90%; + height: 30px; + left: 5%; + bottom: 0; + background: none; + z-index: 1; + border-radius: 4px; + box-shadow: 0px 95px 25px rgba(0, 0, 0, 0.2); + -webkit-transform: translateZ(-90px) rotateX(65deg); + transform: translateZ(-90px) rotateX(65deg); } + +.reveal.cube .slides > section.stack { + padding: 0; + background: none; } + +.reveal.cube .slides > section.past { + -webkit-transform-origin: 100% 0%; + transform-origin: 100% 0%; + -webkit-transform: translate3d(-100%, 0, 0) rotateY(-90deg); + transform: translate3d(-100%, 0, 0) rotateY(-90deg); } + +.reveal.cube .slides > section.future { + -webkit-transform-origin: 0% 0%; + transform-origin: 0% 0%; + -webkit-transform: translate3d(100%, 0, 0) rotateY(90deg); + transform: translate3d(100%, 0, 0) rotateY(90deg); } + +.reveal.cube .slides > section > section.past { + -webkit-transform-origin: 0% 100%; + transform-origin: 0% 100%; + -webkit-transform: translate3d(0, -100%, 0) rotateX(90deg); + transform: translate3d(0, -100%, 0) rotateX(90deg); } + +.reveal.cube .slides > section > section.future { + -webkit-transform-origin: 0% 0%; + transform-origin: 0% 0%; + -webkit-transform: translate3d(0, 100%, 0) rotateX(-90deg); + transform: translate3d(0, 100%, 0) rotateX(-90deg); } + +/********************************************* + * PAGE TRANSITION + * + * WARNING: + * this is deprecated and will be removed in a + * future version. + *********************************************/ +.reveal.page .slides { + -webkit-perspective-origin: 0% 50%; + perspective-origin: 0% 50%; + -webkit-perspective: 3000px; + perspective: 3000px; } + +.reveal.page .slides section { + padding: 30px; + min-height: 700px; + box-sizing: border-box; + -webkit-transform-style: preserve-3d; + transform-style: preserve-3d; } + +.reveal.page .slides section.past { + z-index: 12; } + +.reveal.page .slides section:not(.stack):before { + content: ''; + position: absolute; + display: block; + width: 100%; + height: 100%; + left: 0; + top: 0; + background: rgba(0, 0, 0, 0.1); + -webkit-transform: translateZ(-20px); + transform: translateZ(-20px); } + +.reveal.page .slides section:not(.stack):after { + content: ''; + position: absolute; + display: block; + width: 90%; + height: 30px; + left: 5%; + bottom: 0; + background: none; + z-index: 1; + border-radius: 4px; + box-shadow: 0px 95px 25px rgba(0, 0, 0, 0.2); + -webkit-transform: translateZ(-90px) rotateX(65deg); } + +.reveal.page .slides > section.stack { + padding: 0; + background: none; } + +.reveal.page .slides > section.past { + -webkit-transform-origin: 0% 0%; + transform-origin: 0% 0%; + -webkit-transform: translate3d(-40%, 0, 0) rotateY(-80deg); + transform: translate3d(-40%, 0, 0) rotateY(-80deg); } + +.reveal.page .slides > section.future { + -webkit-transform-origin: 100% 0%; + transform-origin: 100% 0%; + -webkit-transform: translate3d(0, 0, 0); + transform: translate3d(0, 0, 0); } + +.reveal.page .slides > section > section.past { + -webkit-transform-origin: 0% 0%; + transform-origin: 0% 0%; + -webkit-transform: translate3d(0, -40%, 0) rotateX(80deg); + transform: translate3d(0, -40%, 0) rotateX(80deg); } + +.reveal.page .slides > section > section.future { + -webkit-transform-origin: 0% 100%; + transform-origin: 0% 100%; + -webkit-transform: translate3d(0, 0, 0); + transform: translate3d(0, 0, 0); } + +/********************************************* + * FADE TRANSITION + *********************************************/ +.reveal .slides section[data-transition=fade], +.reveal.fade .slides section:not([data-transition]), +.reveal.fade .slides > section > section:not([data-transition]) { + -webkit-transform: none; + transform: none; + transition: opacity 0.5s; } + +.reveal.fade.overview .slides section, +.reveal.fade.overview .slides > section > section { + transition: none; } + +/********************************************* + * NO TRANSITION + *********************************************/ +.reveal .slides section[data-transition=none], +.reveal.none .slides section:not([data-transition]) { + -webkit-transform: none; + transform: none; + transition: none; } + +/********************************************* + * PAUSED MODE + *********************************************/ +.reveal .pause-overlay { + position: absolute; + top: 0; + left: 0; + width: 100%; + height: 100%; + background: black; + visibility: hidden; + opacity: 0; + z-index: 100; + transition: all 1s ease; } + +.reveal .pause-overlay .resume-button { + position: absolute; + bottom: 20px; + right: 20px; + color: #ccc; + border-radius: 2px; + padding: 6px 14px; + border: 2px solid #ccc; + font-size: 16px; + background: transparent; + cursor: pointer; } + .reveal .pause-overlay .resume-button:hover { + color: #fff; + border-color: #fff; } + +.reveal.paused .pause-overlay { + visibility: visible; + opacity: 1; } + +/********************************************* + * FALLBACK + *********************************************/ +.no-transforms { + overflow-y: auto; } + +.no-transforms .reveal { + overflow: visible; } + +.no-transforms .reveal .slides { + position: relative; + width: 80%; + max-width: 1280px; + height: auto; + top: 0; + margin: 0 auto; + text-align: center; } + +.no-transforms .reveal .controls, +.no-transforms .reveal .progress { + display: none; } + +.no-transforms .reveal .slides section { + display: block; + opacity: 1; + position: relative; + height: auto; + min-height: 0; + top: 0; + left: 0; + margin: 10vh 0; + margin: 70px 0; + -webkit-transform: none; + transform: none; } + +.reveal .no-transition, +.reveal .no-transition * { + transition: none !important; } + +/********************************************* + * PER-SLIDE BACKGROUNDS + *********************************************/ +.reveal .backgrounds { + position: absolute; + width: 100%; + height: 100%; + top: 0; + left: 0; + -webkit-perspective: 600px; + perspective: 600px; } + +.reveal .slide-background { + display: none; + position: absolute; + width: 100%; + height: 100%; + opacity: 0; + visibility: hidden; + overflow: hidden; + background-color: rgba(0, 0, 0, 0); + transition: all 800ms cubic-bezier(0.26, 0.86, 0.44, 0.985); } + +.reveal .slide-background-content { + position: absolute; + width: 100%; + height: 100%; + background-position: 50% 50%; + background-repeat: no-repeat; + background-size: cover; } + +.reveal .slide-background.stack { + display: block; } + +.reveal .slide-background.present { + opacity: 1; + visibility: visible; + z-index: 2; } + +.print-pdf .reveal .slide-background { + opacity: 1 !important; + visibility: visible !important; } + +/* Video backgrounds */ +.reveal .slide-background video { + position: absolute; + width: 100%; + height: 100%; + max-width: none; + max-height: none; + top: 0; + left: 0; + -o-object-fit: cover; + object-fit: cover; } + +.reveal .slide-background[data-background-size="contain"] video { + -o-object-fit: contain; + object-fit: contain; } + +/* Immediate transition style */ +.reveal[data-background-transition=none] > .backgrounds .slide-background, +.reveal > .backgrounds .slide-background[data-background-transition=none] { + transition: none; } + +/* Slide */ +.reveal[data-background-transition=slide] > .backgrounds .slide-background, +.reveal > .backgrounds .slide-background[data-background-transition=slide] { + opacity: 1; + -webkit-backface-visibility: hidden; + backface-visibility: hidden; } + +.reveal[data-background-transition=slide] > .backgrounds .slide-background.past, +.reveal > .backgrounds .slide-background.past[data-background-transition=slide] { + -webkit-transform: translate(-100%, 0); + transform: translate(-100%, 0); } + +.reveal[data-background-transition=slide] > .backgrounds .slide-background.future, +.reveal > .backgrounds .slide-background.future[data-background-transition=slide] { + -webkit-transform: translate(100%, 0); + transform: translate(100%, 0); } + +.reveal[data-background-transition=slide] > .backgrounds .slide-background > .slide-background.past, +.reveal > .backgrounds .slide-background > .slide-background.past[data-background-transition=slide] { + -webkit-transform: translate(0, -100%); + transform: translate(0, -100%); } + +.reveal[data-background-transition=slide] > .backgrounds .slide-background > .slide-background.future, +.reveal > .backgrounds .slide-background > .slide-background.future[data-background-transition=slide] { + -webkit-transform: translate(0, 100%); + transform: translate(0, 100%); } + +/* Convex */ +.reveal[data-background-transition=convex] > .backgrounds .slide-background.past, +.reveal > .backgrounds .slide-background.past[data-background-transition=convex] { + opacity: 0; + -webkit-transform: translate3d(-100%, 0, 0) rotateY(-90deg) translate3d(-100%, 0, 0); + transform: translate3d(-100%, 0, 0) rotateY(-90deg) translate3d(-100%, 0, 0); } + +.reveal[data-background-transition=convex] > .backgrounds .slide-background.future, +.reveal > .backgrounds .slide-background.future[data-background-transition=convex] { + opacity: 0; + -webkit-transform: translate3d(100%, 0, 0) rotateY(90deg) translate3d(100%, 0, 0); + transform: translate3d(100%, 0, 0) rotateY(90deg) translate3d(100%, 0, 0); } + +.reveal[data-background-transition=convex] > .backgrounds .slide-background > .slide-background.past, +.reveal > .backgrounds .slide-background > .slide-background.past[data-background-transition=convex] { + opacity: 0; + -webkit-transform: translate3d(0, -100%, 0) rotateX(90deg) translate3d(0, -100%, 0); + transform: translate3d(0, -100%, 0) rotateX(90deg) translate3d(0, -100%, 0); } + +.reveal[data-background-transition=convex] > .backgrounds .slide-background > .slide-background.future, +.reveal > .backgrounds .slide-background > .slide-background.future[data-background-transition=convex] { + opacity: 0; + -webkit-transform: translate3d(0, 100%, 0) rotateX(-90deg) translate3d(0, 100%, 0); + transform: translate3d(0, 100%, 0) rotateX(-90deg) translate3d(0, 100%, 0); } + +/* Concave */ +.reveal[data-background-transition=concave] > .backgrounds .slide-background.past, +.reveal > .backgrounds .slide-background.past[data-background-transition=concave] { + opacity: 0; + -webkit-transform: translate3d(-100%, 0, 0) rotateY(90deg) translate3d(-100%, 0, 0); + transform: translate3d(-100%, 0, 0) rotateY(90deg) translate3d(-100%, 0, 0); } + +.reveal[data-background-transition=concave] > .backgrounds .slide-background.future, +.reveal > .backgrounds .slide-background.future[data-background-transition=concave] { + opacity: 0; + -webkit-transform: translate3d(100%, 0, 0) rotateY(-90deg) translate3d(100%, 0, 0); + transform: translate3d(100%, 0, 0) rotateY(-90deg) translate3d(100%, 0, 0); } + +.reveal[data-background-transition=concave] > .backgrounds .slide-background > .slide-background.past, +.reveal > .backgrounds .slide-background > .slide-background.past[data-background-transition=concave] { + opacity: 0; + -webkit-transform: translate3d(0, -100%, 0) rotateX(-90deg) translate3d(0, -100%, 0); + transform: translate3d(0, -100%, 0) rotateX(-90deg) translate3d(0, -100%, 0); } + +.reveal[data-background-transition=concave] > .backgrounds .slide-background > .slide-background.future, +.reveal > .backgrounds .slide-background > .slide-background.future[data-background-transition=concave] { + opacity: 0; + -webkit-transform: translate3d(0, 100%, 0) rotateX(90deg) translate3d(0, 100%, 0); + transform: translate3d(0, 100%, 0) rotateX(90deg) translate3d(0, 100%, 0); } + +/* Zoom */ +.reveal[data-background-transition=zoom] > .backgrounds .slide-background, +.reveal > .backgrounds .slide-background[data-background-transition=zoom] { + transition-timing-function: ease; } + +.reveal[data-background-transition=zoom] > .backgrounds .slide-background.past, +.reveal > .backgrounds .slide-background.past[data-background-transition=zoom] { + opacity: 0; + visibility: hidden; + -webkit-transform: scale(16); + transform: scale(16); } + +.reveal[data-background-transition=zoom] > .backgrounds .slide-background.future, +.reveal > .backgrounds .slide-background.future[data-background-transition=zoom] { + opacity: 0; + visibility: hidden; + -webkit-transform: scale(0.2); + transform: scale(0.2); } + +.reveal[data-background-transition=zoom] > .backgrounds .slide-background > .slide-background.past, +.reveal > .backgrounds .slide-background > .slide-background.past[data-background-transition=zoom] { + opacity: 0; + visibility: hidden; + -webkit-transform: scale(16); + transform: scale(16); } + +.reveal[data-background-transition=zoom] > .backgrounds .slide-background > .slide-background.future, +.reveal > .backgrounds .slide-background > .slide-background.future[data-background-transition=zoom] { + opacity: 0; + visibility: hidden; + -webkit-transform: scale(0.2); + transform: scale(0.2); } + +/* Global transition speed settings */ +.reveal[data-transition-speed="fast"] > .backgrounds .slide-background { + transition-duration: 400ms; } + +.reveal[data-transition-speed="slow"] > .backgrounds .slide-background { + transition-duration: 1200ms; } + +/********************************************* + * OVERVIEW + *********************************************/ +.reveal.overview { + -webkit-perspective-origin: 50% 50%; + perspective-origin: 50% 50%; + -webkit-perspective: 700px; + perspective: 700px; } + .reveal.overview .slides { + -moz-transform-style: preserve-3d; } + .reveal.overview .slides section { + height: 100%; + top: 0 !important; + opacity: 1 !important; + overflow: hidden; + visibility: visible !important; + cursor: pointer; + box-sizing: border-box; } + .reveal.overview .slides section:hover, + .reveal.overview .slides section.present { + outline: 10px solid rgba(150, 150, 150, 0.4); + outline-offset: 10px; } + .reveal.overview .slides section .fragment { + opacity: 1; + transition: none; } + .reveal.overview .slides section:after, + .reveal.overview .slides section:before { + display: none !important; } + .reveal.overview .slides > section.stack { + padding: 0; + top: 0 !important; + background: none; + outline: none; + overflow: visible; } + .reveal.overview .backgrounds { + -webkit-perspective: inherit; + perspective: inherit; + -moz-transform-style: preserve-3d; } + .reveal.overview .backgrounds .slide-background { + opacity: 1; + visibility: visible; + outline: 10px solid rgba(150, 150, 150, 0.1); + outline-offset: 10px; } + .reveal.overview .backgrounds .slide-background.stack { + overflow: visible; } + +.reveal.overview .slides section, +.reveal.overview-deactivating .slides section { + transition: none; } + +.reveal.overview .backgrounds .slide-background, +.reveal.overview-deactivating .backgrounds .slide-background { + transition: none; } + +/********************************************* + * RTL SUPPORT + *********************************************/ +.reveal.rtl .slides, +.reveal.rtl .slides h1, +.reveal.rtl .slides h2, +.reveal.rtl .slides h3, +.reveal.rtl .slides h4, +.reveal.rtl .slides h5, +.reveal.rtl .slides h6 { + direction: rtl; + font-family: sans-serif; } + +.reveal.rtl pre, +.reveal.rtl code { + direction: ltr; } + +.reveal.rtl ol, +.reveal.rtl ul { + text-align: right; } + +.reveal.rtl .progress span { + float: right; } + +/********************************************* + * PARALLAX BACKGROUND + *********************************************/ +.reveal.has-parallax-background .backgrounds { + transition: all 0.8s ease; } + +/* Global transition speed settings */ +.reveal.has-parallax-background[data-transition-speed="fast"] .backgrounds { + transition-duration: 400ms; } + +.reveal.has-parallax-background[data-transition-speed="slow"] .backgrounds { + transition-duration: 1200ms; } + +/********************************************* + * OVERLAY FOR LINK PREVIEWS AND HELP + *********************************************/ +.reveal > .overlay { + position: absolute; + top: 0; + left: 0; + width: 100%; + height: 100%; + z-index: 1000; + background: rgba(0, 0, 0, 0.9); + opacity: 0; + visibility: hidden; + transition: all 0.3s ease; } + +.reveal > .overlay.visible { + opacity: 1; + visibility: visible; } + +.reveal > .overlay .spinner { + position: absolute; + display: block; + top: 50%; + left: 50%; + width: 32px; + height: 32px; + margin: -16px 0 0 -16px; + z-index: 10; + background-image: url(data:image/gif;base64,R0lGODlhIAAgAPMAAJmZmf%2F%2F%2F6%2Bvr8nJybW1tcDAwOjo6Nvb26ioqKOjo7Ozs%2FLy8vz8%2FAAAAAAAAAAAACH%2FC05FVFNDQVBFMi4wAwEAAAAh%2FhpDcmVhdGVkIHdpdGggYWpheGxvYWQuaW5mbwAh%2BQQJCgAAACwAAAAAIAAgAAAE5xDISWlhperN52JLhSSdRgwVo1ICQZRUsiwHpTJT4iowNS8vyW2icCF6k8HMMBkCEDskxTBDAZwuAkkqIfxIQyhBQBFvAQSDITM5VDW6XNE4KagNh6Bgwe60smQUB3d4Rz1ZBApnFASDd0hihh12BkE9kjAJVlycXIg7CQIFA6SlnJ87paqbSKiKoqusnbMdmDC2tXQlkUhziYtyWTxIfy6BE8WJt5YJvpJivxNaGmLHT0VnOgSYf0dZXS7APdpB309RnHOG5gDqXGLDaC457D1zZ%2FV%2FnmOM82XiHRLYKhKP1oZmADdEAAAh%2BQQJCgAAACwAAAAAIAAgAAAE6hDISWlZpOrNp1lGNRSdRpDUolIGw5RUYhhHukqFu8DsrEyqnWThGvAmhVlteBvojpTDDBUEIFwMFBRAmBkSgOrBFZogCASwBDEY%2FCZSg7GSE0gSCjQBMVG023xWBhklAnoEdhQEfyNqMIcKjhRsjEdnezB%2BA4k8gTwJhFuiW4dokXiloUepBAp5qaKpp6%2BHo7aWW54wl7obvEe0kRuoplCGepwSx2jJvqHEmGt6whJpGpfJCHmOoNHKaHx61WiSR92E4lbFoq%2BB6QDtuetcaBPnW6%2BO7wDHpIiK9SaVK5GgV543tzjgGcghAgAh%2BQQJCgAAACwAAAAAIAAgAAAE7hDISSkxpOrN5zFHNWRdhSiVoVLHspRUMoyUakyEe8PTPCATW9A14E0UvuAKMNAZKYUZCiBMuBakSQKG8G2FzUWox2AUtAQFcBKlVQoLgQReZhQlCIJesQXI5B0CBnUMOxMCenoCfTCEWBsJColTMANldx15BGs8B5wlCZ9Po6OJkwmRpnqkqnuSrayqfKmqpLajoiW5HJq7FL1Gr2mMMcKUMIiJgIemy7xZtJsTmsM4xHiKv5KMCXqfyUCJEonXPN2rAOIAmsfB3uPoAK%2B%2BG%2Bw48edZPK%2BM6hLJpQg484enXIdQFSS1u6UhksENEQAAIfkECQoAAAAsAAAAACAAIAAABOcQyEmpGKLqzWcZRVUQnZYg1aBSh2GUVEIQ2aQOE%2BG%2BcD4ntpWkZQj1JIiZIogDFFyHI0UxQwFugMSOFIPJftfVAEoZLBbcLEFhlQiqGp1Vd140AUklUN3eCA51C1EWMzMCezCBBmkxVIVHBWd3HHl9JQOIJSdSnJ0TDKChCwUJjoWMPaGqDKannasMo6WnM562R5YluZRwur0wpgqZE7NKUm%2BFNRPIhjBJxKZteWuIBMN4zRMIVIhffcgojwCF117i4nlLnY5ztRLsnOk%2BaV%2BoJY7V7m76PdkS4trKcdg0Zc0tTcKkRAAAIfkECQoAAAAsAAAAACAAIAAABO4QyEkpKqjqzScpRaVkXZWQEximw1BSCUEIlDohrft6cpKCk5xid5MNJTaAIkekKGQkWyKHkvhKsR7ARmitkAYDYRIbUQRQjWBwJRzChi9CRlBcY1UN4g0%2FVNB0AlcvcAYHRyZPdEQFYV8ccwR5HWxEJ02YmRMLnJ1xCYp0Y5idpQuhopmmC2KgojKasUQDk5BNAwwMOh2RtRq5uQuPZKGIJQIGwAwGf6I0JXMpC8C7kXWDBINFMxS4DKMAWVWAGYsAdNqW5uaRxkSKJOZKaU3tPOBZ4DuK2LATgJhkPJMgTwKCdFjyPHEnKxFCDhEAACH5BAkKAAAALAAAAAAgACAAAATzEMhJaVKp6s2nIkolIJ2WkBShpkVRWqqQrhLSEu9MZJKK9y1ZrqYK9WiClmvoUaF8gIQSNeF1Er4MNFn4SRSDARWroAIETg1iVwuHjYB1kYc1mwruwXKC9gmsJXliGxc%2BXiUCby9ydh1sOSdMkpMTBpaXBzsfhoc5l58Gm5yToAaZhaOUqjkDgCWNHAULCwOLaTmzswadEqggQwgHuQsHIoZCHQMMQgQGubVEcxOPFAcMDAYUA85eWARmfSRQCdcMe0zeP1AAygwLlJtPNAAL19DARdPzBOWSm1brJBi45soRAWQAAkrQIykShQ9wVhHCwCQCACH5BAkKAAAALAAAAAAgACAAAATrEMhJaVKp6s2nIkqFZF2VIBWhUsJaTokqUCoBq%2BE71SRQeyqUToLA7VxF0JDyIQh%2FMVVPMt1ECZlfcjZJ9mIKoaTl1MRIl5o4CUKXOwmyrCInCKqcWtvadL2SYhyASyNDJ0uIiRMDjI0Fd30%2FiI2UA5GSS5UDj2l6NoqgOgN4gksEBgYFf0FDqKgHnyZ9OX8HrgYHdHpcHQULXAS2qKpENRg7eAMLC7kTBaixUYFkKAzWAAnLC7FLVxLWDBLKCwaKTULgEwbLA4hJtOkSBNqITT3xEgfLpBtzE%2FjiuL04RGEBgwWhShRgQExHBAAh%2BQQJCgAAACwAAAAAIAAgAAAE7xDISWlSqerNpyJKhWRdlSAVoVLCWk6JKlAqAavhO9UkUHsqlE6CwO1cRdCQ8iEIfzFVTzLdRAmZX3I2SfZiCqGk5dTESJeaOAlClzsJsqwiJwiqnFrb2nS9kmIcgEsjQydLiIlHehhpejaIjzh9eomSjZR%2BipslWIRLAgMDOR2DOqKogTB9pCUJBagDBXR6XB0EBkIIsaRsGGMMAxoDBgYHTKJiUYEGDAzHC9EACcUGkIgFzgwZ0QsSBcXHiQvOwgDdEwfFs0sDzt4S6BK4xYjkDOzn0unFeBzOBijIm1Dgmg5YFQwsCMjp1oJ8LyIAACH5BAkKAAAALAAAAAAgACAAAATwEMhJaVKp6s2nIkqFZF2VIBWhUsJaTokqUCoBq%2BE71SRQeyqUToLA7VxF0JDyIQh%2FMVVPMt1ECZlfcjZJ9mIKoaTl1MRIl5o4CUKXOwmyrCInCKqcWtvadL2SYhyASyNDJ0uIiUd6GGl6NoiPOH16iZKNlH6KmyWFOggHhEEvAwwMA0N9GBsEC6amhnVcEwavDAazGwIDaH1ipaYLBUTCGgQDA8NdHz0FpqgTBwsLqAbWAAnIA4FWKdMLGdYGEgraigbT0OITBcg5QwPT4xLrROZL6AuQAPUS7bxLpoWidY0JtxLHKhwwMJBTHgPKdEQAACH5BAkKAAAALAAAAAAgACAAAATrEMhJaVKp6s2nIkqFZF2VIBWhUsJaTokqUCoBq%2BE71SRQeyqUToLA7VxF0JDyIQh%2FMVVPMt1ECZlfcjZJ9mIKoaTl1MRIl5o4CUKXOwmyrCInCKqcWtvadL2SYhyASyNDJ0uIiUd6GAULDJCRiXo1CpGXDJOUjY%2BYip9DhToJA4RBLwMLCwVDfRgbBAaqqoZ1XBMHswsHtxtFaH1iqaoGNgAIxRpbFAgfPQSqpbgGBqUD1wBXeCYp1AYZ19JJOYgH1KwA4UBvQwXUBxPqVD9L3sbp2BNk2xvvFPJd%2BMFCN6HAAIKgNggY0KtEBAAh%2BQQJCgAAACwAAAAAIAAgAAAE6BDISWlSqerNpyJKhWRdlSAVoVLCWk6JKlAqAavhO9UkUHsqlE6CwO1cRdCQ8iEIfzFVTzLdRAmZX3I2SfYIDMaAFdTESJeaEDAIMxYFqrOUaNW4E4ObYcCXaiBVEgULe0NJaxxtYksjh2NLkZISgDgJhHthkpU4mW6blRiYmZOlh4JWkDqILwUGBnE6TYEbCgevr0N1gH4At7gHiRpFaLNrrq8HNgAJA70AWxQIH1%2BvsYMDAzZQPC9VCNkDWUhGkuE5PxJNwiUK4UfLzOlD4WvzAHaoG9nxPi5d%2BjYUqfAhhykOFwJWiAAAIfkECQoAAAAsAAAAACAAIAAABPAQyElpUqnqzaciSoVkXVUMFaFSwlpOCcMYlErAavhOMnNLNo8KsZsMZItJEIDIFSkLGQoQTNhIsFehRww2CQLKF0tYGKYSg%2BygsZIuNqJksKgbfgIGepNo2cIUB3V1B3IvNiBYNQaDSTtfhhx0CwVPI0UJe0%2Bbm4g5VgcGoqOcnjmjqDSdnhgEoamcsZuXO1aWQy8KAwOAuTYYGwi7w5h%2BKr0SJ8MFihpNbx%2B4Erq7BYBuzsdiH1jCAzoSfl0rVirNbRXlBBlLX%2BBP0XJLAPGzTkAuAOqb0WT5AH7OcdCm5B8TgRwSRKIHQtaLCwg1RAAAOwAAAAAAAAAAAA%3D%3D); + visibility: visible; + opacity: 0.6; + transition: all 0.3s ease; } + +.reveal > .overlay header { + position: absolute; + left: 0; + top: 0; + width: 100%; + height: 40px; + z-index: 2; + border-bottom: 1px solid #222; } + +.reveal > .overlay header a { + display: inline-block; + width: 40px; + height: 40px; + line-height: 36px; + padding: 0 10px; + float: right; + opacity: 0.6; + box-sizing: border-box; } + +.reveal > .overlay header a:hover { + opacity: 1; } + +.reveal > .overlay header a .icon { + display: inline-block; + width: 20px; + height: 20px; + background-position: 50% 50%; + background-size: 100%; + background-repeat: no-repeat; } + +.reveal > .overlay header a.close .icon { + background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAABkklEQVRYR8WX4VHDMAxG6wnoJrABZQPYBCaBTWAD2g1gE5gg6OOsXuxIlr40d81dfrSJ9V4c2VLK7spHuTJ/5wpM07QXuXc5X0opX2tEJcadjHuV80li/FgxTIEK/5QBCICBD6xEhSMGHgQPgBgLiYVAB1dpSqKDawxTohFw4JSEA3clzgIBPCURwE2JucBR7rhPJJv5OpJwDX+SfDjgx1wACQeJG1aChP9K/IMmdZ8DtESV1WyP3Bt4MwM6sj4NMxMYiqUWHQu4KYA/SYkIjOsm3BXYWMKFDwU2khjCQ4ELJUJ4SmClRArOCmSXGuKma0fYD5CbzHxFpCSGAhfAVSSUGDUk2BWZaff2g6GE15BsBQ9nwmpIGDiyHQddwNTMKkbZaf9fajXQca1EX44puJZUsnY0ObGmITE3GVLCbEhQUjGVt146j6oasWN+49Vph2w1pZ5EansNZqKBm1txbU57iRRcZ86RWMDdWtBJUHBHwoQPi1GV+JCbntmvok7iTX4/Up9mgyTc/FJYDTcndgH/AA5A/CHsyEkVAAAAAElFTkSuQmCC); } + +.reveal > .overlay header a.external .icon { + background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAAcElEQVRYR+2WSQoAIQwEzf8f7XiOMkUQxUPlGkM3hVmiQfQR9GYnH1SsAQlI4DiBqkCMoNb9y2e90IAEJPAcgdznU9+engMaeJ7Azh5Y1U67gAho4DqBqmB1buAf0MB1AlVBek83ZPkmJMGc1wAR+AAqod/B97TRpQAAAABJRU5ErkJggg==); } + +.reveal > .overlay .viewport { + position: absolute; + display: -webkit-box; + display: -ms-flexbox; + display: flex; + top: 40px; + right: 0; + bottom: 0; + left: 0; } + +.reveal > .overlay.overlay-preview .viewport iframe { + width: 100%; + height: 100%; + max-width: 100%; + max-height: 100%; + border: 0; + opacity: 0; + visibility: hidden; + transition: all 0.3s ease; } + +.reveal > .overlay.overlay-preview.loaded .viewport iframe { + opacity: 1; + visibility: visible; } + +.reveal > .overlay.overlay-preview.loaded .viewport-inner { + position: absolute; + z-index: -1; + left: 0; + top: 45%; + width: 100%; + text-align: center; + letter-spacing: normal; } + +.reveal > .overlay.overlay-preview .x-frame-error { + opacity: 0; + transition: opacity 0.3s ease 0.3s; } + +.reveal > .overlay.overlay-preview.loaded .x-frame-error { + opacity: 1; } + +.reveal > .overlay.overlay-preview.loaded .spinner { + opacity: 0; + visibility: hidden; + -webkit-transform: scale(0.2); + transform: scale(0.2); } + +.reveal > .overlay.overlay-help .viewport { + overflow: auto; + color: #fff; } + +.reveal > .overlay.overlay-help .viewport .viewport-inner { + width: 600px; + margin: auto; + padding: 20px 20px 80px 20px; + text-align: center; + letter-spacing: normal; } + +.reveal > .overlay.overlay-help .viewport .viewport-inner .title { + font-size: 20px; } + +.reveal > .overlay.overlay-help .viewport .viewport-inner table { + border: 1px solid #fff; + border-collapse: collapse; + font-size: 16px; } + +.reveal > .overlay.overlay-help .viewport .viewport-inner table th, +.reveal > .overlay.overlay-help .viewport .viewport-inner table td { + width: 200px; + padding: 14px; + border: 1px solid #fff; + vertical-align: middle; } + +.reveal > .overlay.overlay-help .viewport .viewport-inner table th { + padding-top: 20px; + padding-bottom: 20px; } + +/********************************************* + * PLAYBACK COMPONENT + *********************************************/ +.reveal .playback { + position: absolute; + left: 15px; + bottom: 20px; + z-index: 30; + cursor: pointer; + transition: all 400ms ease; + -webkit-tap-highlight-color: rgba(0, 0, 0, 0); } + +.reveal.overview .playback { + opacity: 0; + visibility: hidden; } + +/********************************************* + * CODE HIGHLGIHTING + *********************************************/ +.reveal .hljs table { + margin: initial; } + +.reveal .hljs-ln-code, +.reveal .hljs-ln-numbers { + padding: 0; + border: 0; } + +.reveal .hljs-ln-numbers { + opacity: 0.6; + padding-right: 0.75em; + text-align: right; + vertical-align: top; } + +.reveal .hljs.has-highlights tr:not(.highlight-line) { + opacity: 0.4; } + +.reveal .hljs:not(:first-child).fragment { + position: absolute; + top: 0; + left: 0; + width: 100%; + box-sizing: border-box; } + +/********************************************* + * ROLLING LINKS + *********************************************/ +.reveal .roll { + display: inline-block; + line-height: 1.2; + overflow: hidden; + vertical-align: top; + -webkit-perspective: 400px; + perspective: 400px; + -webkit-perspective-origin: 50% 50%; + perspective-origin: 50% 50%; } + +.reveal .roll:hover { + background: none; + text-shadow: none; } + +.reveal .roll span { + display: block; + position: relative; + padding: 0 2px; + pointer-events: none; + transition: all 400ms ease; + -webkit-transform-origin: 50% 0%; + transform-origin: 50% 0%; + -webkit-transform-style: preserve-3d; + transform-style: preserve-3d; + -webkit-backface-visibility: hidden; + backface-visibility: hidden; } + +.reveal .roll:hover span { + background: rgba(0, 0, 0, 0.5); + -webkit-transform: translate3d(0px, 0px, -45px) rotateX(90deg); + transform: translate3d(0px, 0px, -45px) rotateX(90deg); } + +.reveal .roll span:after { + content: attr(data-title); + display: block; + position: absolute; + left: 0; + top: 0; + padding: 0 2px; + -webkit-backface-visibility: hidden; + backface-visibility: hidden; + -webkit-transform-origin: 50% 0%; + transform-origin: 50% 0%; + -webkit-transform: translate3d(0px, 110%, 0px) rotateX(-90deg); + transform: translate3d(0px, 110%, 0px) rotateX(-90deg); } + +/********************************************* + * SPEAKER NOTES + *********************************************/ +.reveal aside.notes { + display: none; } + +.reveal .speaker-notes { + display: none; + position: absolute; + width: 33.3333333333%; + height: 100%; + top: 0; + left: 100%; + padding: 14px 18px 14px 18px; + z-index: 1; + font-size: 18px; + line-height: 1.4; + border: 1px solid rgba(0, 0, 0, 0.05); + color: #222; + background-color: #f5f5f5; + overflow: auto; + box-sizing: border-box; + text-align: left; + font-family: Helvetica, sans-serif; + -webkit-overflow-scrolling: touch; } + .reveal .speaker-notes .notes-placeholder { + color: #ccc; + font-style: italic; } + .reveal .speaker-notes:focus { + outline: none; } + .reveal .speaker-notes:before { + content: 'Speaker notes'; + display: block; + margin-bottom: 10px; + opacity: 0.5; } + +.reveal.show-notes { + max-width: 75%; + overflow: visible; } + +.reveal.show-notes .speaker-notes { + display: block; } + +@media screen and (min-width: 1600px) { + .reveal .speaker-notes { + font-size: 20px; } } + +@media screen and (max-width: 1024px) { + .reveal.show-notes { + border-left: 0; + max-width: none; + max-height: 70%; + max-height: 70vh; + overflow: visible; } + .reveal.show-notes .speaker-notes { + top: 100%; + left: 0; + width: 100%; + height: 42.8571428571%; + height: 30vh; + border: 0; } } + +@media screen and (max-width: 600px) { + .reveal.show-notes { + max-height: 60%; + max-height: 60vh; } + .reveal.show-notes .speaker-notes { + top: 100%; + height: 66.6666666667%; + height: 40vh; } + .reveal .speaker-notes { + font-size: 14px; } } + +/********************************************* + * ZOOM PLUGIN + *********************************************/ +.zoomed .reveal *, +.zoomed .reveal *:before, +.zoomed .reveal *:after { + -webkit-backface-visibility: visible !important; + backface-visibility: visible !important; } + +.zoomed .reveal .progress, +.zoomed .reveal .controls { + opacity: 0; } + +.zoomed .reveal .roll span { + background: none; } + +.zoomed .reveal .roll span:after { + visibility: hidden; } diff --git a/AdvancedCppV2/css/reveal.scss b/AdvancedCppV2/css/reveal.scss new file mode 100644 index 0000000..ab11f32 --- /dev/null +++ b/AdvancedCppV2/css/reveal.scss @@ -0,0 +1,1777 @@ +/*! + * reveal.js + * http://revealjs.com + * MIT licensed + * + * Copyright (C) 2020 Hakim El Hattab, http://hakim.se + */ + + +/********************************************* + * GLOBAL STYLES + *********************************************/ + +html { + width: 100%; + height: 100%; + height: 100vh; + height: calc( var(--vh, 1vh) * 100 ); + overflow: hidden; +} + +body { + height: 100%; + overflow: hidden; + position: relative; + line-height: 1; + margin: 0; + + background-color: #fff; + color: #000; +} + + +/********************************************* + * VIEW FRAGMENTS + *********************************************/ + +.reveal .slides section .fragment { + opacity: 0; + visibility: hidden; + transition: all .2s ease; + + &.visible { + opacity: 1; + visibility: inherit; + } +} + +.reveal .slides section .fragment.grow { + opacity: 1; + visibility: inherit; + + &.visible { + transform: scale( 1.3 ); + } +} + +.reveal .slides section .fragment.shrink { + opacity: 1; + visibility: inherit; + + &.visible { + transform: scale( 0.7 ); + } +} + +.reveal .slides section .fragment.zoom-in { + transform: scale( 0.1 ); + + &.visible { + transform: none; + } +} + +.reveal .slides section .fragment.fade-out { + opacity: 1; + visibility: inherit; + + &.visible { + opacity: 0; + visibility: hidden; + } +} + +.reveal .slides section .fragment.semi-fade-out { + opacity: 1; + visibility: inherit; + + &.visible { + opacity: 0.5; + visibility: inherit; + } +} + +.reveal .slides section .fragment.strike { + opacity: 1; + visibility: inherit; + + &.visible { + text-decoration: line-through; + } +} + +.reveal .slides section .fragment.fade-up { + transform: translate(0, 40px); + + &.visible { + transform: translate(0, 0); + } +} + +.reveal .slides section .fragment.fade-down { + transform: translate(0, -40px); + + &.visible { + transform: translate(0, 0); + } +} + +.reveal .slides section .fragment.fade-right { + transform: translate(-40px, 0); + + &.visible { + transform: translate(0, 0); + } +} + +.reveal .slides section .fragment.fade-left { + transform: translate(40px, 0); + + &.visible { + transform: translate(0, 0); + } +} + +.reveal .slides section .fragment.fade-in-then-out, +.reveal .slides section .fragment.current-visible { + opacity: 0; + visibility: hidden; + + &.current-fragment { + opacity: 1; + visibility: inherit; + } +} + +.reveal .slides section .fragment.fade-in-then-semi-out { + opacity: 0; + visibility: hidden; + + &.visible { + opacity: 0.5; + visibility: inherit; + } + + &.current-fragment { + opacity: 1; + visibility: inherit; + } +} + +.reveal .slides section .fragment.highlight-red, +.reveal .slides section .fragment.highlight-current-red, +.reveal .slides section .fragment.highlight-green, +.reveal .slides section .fragment.highlight-current-green, +.reveal .slides section .fragment.highlight-blue, +.reveal .slides section .fragment.highlight-current-blue { + opacity: 1; + visibility: inherit; +} + .reveal .slides section .fragment.highlight-red.visible { + color: #ff2c2d + } + .reveal .slides section .fragment.highlight-green.visible { + color: #17ff2e; + } + .reveal .slides section .fragment.highlight-blue.visible { + color: #1b91ff; + } + +.reveal .slides section .fragment.highlight-current-red.current-fragment { + color: #ff2c2d +} +.reveal .slides section .fragment.highlight-current-green.current-fragment { + color: #17ff2e; +} +.reveal .slides section .fragment.highlight-current-blue.current-fragment { + color: #1b91ff; +} + + +/********************************************* + * DEFAULT ELEMENT STYLES + *********************************************/ + +/* Fixes issue in Chrome where italic fonts did not appear when printing to PDF */ +.reveal:after { + content: ''; + font-style: italic; +} + +.reveal iframe { + z-index: 1; +} + +/** Prevents layering issues in certain browser/transition combinations */ +.reveal a { + position: relative; +} + +.reveal .stretch { + max-width: none; + max-height: none; +} + +.reveal pre.stretch code { + height: 100%; + max-height: 100%; + box-sizing: border-box; +} + + +/********************************************* + * CONTROLS + *********************************************/ + +@keyframes bounce-right { + 0%, 10%, 25%, 40%, 50% {transform: translateX(0);} + 20% {transform: translateX(10px);} + 30% {transform: translateX(-5px);} +} + +@keyframes bounce-down { + 0%, 10%, 25%, 40%, 50% {transform: translateY(0);} + 20% {transform: translateY(10px);} + 30% {transform: translateY(-5px);} +} + +$controlArrowSize: 3.6em; +$controlArrowSpacing: 1.4em; +$controlArrowLength: 2.6em; +$controlArrowThickness: 0.5em; +$controlsArrowAngle: 45deg; +$controlsArrowAngleHover: 40deg; +$controlsArrowAngleActive: 36deg; + +@mixin controlsArrowTransform( $angle ) { + &:before { + transform: translateX(($controlArrowSize - $controlArrowLength)/2) translateY(($controlArrowSize - $controlArrowThickness)/2) rotate( $angle ); + } + + &:after { + transform: translateX(($controlArrowSize - $controlArrowLength)/2) translateY(($controlArrowSize - $controlArrowThickness)/2) rotate( -$angle ); + } +} + +.reveal .controls { + $spacing: 12px; + + display: none; + position: absolute; + top: auto; + bottom: $spacing; + right: $spacing; + left: auto; + z-index: 11; + color: #000; + pointer-events: none; + font-size: 10px; + + button { + position: absolute; + padding: 0; + background-color: transparent; + border: 0; + outline: 0; + cursor: pointer; + color: currentColor; + transform: scale(.9999); + transition: color 0.2s ease, + opacity 0.2s ease, + transform 0.2s ease; + z-index: 2; // above slides + pointer-events: auto; + font-size: inherit; + + visibility: hidden; + opacity: 0; + + -webkit-appearance: none; + -webkit-tap-highlight-color: rgba( 0, 0, 0, 0 ); + } + + .controls-arrow:before, + .controls-arrow:after { + content: ''; + position: absolute; + top: 0; + left: 0; + width: $controlArrowLength; + height: $controlArrowThickness; + border-radius: $controlArrowThickness/2; + background-color: currentColor; + + transition: all 0.15s ease, background-color 0.8s ease; + transform-origin: floor(($controlArrowThickness/2)*10)/10 50%; + will-change: transform; + } + + .controls-arrow { + position: relative; + width: $controlArrowSize; + height: $controlArrowSize; + + @include controlsArrowTransform( $controlsArrowAngle ); + + &:hover { + @include controlsArrowTransform( $controlsArrowAngleHover ); + } + + &:active { + @include controlsArrowTransform( $controlsArrowAngleActive ); + } + } + + .navigate-left { + right: $controlArrowSize + $controlArrowSpacing*2; + bottom: $controlArrowSpacing + $controlArrowSize/2; + transform: translateX( -10px ); + } + + .navigate-right { + right: 0; + bottom: $controlArrowSpacing + $controlArrowSize/2; + transform: translateX( 10px ); + + .controls-arrow { + transform: rotate( 180deg ); + } + + &.highlight { + animation: bounce-right 2s 50 both ease-out; + } + } + + .navigate-up { + right: $controlArrowSpacing + $controlArrowSize/2; + bottom: $controlArrowSpacing*2 + $controlArrowSize; + transform: translateY( -10px ); + + .controls-arrow { + transform: rotate( 90deg ); + } + } + + .navigate-down { + right: $controlArrowSpacing + $controlArrowSize/2; + bottom: -$controlArrowSpacing; + padding-bottom: $controlArrowSpacing; + transform: translateY( 10px ); + + .controls-arrow { + transform: rotate( -90deg ); + } + + &.highlight { + animation: bounce-down 2s 50 both ease-out; + } + } + + // Back arrow style: "faded": + // Deemphasize backwards navigation arrows in favor of drawing + // attention to forwards navigation + &[data-controls-back-arrows="faded"] .navigate-left.enabled, + &[data-controls-back-arrows="faded"] .navigate-up.enabled { + opacity: 0.3; + + &:hover { + opacity: 1; + } + } + + // Back arrow style: "hidden": + // Never show arrows for backwards navigation + &[data-controls-back-arrows="hidden"] .navigate-left.enabled, + &[data-controls-back-arrows="hidden"] .navigate-up.enabled { + opacity: 0; + visibility: hidden; + } + + // Any control button that can be clicked is "enabled" + .enabled { + visibility: visible; + opacity: 0.9; + cursor: pointer; + transform: none; + } + + // Any control button that leads to showing or hiding + // a fragment + .enabled.fragmented { + opacity: 0.5; + } + + .enabled:hover, + .enabled.fragmented:hover { + opacity: 1; + } +} + +.reveal[data-navigation-mode="linear"].has-horizontal-slides .navigate-up, +.reveal[data-navigation-mode="linear"].has-horizontal-slides .navigate-down { + display: none; +} + +// Adjust the layout when there are no vertical slides +.reveal[data-navigation-mode="linear"].has-horizontal-slides .navigate-left, +.reveal:not(.has-vertical-slides) .controls .navigate-left { + bottom: $controlArrowSpacing; + right: 0.5em + $controlArrowSpacing + $controlArrowSize; +} + +.reveal[data-navigation-mode="linear"].has-horizontal-slides .navigate-right, +.reveal:not(.has-vertical-slides) .controls .navigate-right { + bottom: $controlArrowSpacing; + right: 0.5em; +} + +// Adjust the layout when there are no horizontal slides +.reveal:not(.has-horizontal-slides) .controls .navigate-up { + right: $controlArrowSpacing; + bottom: $controlArrowSpacing + $controlArrowSize; +} +.reveal:not(.has-horizontal-slides) .controls .navigate-down { + right: $controlArrowSpacing; + bottom: 0.5em; +} + +// Invert arrows based on background color +.reveal.has-dark-background .controls { + color: #fff; +} +.reveal.has-light-background .controls { + color: #000; +} + +// Disable active states on touch devices +.reveal.no-hover .controls .controls-arrow:hover, +.reveal.no-hover .controls .controls-arrow:active { + @include controlsArrowTransform( $controlsArrowAngle ); +} + +// Edge aligned controls layout +@media screen and (min-width: 500px) { + + $spacing: 0.8em; + + .reveal .controls[data-controls-layout="edges"] { + & { + top: 0; + right: 0; + bottom: 0; + left: 0; + } + + .navigate-left, + .navigate-right, + .navigate-up, + .navigate-down { + bottom: auto; + right: auto; + } + + .navigate-left { + top: 50%; + left: $spacing; + margin-top: -$controlArrowSize/2; + } + + .navigate-right { + top: 50%; + right: $spacing; + margin-top: -$controlArrowSize/2; + } + + .navigate-up { + top: $spacing; + left: 50%; + margin-left: -$controlArrowSize/2; + } + + .navigate-down { + bottom: $spacing - $controlArrowSpacing + 0.3em; + left: 50%; + margin-left: -$controlArrowSize/2; + } + } + +} + + +/********************************************* + * PROGRESS BAR + *********************************************/ + +.reveal .progress { + position: absolute; + display: none; + height: 3px; + width: 100%; + bottom: 0; + left: 0; + z-index: 10; + + background-color: rgba( 0, 0, 0, 0.2 ); + color: #fff; +} + .reveal .progress:after { + content: ''; + display: block; + position: absolute; + height: 10px; + width: 100%; + top: -10px; + } + .reveal .progress span { + display: block; + height: 100%; + width: 0px; + + background-color: currentColor; + transition: width 800ms cubic-bezier(0.260, 0.860, 0.440, 0.985); + } + +/********************************************* + * SLIDE NUMBER + *********************************************/ + +.reveal .slide-number { + position: absolute; + display: block; + right: 8px; + bottom: 8px; + z-index: 31; + font-family: Helvetica, sans-serif; + font-size: 12px; + line-height: 1; + color: #fff; + background-color: rgba( 0, 0, 0, 0.4 ); + padding: 5px; +} + +.reveal .slide-number a { + color: currentColor; +} + +.reveal .slide-number-delimiter { + margin: 0 3px; +} + +/********************************************* + * SLIDES + *********************************************/ + +.reveal { + position: relative; + width: 100%; + height: 100%; + overflow: hidden; + touch-action: pinch-zoom; +} + +.reveal .slides { + position: absolute; + width: 100%; + height: 100%; + top: 0; + right: 0; + bottom: 0; + left: 0; + margin: auto; + pointer-events: none; + + overflow: visible; + z-index: 1; + text-align: center; + perspective: 600px; + perspective-origin: 50% 40%; +} + +.reveal .slides>section { + perspective: 600px; +} + +.reveal .slides>section, +.reveal .slides>section>section { + display: none; + position: absolute; + width: 100%; + padding: 20px 0px; + pointer-events: auto; + + z-index: 10; + transform-style: flat; + transition: transform-origin 800ms cubic-bezier(0.260, 0.860, 0.440, 0.985), + transform 800ms cubic-bezier(0.260, 0.860, 0.440, 0.985), + visibility 800ms cubic-bezier(0.260, 0.860, 0.440, 0.985), + opacity 800ms cubic-bezier(0.260, 0.860, 0.440, 0.985); +} + +/* Global transition speed settings */ +.reveal[data-transition-speed="fast"] .slides section { + transition-duration: 400ms; +} +.reveal[data-transition-speed="slow"] .slides section { + transition-duration: 1200ms; +} + +/* Slide-specific transition speed overrides */ +.reveal .slides section[data-transition-speed="fast"] { + transition-duration: 400ms; +} +.reveal .slides section[data-transition-speed="slow"] { + transition-duration: 1200ms; +} + +.reveal .slides>section.stack { + padding-top: 0; + padding-bottom: 0; + pointer-events: none; + height: 100%; +} + +.reveal .slides>section.present, +.reveal .slides>section>section.present { + display: block; + z-index: 11; + opacity: 1; +} + +.reveal .slides>section:empty, +.reveal .slides>section>section:empty, +.reveal .slides>section[data-background-interactive], +.reveal .slides>section>section[data-background-interactive] { + pointer-events: none; +} + +.reveal.center, +.reveal.center .slides, +.reveal.center .slides section { + min-height: 0 !important; +} + +/* Don't allow interaction with invisible slides */ +.reveal .slides>section.future, +.reveal .slides>section>section.future, +.reveal .slides>section.past, +.reveal .slides>section>section.past { + pointer-events: none; +} + +.reveal.overview .slides>section, +.reveal.overview .slides>section>section { + pointer-events: auto; +} + +.reveal .slides>section.past, +.reveal .slides>section.future, +.reveal .slides>section>section.past, +.reveal .slides>section>section.future { + opacity: 0; +} + + +/********************************************* + * Mixins for readability of transitions + *********************************************/ + +@mixin transition-global($style) { + .reveal .slides section[data-transition=#{$style}], + .reveal.#{$style} .slides section:not([data-transition]) { + @content; + } +} +@mixin transition-stack($style) { + .reveal .slides section[data-transition=#{$style}].stack, + .reveal.#{$style} .slides section.stack { + @content; + } +} +@mixin transition-horizontal-past($style) { + .reveal .slides>section[data-transition=#{$style}].past, + .reveal .slides>section[data-transition~=#{$style}-out].past, + .reveal.#{$style} .slides>section:not([data-transition]).past { + @content; + } +} +@mixin transition-horizontal-future($style) { + .reveal .slides>section[data-transition=#{$style}].future, + .reveal .slides>section[data-transition~=#{$style}-in].future, + .reveal.#{$style} .slides>section:not([data-transition]).future { + @content; + } +} + +@mixin transition-vertical-past($style) { + .reveal .slides>section>section[data-transition=#{$style}].past, + .reveal .slides>section>section[data-transition~=#{$style}-out].past, + .reveal.#{$style} .slides>section>section:not([data-transition]).past { + @content; + } +} +@mixin transition-vertical-future($style) { + .reveal .slides>section>section[data-transition=#{$style}].future, + .reveal .slides>section>section[data-transition~=#{$style}-in].future, + .reveal.#{$style} .slides>section>section:not([data-transition]).future { + @content; + } +} + +/********************************************* + * SLIDE TRANSITION + * Aliased 'linear' for backwards compatibility + *********************************************/ + +@each $stylename in slide, linear { + .reveal.#{$stylename} section { + backface-visibility: hidden; + } + @include transition-horizontal-past(#{$stylename}) { + transform: translate(-150%, 0); + } + @include transition-horizontal-future(#{$stylename}) { + transform: translate(150%, 0); + } + @include transition-vertical-past(#{$stylename}) { + transform: translate(0, -150%); + } + @include transition-vertical-future(#{$stylename}) { + transform: translate(0, 150%); + } +} + +/********************************************* + * CONVEX TRANSITION + * Aliased 'default' for backwards compatibility + *********************************************/ + +@each $stylename in default, convex { + @include transition-stack(#{$stylename}) { + transform-style: preserve-3d; + } + + @include transition-horizontal-past(#{$stylename}) { + transform: translate3d(-100%, 0, 0) rotateY(-90deg) translate3d(-100%, 0, 0); + } + @include transition-horizontal-future(#{$stylename}) { + transform: translate3d(100%, 0, 0) rotateY(90deg) translate3d(100%, 0, 0); + } + @include transition-vertical-past(#{$stylename}) { + transform: translate3d(0, -300px, 0) rotateX(70deg) translate3d(0, -300px, 0); + } + @include transition-vertical-future(#{$stylename}) { + transform: translate3d(0, 300px, 0) rotateX(-70deg) translate3d(0, 300px, 0); + } +} + +/********************************************* + * CONCAVE TRANSITION + *********************************************/ + +@include transition-stack(concave) { + transform-style: preserve-3d; +} + +@include transition-horizontal-past(concave) { + transform: translate3d(-100%, 0, 0) rotateY(90deg) translate3d(-100%, 0, 0); +} +@include transition-horizontal-future(concave) { + transform: translate3d(100%, 0, 0) rotateY(-90deg) translate3d(100%, 0, 0); +} +@include transition-vertical-past(concave) { + transform: translate3d(0, -80%, 0) rotateX(-70deg) translate3d(0, -80%, 0); +} +@include transition-vertical-future(concave) { + transform: translate3d(0, 80%, 0) rotateX(70deg) translate3d(0, 80%, 0); +} + + +/********************************************* + * ZOOM TRANSITION + *********************************************/ + +@include transition-global(zoom) { + transition-timing-function: ease; +} +@include transition-horizontal-past(zoom) { + visibility: hidden; + transform: scale(16); +} +@include transition-horizontal-future(zoom) { + visibility: hidden; + transform: scale(0.2); +} +@include transition-vertical-past(zoom) { + transform: scale(16); +} +@include transition-vertical-future(zoom) { + transform: scale(0.2); +} + + +/********************************************* + * CUBE TRANSITION + * + * WARNING: + * this is deprecated and will be removed in a + * future version. + *********************************************/ + +.reveal.cube .slides { + perspective: 1300px; +} + +.reveal.cube .slides section { + padding: 30px; + min-height: 700px; + backface-visibility: hidden; + box-sizing: border-box; + transform-style: preserve-3d; +} + .reveal.center.cube .slides section { + min-height: 0; + } + .reveal.cube .slides section:not(.stack):before { + content: ''; + position: absolute; + display: block; + width: 100%; + height: 100%; + left: 0; + top: 0; + background: rgba(0,0,0,0.1); + border-radius: 4px; + transform: translateZ( -20px ); + } + .reveal.cube .slides section:not(.stack):after { + content: ''; + position: absolute; + display: block; + width: 90%; + height: 30px; + left: 5%; + bottom: 0; + background: none; + z-index: 1; + + border-radius: 4px; + box-shadow: 0px 95px 25px rgba(0,0,0,0.2); + transform: translateZ(-90px) rotateX( 65deg ); + } + +.reveal.cube .slides>section.stack { + padding: 0; + background: none; +} + +.reveal.cube .slides>section.past { + transform-origin: 100% 0%; + transform: translate3d(-100%, 0, 0) rotateY(-90deg); +} + +.reveal.cube .slides>section.future { + transform-origin: 0% 0%; + transform: translate3d(100%, 0, 0) rotateY(90deg); +} + +.reveal.cube .slides>section>section.past { + transform-origin: 0% 100%; + transform: translate3d(0, -100%, 0) rotateX(90deg); +} + +.reveal.cube .slides>section>section.future { + transform-origin: 0% 0%; + transform: translate3d(0, 100%, 0) rotateX(-90deg); +} + + +/********************************************* + * PAGE TRANSITION + * + * WARNING: + * this is deprecated and will be removed in a + * future version. + *********************************************/ + +.reveal.page .slides { + perspective-origin: 0% 50%; + perspective: 3000px; +} + +.reveal.page .slides section { + padding: 30px; + min-height: 700px; + box-sizing: border-box; + transform-style: preserve-3d; +} + .reveal.page .slides section.past { + z-index: 12; + } + .reveal.page .slides section:not(.stack):before { + content: ''; + position: absolute; + display: block; + width: 100%; + height: 100%; + left: 0; + top: 0; + background: rgba(0,0,0,0.1); + transform: translateZ( -20px ); + } + .reveal.page .slides section:not(.stack):after { + content: ''; + position: absolute; + display: block; + width: 90%; + height: 30px; + left: 5%; + bottom: 0; + background: none; + z-index: 1; + + border-radius: 4px; + box-shadow: 0px 95px 25px rgba(0,0,0,0.2); + + -webkit-transform: translateZ(-90px) rotateX( 65deg ); + } + +.reveal.page .slides>section.stack { + padding: 0; + background: none; +} + +.reveal.page .slides>section.past { + transform-origin: 0% 0%; + transform: translate3d(-40%, 0, 0) rotateY(-80deg); +} + +.reveal.page .slides>section.future { + transform-origin: 100% 0%; + transform: translate3d(0, 0, 0); +} + +.reveal.page .slides>section>section.past { + transform-origin: 0% 0%; + transform: translate3d(0, -40%, 0) rotateX(80deg); +} + +.reveal.page .slides>section>section.future { + transform-origin: 0% 100%; + transform: translate3d(0, 0, 0); +} + + +/********************************************* + * FADE TRANSITION + *********************************************/ + +.reveal .slides section[data-transition=fade], +.reveal.fade .slides section:not([data-transition]), +.reveal.fade .slides>section>section:not([data-transition]) { + transform: none; + transition: opacity 0.5s; +} + + +.reveal.fade.overview .slides section, +.reveal.fade.overview .slides>section>section { + transition: none; +} + + +/********************************************* + * NO TRANSITION + *********************************************/ + +@include transition-global(none) { + transform: none; + transition: none; +} + + +/********************************************* + * PAUSED MODE + *********************************************/ + +.reveal .pause-overlay { + position: absolute; + top: 0; + left: 0; + width: 100%; + height: 100%; + background: black; + visibility: hidden; + opacity: 0; + z-index: 100; + transition: all 1s ease; +} + +.reveal .pause-overlay .resume-button { + position: absolute; + bottom: 20px; + right: 20px; + color: #ccc; + border-radius: 2px; + padding: 6px 14px; + border: 2px solid #ccc; + font-size: 16px; + background: transparent; + cursor: pointer; + + &:hover { + color: #fff; + border-color: #fff; + } +} + +.reveal.paused .pause-overlay { + visibility: visible; + opacity: 1; +} + + +/********************************************* + * FALLBACK + *********************************************/ + +.no-transforms { + overflow-y: auto; +} + +.no-transforms .reveal { + overflow: visible; +} + +.no-transforms .reveal .slides { + position: relative; + width: 80%; + max-width: 1280px; + height: auto; + top: 0; + margin: 0 auto; + text-align: center; +} + +.no-transforms .reveal .controls, +.no-transforms .reveal .progress { + display: none; +} + +.no-transforms .reveal .slides section { + display: block; + opacity: 1; + position: relative; + height: auto; + min-height: 0; + top: 0; + left: 0; + margin: 10vh 0; + margin: 70px 0; + transform: none; +} + +.reveal .no-transition, +.reveal .no-transition * { + transition: none !important; +} + + +/********************************************* + * PER-SLIDE BACKGROUNDS + *********************************************/ + +.reveal .backgrounds { + position: absolute; + width: 100%; + height: 100%; + top: 0; + left: 0; + perspective: 600px; +} + .reveal .slide-background { + display: none; + position: absolute; + width: 100%; + height: 100%; + opacity: 0; + visibility: hidden; + overflow: hidden; + + background-color: rgba( 0, 0, 0, 0 ); + + transition: all 800ms cubic-bezier(0.260, 0.860, 0.440, 0.985); + } + + .reveal .slide-background-content { + position: absolute; + width: 100%; + height: 100%; + + background-position: 50% 50%; + background-repeat: no-repeat; + background-size: cover; + } + + .reveal .slide-background.stack { + display: block; + } + + .reveal .slide-background.present { + opacity: 1; + visibility: visible; + z-index: 2; + } + + .print-pdf .reveal .slide-background { + opacity: 1 !important; + visibility: visible !important; + } + +/* Video backgrounds */ +.reveal .slide-background video { + position: absolute; + width: 100%; + height: 100%; + max-width: none; + max-height: none; + top: 0; + left: 0; + object-fit: cover; +} + .reveal .slide-background[data-background-size="contain"] video { + object-fit: contain; + } + +/* Immediate transition style */ +.reveal[data-background-transition=none]>.backgrounds .slide-background, +.reveal>.backgrounds .slide-background[data-background-transition=none] { + transition: none; +} + +/* Slide */ +.reveal[data-background-transition=slide]>.backgrounds .slide-background, +.reveal>.backgrounds .slide-background[data-background-transition=slide] { + opacity: 1; + backface-visibility: hidden; +} + .reveal[data-background-transition=slide]>.backgrounds .slide-background.past, + .reveal>.backgrounds .slide-background.past[data-background-transition=slide] { + transform: translate(-100%, 0); + } + .reveal[data-background-transition=slide]>.backgrounds .slide-background.future, + .reveal>.backgrounds .slide-background.future[data-background-transition=slide] { + transform: translate(100%, 0); + } + + .reveal[data-background-transition=slide]>.backgrounds .slide-background>.slide-background.past, + .reveal>.backgrounds .slide-background>.slide-background.past[data-background-transition=slide] { + transform: translate(0, -100%); + } + .reveal[data-background-transition=slide]>.backgrounds .slide-background>.slide-background.future, + .reveal>.backgrounds .slide-background>.slide-background.future[data-background-transition=slide] { + transform: translate(0, 100%); + } + + +/* Convex */ +.reveal[data-background-transition=convex]>.backgrounds .slide-background.past, +.reveal>.backgrounds .slide-background.past[data-background-transition=convex] { + opacity: 0; + transform: translate3d(-100%, 0, 0) rotateY(-90deg) translate3d(-100%, 0, 0); +} +.reveal[data-background-transition=convex]>.backgrounds .slide-background.future, +.reveal>.backgrounds .slide-background.future[data-background-transition=convex] { + opacity: 0; + transform: translate3d(100%, 0, 0) rotateY(90deg) translate3d(100%, 0, 0); +} + +.reveal[data-background-transition=convex]>.backgrounds .slide-background>.slide-background.past, +.reveal>.backgrounds .slide-background>.slide-background.past[data-background-transition=convex] { + opacity: 0; + transform: translate3d(0, -100%, 0) rotateX(90deg) translate3d(0, -100%, 0); +} +.reveal[data-background-transition=convex]>.backgrounds .slide-background>.slide-background.future, +.reveal>.backgrounds .slide-background>.slide-background.future[data-background-transition=convex] { + opacity: 0; + transform: translate3d(0, 100%, 0) rotateX(-90deg) translate3d(0, 100%, 0); +} + + +/* Concave */ +.reveal[data-background-transition=concave]>.backgrounds .slide-background.past, +.reveal>.backgrounds .slide-background.past[data-background-transition=concave] { + opacity: 0; + transform: translate3d(-100%, 0, 0) rotateY(90deg) translate3d(-100%, 0, 0); +} +.reveal[data-background-transition=concave]>.backgrounds .slide-background.future, +.reveal>.backgrounds .slide-background.future[data-background-transition=concave] { + opacity: 0; + transform: translate3d(100%, 0, 0) rotateY(-90deg) translate3d(100%, 0, 0); +} + +.reveal[data-background-transition=concave]>.backgrounds .slide-background>.slide-background.past, +.reveal>.backgrounds .slide-background>.slide-background.past[data-background-transition=concave] { + opacity: 0; + transform: translate3d(0, -100%, 0) rotateX(-90deg) translate3d(0, -100%, 0); +} +.reveal[data-background-transition=concave]>.backgrounds .slide-background>.slide-background.future, +.reveal>.backgrounds .slide-background>.slide-background.future[data-background-transition=concave] { + opacity: 0; + transform: translate3d(0, 100%, 0) rotateX(90deg) translate3d(0, 100%, 0); +} + +/* Zoom */ +.reveal[data-background-transition=zoom]>.backgrounds .slide-background, +.reveal>.backgrounds .slide-background[data-background-transition=zoom] { + transition-timing-function: ease; +} + +.reveal[data-background-transition=zoom]>.backgrounds .slide-background.past, +.reveal>.backgrounds .slide-background.past[data-background-transition=zoom] { + opacity: 0; + visibility: hidden; + transform: scale(16); +} +.reveal[data-background-transition=zoom]>.backgrounds .slide-background.future, +.reveal>.backgrounds .slide-background.future[data-background-transition=zoom] { + opacity: 0; + visibility: hidden; + transform: scale(0.2); +} + +.reveal[data-background-transition=zoom]>.backgrounds .slide-background>.slide-background.past, +.reveal>.backgrounds .slide-background>.slide-background.past[data-background-transition=zoom] { + opacity: 0; + visibility: hidden; + transform: scale(16); +} +.reveal[data-background-transition=zoom]>.backgrounds .slide-background>.slide-background.future, +.reveal>.backgrounds .slide-background>.slide-background.future[data-background-transition=zoom] { + opacity: 0; + visibility: hidden; + transform: scale(0.2); +} + + +/* Global transition speed settings */ +.reveal[data-transition-speed="fast"]>.backgrounds .slide-background { + transition-duration: 400ms; +} +.reveal[data-transition-speed="slow"]>.backgrounds .slide-background { + transition-duration: 1200ms; +} + + +/********************************************* + * OVERVIEW + *********************************************/ + +.reveal.overview { + perspective-origin: 50% 50%; + perspective: 700px; + + .slides { + // Fixes overview rendering errors in FF48+, not applied to + // other browsers since it degrades performance + -moz-transform-style: preserve-3d; + } + + .slides section { + height: 100%; + top: 0 !important; + opacity: 1 !important; + overflow: hidden; + visibility: visible !important; + cursor: pointer; + box-sizing: border-box; + } + .slides section:hover, + .slides section.present { + outline: 10px solid rgba(150,150,150,0.4); + outline-offset: 10px; + } + .slides section .fragment { + opacity: 1; + transition: none; + } + .slides section:after, + .slides section:before { + display: none !important; + } + .slides>section.stack { + padding: 0; + top: 0 !important; + background: none; + outline: none; + overflow: visible; + } + + .backgrounds { + perspective: inherit; + + // Fixes overview rendering errors in FF48+, not applied to + // other browsers since it degrades performance + -moz-transform-style: preserve-3d; + } + + .backgrounds .slide-background { + opacity: 1; + visibility: visible; + + // This can't be applied to the slide itself in Safari + outline: 10px solid rgba(150,150,150,0.1); + outline-offset: 10px; + } + + .backgrounds .slide-background.stack { + overflow: visible; + } +} + +// Disable transitions transitions while we're activating +// or deactivating the overview mode. +.reveal.overview .slides section, +.reveal.overview-deactivating .slides section { + transition: none; +} + +.reveal.overview .backgrounds .slide-background, +.reveal.overview-deactivating .backgrounds .slide-background { + transition: none; +} + + +/********************************************* + * RTL SUPPORT + *********************************************/ + +.reveal.rtl .slides, +.reveal.rtl .slides h1, +.reveal.rtl .slides h2, +.reveal.rtl .slides h3, +.reveal.rtl .slides h4, +.reveal.rtl .slides h5, +.reveal.rtl .slides h6 { + direction: rtl; + font-family: sans-serif; +} + +.reveal.rtl pre, +.reveal.rtl code { + direction: ltr; +} + +.reveal.rtl ol, +.reveal.rtl ul { + text-align: right; +} + +.reveal.rtl .progress span { + float: right +} + +/********************************************* + * PARALLAX BACKGROUND + *********************************************/ + +.reveal.has-parallax-background .backgrounds { + transition: all 0.8s ease; +} + +/* Global transition speed settings */ +.reveal.has-parallax-background[data-transition-speed="fast"] .backgrounds { + transition-duration: 400ms; +} +.reveal.has-parallax-background[data-transition-speed="slow"] .backgrounds { + transition-duration: 1200ms; +} + + +/********************************************* + * OVERLAY FOR LINK PREVIEWS AND HELP + *********************************************/ + +.reveal > .overlay { + position: absolute; + top: 0; + left: 0; + width: 100%; + height: 100%; + z-index: 1000; + background: rgba( 0, 0, 0, 0.9 ); + opacity: 0; + visibility: hidden; + transition: all 0.3s ease; +} + .reveal > .overlay.visible { + opacity: 1; + visibility: visible; + } + + .reveal > .overlay .spinner { + position: absolute; + display: block; + top: 50%; + left: 50%; + width: 32px; + height: 32px; + margin: -16px 0 0 -16px; + z-index: 10; + background-image: url(data:image/gif;base64,R0lGODlhIAAgAPMAAJmZmf%2F%2F%2F6%2Bvr8nJybW1tcDAwOjo6Nvb26ioqKOjo7Ozs%2FLy8vz8%2FAAAAAAAAAAAACH%2FC05FVFNDQVBFMi4wAwEAAAAh%2FhpDcmVhdGVkIHdpdGggYWpheGxvYWQuaW5mbwAh%2BQQJCgAAACwAAAAAIAAgAAAE5xDISWlhperN52JLhSSdRgwVo1ICQZRUsiwHpTJT4iowNS8vyW2icCF6k8HMMBkCEDskxTBDAZwuAkkqIfxIQyhBQBFvAQSDITM5VDW6XNE4KagNh6Bgwe60smQUB3d4Rz1ZBApnFASDd0hihh12BkE9kjAJVlycXIg7CQIFA6SlnJ87paqbSKiKoqusnbMdmDC2tXQlkUhziYtyWTxIfy6BE8WJt5YJvpJivxNaGmLHT0VnOgSYf0dZXS7APdpB309RnHOG5gDqXGLDaC457D1zZ%2FV%2FnmOM82XiHRLYKhKP1oZmADdEAAAh%2BQQJCgAAACwAAAAAIAAgAAAE6hDISWlZpOrNp1lGNRSdRpDUolIGw5RUYhhHukqFu8DsrEyqnWThGvAmhVlteBvojpTDDBUEIFwMFBRAmBkSgOrBFZogCASwBDEY%2FCZSg7GSE0gSCjQBMVG023xWBhklAnoEdhQEfyNqMIcKjhRsjEdnezB%2BA4k8gTwJhFuiW4dokXiloUepBAp5qaKpp6%2BHo7aWW54wl7obvEe0kRuoplCGepwSx2jJvqHEmGt6whJpGpfJCHmOoNHKaHx61WiSR92E4lbFoq%2BB6QDtuetcaBPnW6%2BO7wDHpIiK9SaVK5GgV543tzjgGcghAgAh%2BQQJCgAAACwAAAAAIAAgAAAE7hDISSkxpOrN5zFHNWRdhSiVoVLHspRUMoyUakyEe8PTPCATW9A14E0UvuAKMNAZKYUZCiBMuBakSQKG8G2FzUWox2AUtAQFcBKlVQoLgQReZhQlCIJesQXI5B0CBnUMOxMCenoCfTCEWBsJColTMANldx15BGs8B5wlCZ9Po6OJkwmRpnqkqnuSrayqfKmqpLajoiW5HJq7FL1Gr2mMMcKUMIiJgIemy7xZtJsTmsM4xHiKv5KMCXqfyUCJEonXPN2rAOIAmsfB3uPoAK%2B%2BG%2Bw48edZPK%2BM6hLJpQg484enXIdQFSS1u6UhksENEQAAIfkECQoAAAAsAAAAACAAIAAABOcQyEmpGKLqzWcZRVUQnZYg1aBSh2GUVEIQ2aQOE%2BG%2BcD4ntpWkZQj1JIiZIogDFFyHI0UxQwFugMSOFIPJftfVAEoZLBbcLEFhlQiqGp1Vd140AUklUN3eCA51C1EWMzMCezCBBmkxVIVHBWd3HHl9JQOIJSdSnJ0TDKChCwUJjoWMPaGqDKannasMo6WnM562R5YluZRwur0wpgqZE7NKUm%2BFNRPIhjBJxKZteWuIBMN4zRMIVIhffcgojwCF117i4nlLnY5ztRLsnOk%2BaV%2BoJY7V7m76PdkS4trKcdg0Zc0tTcKkRAAAIfkECQoAAAAsAAAAACAAIAAABO4QyEkpKqjqzScpRaVkXZWQEximw1BSCUEIlDohrft6cpKCk5xid5MNJTaAIkekKGQkWyKHkvhKsR7ARmitkAYDYRIbUQRQjWBwJRzChi9CRlBcY1UN4g0%2FVNB0AlcvcAYHRyZPdEQFYV8ccwR5HWxEJ02YmRMLnJ1xCYp0Y5idpQuhopmmC2KgojKasUQDk5BNAwwMOh2RtRq5uQuPZKGIJQIGwAwGf6I0JXMpC8C7kXWDBINFMxS4DKMAWVWAGYsAdNqW5uaRxkSKJOZKaU3tPOBZ4DuK2LATgJhkPJMgTwKCdFjyPHEnKxFCDhEAACH5BAkKAAAALAAAAAAgACAAAATzEMhJaVKp6s2nIkolIJ2WkBShpkVRWqqQrhLSEu9MZJKK9y1ZrqYK9WiClmvoUaF8gIQSNeF1Er4MNFn4SRSDARWroAIETg1iVwuHjYB1kYc1mwruwXKC9gmsJXliGxc%2BXiUCby9ydh1sOSdMkpMTBpaXBzsfhoc5l58Gm5yToAaZhaOUqjkDgCWNHAULCwOLaTmzswadEqggQwgHuQsHIoZCHQMMQgQGubVEcxOPFAcMDAYUA85eWARmfSRQCdcMe0zeP1AAygwLlJtPNAAL19DARdPzBOWSm1brJBi45soRAWQAAkrQIykShQ9wVhHCwCQCACH5BAkKAAAALAAAAAAgACAAAATrEMhJaVKp6s2nIkqFZF2VIBWhUsJaTokqUCoBq%2BE71SRQeyqUToLA7VxF0JDyIQh%2FMVVPMt1ECZlfcjZJ9mIKoaTl1MRIl5o4CUKXOwmyrCInCKqcWtvadL2SYhyASyNDJ0uIiRMDjI0Fd30%2FiI2UA5GSS5UDj2l6NoqgOgN4gksEBgYFf0FDqKgHnyZ9OX8HrgYHdHpcHQULXAS2qKpENRg7eAMLC7kTBaixUYFkKAzWAAnLC7FLVxLWDBLKCwaKTULgEwbLA4hJtOkSBNqITT3xEgfLpBtzE%2FjiuL04RGEBgwWhShRgQExHBAAh%2BQQJCgAAACwAAAAAIAAgAAAE7xDISWlSqerNpyJKhWRdlSAVoVLCWk6JKlAqAavhO9UkUHsqlE6CwO1cRdCQ8iEIfzFVTzLdRAmZX3I2SfZiCqGk5dTESJeaOAlClzsJsqwiJwiqnFrb2nS9kmIcgEsjQydLiIlHehhpejaIjzh9eomSjZR%2BipslWIRLAgMDOR2DOqKogTB9pCUJBagDBXR6XB0EBkIIsaRsGGMMAxoDBgYHTKJiUYEGDAzHC9EACcUGkIgFzgwZ0QsSBcXHiQvOwgDdEwfFs0sDzt4S6BK4xYjkDOzn0unFeBzOBijIm1Dgmg5YFQwsCMjp1oJ8LyIAACH5BAkKAAAALAAAAAAgACAAAATwEMhJaVKp6s2nIkqFZF2VIBWhUsJaTokqUCoBq%2BE71SRQeyqUToLA7VxF0JDyIQh%2FMVVPMt1ECZlfcjZJ9mIKoaTl1MRIl5o4CUKXOwmyrCInCKqcWtvadL2SYhyASyNDJ0uIiUd6GGl6NoiPOH16iZKNlH6KmyWFOggHhEEvAwwMA0N9GBsEC6amhnVcEwavDAazGwIDaH1ipaYLBUTCGgQDA8NdHz0FpqgTBwsLqAbWAAnIA4FWKdMLGdYGEgraigbT0OITBcg5QwPT4xLrROZL6AuQAPUS7bxLpoWidY0JtxLHKhwwMJBTHgPKdEQAACH5BAkKAAAALAAAAAAgACAAAATrEMhJaVKp6s2nIkqFZF2VIBWhUsJaTokqUCoBq%2BE71SRQeyqUToLA7VxF0JDyIQh%2FMVVPMt1ECZlfcjZJ9mIKoaTl1MRIl5o4CUKXOwmyrCInCKqcWtvadL2SYhyASyNDJ0uIiUd6GAULDJCRiXo1CpGXDJOUjY%2BYip9DhToJA4RBLwMLCwVDfRgbBAaqqoZ1XBMHswsHtxtFaH1iqaoGNgAIxRpbFAgfPQSqpbgGBqUD1wBXeCYp1AYZ19JJOYgH1KwA4UBvQwXUBxPqVD9L3sbp2BNk2xvvFPJd%2BMFCN6HAAIKgNggY0KtEBAAh%2BQQJCgAAACwAAAAAIAAgAAAE6BDISWlSqerNpyJKhWRdlSAVoVLCWk6JKlAqAavhO9UkUHsqlE6CwO1cRdCQ8iEIfzFVTzLdRAmZX3I2SfYIDMaAFdTESJeaEDAIMxYFqrOUaNW4E4ObYcCXaiBVEgULe0NJaxxtYksjh2NLkZISgDgJhHthkpU4mW6blRiYmZOlh4JWkDqILwUGBnE6TYEbCgevr0N1gH4At7gHiRpFaLNrrq8HNgAJA70AWxQIH1%2BvsYMDAzZQPC9VCNkDWUhGkuE5PxJNwiUK4UfLzOlD4WvzAHaoG9nxPi5d%2BjYUqfAhhykOFwJWiAAAIfkECQoAAAAsAAAAACAAIAAABPAQyElpUqnqzaciSoVkXVUMFaFSwlpOCcMYlErAavhOMnNLNo8KsZsMZItJEIDIFSkLGQoQTNhIsFehRww2CQLKF0tYGKYSg%2BygsZIuNqJksKgbfgIGepNo2cIUB3V1B3IvNiBYNQaDSTtfhhx0CwVPI0UJe0%2Bbm4g5VgcGoqOcnjmjqDSdnhgEoamcsZuXO1aWQy8KAwOAuTYYGwi7w5h%2BKr0SJ8MFihpNbx%2B4Erq7BYBuzsdiH1jCAzoSfl0rVirNbRXlBBlLX%2BBP0XJLAPGzTkAuAOqb0WT5AH7OcdCm5B8TgRwSRKIHQtaLCwg1RAAAOwAAAAAAAAAAAA%3D%3D); + + visibility: visible; + opacity: 0.6; + transition: all 0.3s ease; + } + + .reveal > .overlay header { + position: absolute; + left: 0; + top: 0; + width: 100%; + height: 40px; + z-index: 2; + border-bottom: 1px solid #222; + } + .reveal > .overlay header a { + display: inline-block; + width: 40px; + height: 40px; + line-height: 36px; + padding: 0 10px; + float: right; + opacity: 0.6; + + box-sizing: border-box; + } + .reveal > .overlay header a:hover { + opacity: 1; + } + .reveal > .overlay header a .icon { + display: inline-block; + width: 20px; + height: 20px; + + background-position: 50% 50%; + background-size: 100%; + background-repeat: no-repeat; + } + .reveal > .overlay header a.close .icon { + background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAABkklEQVRYR8WX4VHDMAxG6wnoJrABZQPYBCaBTWAD2g1gE5gg6OOsXuxIlr40d81dfrSJ9V4c2VLK7spHuTJ/5wpM07QXuXc5X0opX2tEJcadjHuV80li/FgxTIEK/5QBCICBD6xEhSMGHgQPgBgLiYVAB1dpSqKDawxTohFw4JSEA3clzgIBPCURwE2JucBR7rhPJJv5OpJwDX+SfDjgx1wACQeJG1aChP9K/IMmdZ8DtESV1WyP3Bt4MwM6sj4NMxMYiqUWHQu4KYA/SYkIjOsm3BXYWMKFDwU2khjCQ4ELJUJ4SmClRArOCmSXGuKma0fYD5CbzHxFpCSGAhfAVSSUGDUk2BWZaff2g6GE15BsBQ9nwmpIGDiyHQddwNTMKkbZaf9fajXQca1EX44puJZUsnY0ObGmITE3GVLCbEhQUjGVt146j6oasWN+49Vph2w1pZ5EansNZqKBm1txbU57iRRcZ86RWMDdWtBJUHBHwoQPi1GV+JCbntmvok7iTX4/Up9mgyTc/FJYDTcndgH/AA5A/CHsyEkVAAAAAElFTkSuQmCC); + } + .reveal > .overlay header a.external .icon { + background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAAcElEQVRYR+2WSQoAIQwEzf8f7XiOMkUQxUPlGkM3hVmiQfQR9GYnH1SsAQlI4DiBqkCMoNb9y2e90IAEJPAcgdznU9+engMaeJ7Azh5Y1U67gAho4DqBqmB1buAf0MB1AlVBek83ZPkmJMGc1wAR+AAqod/B97TRpQAAAABJRU5ErkJggg==); + } + + .reveal > .overlay .viewport { + position: absolute; + display: flex; + top: 40px; + right: 0; + bottom: 0; + left: 0; + } + + .reveal > .overlay.overlay-preview .viewport iframe { + width: 100%; + height: 100%; + max-width: 100%; + max-height: 100%; + border: 0; + + opacity: 0; + visibility: hidden; + transition: all 0.3s ease; + } + + .reveal > .overlay.overlay-preview.loaded .viewport iframe { + opacity: 1; + visibility: visible; + } + + .reveal > .overlay.overlay-preview.loaded .viewport-inner { + position: absolute; + z-index: -1; + left: 0; + top: 45%; + width: 100%; + text-align: center; + letter-spacing: normal; + } + .reveal > .overlay.overlay-preview .x-frame-error { + opacity: 0; + transition: opacity 0.3s ease 0.3s; + } + .reveal > .overlay.overlay-preview.loaded .x-frame-error { + opacity: 1; + } + + .reveal > .overlay.overlay-preview.loaded .spinner { + opacity: 0; + visibility: hidden; + transform: scale(0.2); + } + + .reveal > .overlay.overlay-help .viewport { + overflow: auto; + color: #fff; + } + + .reveal > .overlay.overlay-help .viewport .viewport-inner { + width: 600px; + margin: auto; + padding: 20px 20px 80px 20px; + text-align: center; + letter-spacing: normal; + } + + .reveal > .overlay.overlay-help .viewport .viewport-inner .title { + font-size: 20px; + } + + .reveal > .overlay.overlay-help .viewport .viewport-inner table { + border: 1px solid #fff; + border-collapse: collapse; + font-size: 16px; + } + + .reveal > .overlay.overlay-help .viewport .viewport-inner table th, + .reveal > .overlay.overlay-help .viewport .viewport-inner table td { + width: 200px; + padding: 14px; + border: 1px solid #fff; + vertical-align: middle; + } + + .reveal > .overlay.overlay-help .viewport .viewport-inner table th { + padding-top: 20px; + padding-bottom: 20px; + } + + +/********************************************* + * PLAYBACK COMPONENT + *********************************************/ + +.reveal .playback { + position: absolute; + left: 15px; + bottom: 20px; + z-index: 30; + cursor: pointer; + transition: all 400ms ease; + -webkit-tap-highlight-color: rgba( 0, 0, 0, 0 ); +} + +.reveal.overview .playback { + opacity: 0; + visibility: hidden; +} + + +/********************************************* + * CODE HIGHLGIHTING + *********************************************/ + +.reveal .hljs table { + margin: initial; +} + +.reveal .hljs-ln-code, +.reveal .hljs-ln-numbers { + padding: 0; + border: 0; +} + +.reveal .hljs-ln-numbers { + opacity: 0.6; + padding-right: 0.75em; + text-align: right; + vertical-align: top; +} + +.reveal .hljs.has-highlights tr:not(.highlight-line) { + opacity: 0.4; +} + +.reveal .hljs:not(:first-child).fragment { + position: absolute; + top: 0; + left: 0; + width: 100%; + box-sizing: border-box; +} + + +/********************************************* + * ROLLING LINKS + *********************************************/ + +.reveal .roll { + display: inline-block; + line-height: 1.2; + overflow: hidden; + + vertical-align: top; + perspective: 400px; + perspective-origin: 50% 50%; +} + .reveal .roll:hover { + background: none; + text-shadow: none; + } +.reveal .roll span { + display: block; + position: relative; + padding: 0 2px; + + pointer-events: none; + transition: all 400ms ease; + transform-origin: 50% 0%; + transform-style: preserve-3d; + backface-visibility: hidden; +} + .reveal .roll:hover span { + background: rgba(0,0,0,0.5); + transform: translate3d( 0px, 0px, -45px ) rotateX( 90deg ); + } +.reveal .roll span:after { + content: attr(data-title); + + display: block; + position: absolute; + left: 0; + top: 0; + padding: 0 2px; + backface-visibility: hidden; + transform-origin: 50% 0%; + transform: translate3d( 0px, 110%, 0px ) rotateX( -90deg ); +} + + +/********************************************* + * SPEAKER NOTES + *********************************************/ + +$notesWidthPercent: 25%; + +// Hide on-page notes +.reveal aside.notes { + display: none; +} + +// An interface element that can optionally be used to show the +// speaker notes to all viewers, on top of the presentation +.reveal .speaker-notes { + display: none; + position: absolute; + width: $notesWidthPercent / (1-$notesWidthPercent/100) * 1%; + height: 100%; + top: 0; + left: 100%; + padding: 14px 18px 14px 18px; + z-index: 1; + font-size: 18px; + line-height: 1.4; + border: 1px solid rgba( 0, 0, 0, 0.05 ); + color: #222; + background-color: #f5f5f5; + overflow: auto; + box-sizing: border-box; + text-align: left; + font-family: Helvetica, sans-serif; + -webkit-overflow-scrolling: touch; + + .notes-placeholder { + color: #ccc; + font-style: italic; + } + + &:focus { + outline: none; + } + + &:before { + content: 'Speaker notes'; + display: block; + margin-bottom: 10px; + opacity: 0.5; + } +} + + +.reveal.show-notes { + max-width: 100% - $notesWidthPercent; + overflow: visible; +} + +.reveal.show-notes .speaker-notes { + display: block; +} + +@media screen and (min-width: 1600px) { + .reveal .speaker-notes { + font-size: 20px; + } +} + +@media screen and (max-width: 1024px) { + .reveal.show-notes { + border-left: 0; + max-width: none; + max-height: 70%; + max-height: 70vh; + overflow: visible; + } + + .reveal.show-notes .speaker-notes { + top: 100%; + left: 0; + width: 100%; + height: (30/0.7)*1%; + height: 30vh; + border: 0; + } +} + +@media screen and (max-width: 600px) { + .reveal.show-notes { + max-height: 60%; + max-height: 60vh; + } + + .reveal.show-notes .speaker-notes { + top: 100%; + height: (40/0.6)*1%; + height: 40vh; + } + + .reveal .speaker-notes { + font-size: 14px; + } +} + + +/********************************************* + * ZOOM PLUGIN + *********************************************/ + +.zoomed .reveal *, +.zoomed .reveal *:before, +.zoomed .reveal *:after { + backface-visibility: visible !important; +} + +.zoomed .reveal .progress, +.zoomed .reveal .controls { + opacity: 0; +} + +.zoomed .reveal .roll span { + background: none; +} + +.zoomed .reveal .roll span:after { + visibility: hidden; +} diff --git a/AdvancedCppV2/css/theme/README.md b/AdvancedCppV2/css/theme/README.md new file mode 100644 index 0000000..5ebe72a --- /dev/null +++ b/AdvancedCppV2/css/theme/README.md @@ -0,0 +1,21 @@ +## Dependencies + +Themes are written using Sass to keep things modular and reduce the need for repeated selectors across files. Make sure that you have the reveal.js development environment including the Grunt dependencies installed before proceeding: https://github.com/hakimel/reveal.js#full-setup + +## Creating a Theme + +To create your own theme, start by duplicating a ```.scss``` file in [/css/theme/source](https://github.com/hakimel/reveal.js/blob/master/css/theme/source). It will be automatically compiled by Grunt from Sass to CSS (see the [Gruntfile](https://github.com/hakimel/reveal.js/blob/master/gruntfile.js)) when you run `npm run build -- css-themes`. + +Each theme file does four things in the following order: + +1. **Include [/css/theme/template/mixins.scss](https://github.com/hakimel/reveal.js/blob/master/css/theme/template/mixins.scss)** +Shared utility functions. + +2. **Include [/css/theme/template/settings.scss](https://github.com/hakimel/reveal.js/blob/master/css/theme/template/settings.scss)** +Declares a set of custom variables that the template file (step 4) expects. Can be overridden in step 3. + +3. **Override** +This is where you override the default theme. Either by specifying variables (see [settings.scss](https://github.com/hakimel/reveal.js/blob/master/css/theme/template/settings.scss) for reference) or by adding any selectors and styles you please. + +4. **Include [/css/theme/template/theme.scss](https://github.com/hakimel/reveal.js/blob/master/css/theme/template/theme.scss)** +The template theme file which will generate final CSS output based on the currently defined variables. diff --git a/AdvancedCppV2/css/theme/beige.css b/AdvancedCppV2/css/theme/beige.css new file mode 100644 index 0000000..615dd6d --- /dev/null +++ b/AdvancedCppV2/css/theme/beige.css @@ -0,0 +1,277 @@ +/** + * Beige theme for reveal.js. + * + * Copyright (C) 2011-2012 Hakim El Hattab, http://hakim.se + */ +@import url(../../lib/font/league-gothic/league-gothic.css); +@import url(https://fonts.googleapis.com/css?family=Lato:400,700,400italic,700italic); +/********************************************* + * GLOBAL STYLES + *********************************************/ +body { + background: #f7f2d3; + background: -moz-radial-gradient(center, circle cover, white 0%, #f7f2d3 100%); + background: -webkit-gradient(radial, center center, 0px, center center, 100%, color-stop(0%, white), color-stop(100%, #f7f2d3)); + background: -webkit-radial-gradient(center, circle cover, white 0%, #f7f2d3 100%); + background: -o-radial-gradient(center, circle cover, white 0%, #f7f2d3 100%); + background: -ms-radial-gradient(center, circle cover, white 0%, #f7f2d3 100%); + background: radial-gradient(center, circle cover, white 0%, #f7f2d3 100%); + background-color: #f7f3de; } + +.reveal { + font-family: "Lato", sans-serif; + font-size: 40px; + font-weight: normal; + color: #333; } + +::selection { + color: #fff; + background: rgba(79, 64, 28, 0.99); + text-shadow: none; } + +::-moz-selection { + color: #fff; + background: rgba(79, 64, 28, 0.99); + text-shadow: none; } + +.reveal .slides section, +.reveal .slides section > section { + line-height: 1.3; + font-weight: inherit; } + +/********************************************* + * HEADERS + *********************************************/ +.reveal h1, +.reveal h2, +.reveal h3, +.reveal h4, +.reveal h5, +.reveal h6 { + margin: 0 0 20px 0; + color: #333; + font-family: "League Gothic", Impact, sans-serif; + font-weight: normal; + line-height: 1.2; + letter-spacing: normal; + text-transform: uppercase; + text-shadow: none; + word-wrap: break-word; } + +.reveal h1 { + font-size: 3.77em; } + +.reveal h2 { + font-size: 2.11em; } + +.reveal h3 { + font-size: 1.55em; } + +.reveal h4 { + font-size: 1em; } + +.reveal h1 { + text-shadow: 0 1px 0 #ccc, 0 2px 0 #c9c9c9, 0 3px 0 #bbb, 0 4px 0 #b9b9b9, 0 5px 0 #aaa, 0 6px 1px rgba(0, 0, 0, 0.1), 0 0 5px rgba(0, 0, 0, 0.1), 0 1px 3px rgba(0, 0, 0, 0.3), 0 3px 5px rgba(0, 0, 0, 0.2), 0 5px 10px rgba(0, 0, 0, 0.25), 0 20px 20px rgba(0, 0, 0, 0.15); } + +/********************************************* + * OTHER + *********************************************/ +.reveal p { + margin: 20px 0; + line-height: 1.3; } + +/* Ensure certain elements are never larger than the slide itself */ +.reveal img, +.reveal video, +.reveal iframe { + max-width: 95%; + max-height: 95%; } + +.reveal strong, +.reveal b { + font-weight: bold; } + +.reveal em { + font-style: italic; } + +.reveal ol, +.reveal dl, +.reveal ul { + display: inline-block; + text-align: left; + margin: 0 0 0 1em; } + +.reveal ol { + list-style-type: decimal; } + +.reveal ul { + list-style-type: disc; } + +.reveal ul ul { + list-style-type: square; } + +.reveal ul ul ul { + list-style-type: circle; } + +.reveal ul ul, +.reveal ul ol, +.reveal ol ol, +.reveal ol ul { + display: block; + margin-left: 40px; } + +.reveal dt { + font-weight: bold; } + +.reveal dd { + margin-left: 40px; } + +.reveal blockquote { + display: block; + position: relative; + width: 70%; + margin: 20px auto; + padding: 5px; + font-style: italic; + background: rgba(255, 255, 255, 0.05); + box-shadow: 0px 0px 2px rgba(0, 0, 0, 0.2); } + +.reveal blockquote p:first-child, +.reveal blockquote p:last-child { + display: inline-block; } + +.reveal q { + font-style: italic; } + +.reveal pre { + display: block; + position: relative; + width: 90%; + margin: 20px auto; + text-align: left; + font-size: 0.55em; + font-family: monospace; + line-height: 1.2em; + word-wrap: break-word; + box-shadow: 0px 5px 15px rgba(0, 0, 0, 0.15); } + +.reveal code { + font-family: monospace; + text-transform: none; } + +.reveal pre code { + display: block; + padding: 5px; + overflow: auto; + max-height: 400px; + word-wrap: normal; } + +.reveal table { + margin: auto; + border-collapse: collapse; + border-spacing: 0; } + +.reveal table th { + font-weight: bold; } + +.reveal table th, +.reveal table td { + text-align: left; + padding: 0.2em 0.5em 0.2em 0.5em; + border-bottom: 1px solid; } + +.reveal table th[align="center"], +.reveal table td[align="center"] { + text-align: center; } + +.reveal table th[align="right"], +.reveal table td[align="right"] { + text-align: right; } + +.reveal table tbody tr:last-child th, +.reveal table tbody tr:last-child td { + border-bottom: none; } + +.reveal sup { + vertical-align: super; + font-size: smaller; } + +.reveal sub { + vertical-align: sub; + font-size: smaller; } + +.reveal small { + display: inline-block; + font-size: 0.6em; + line-height: 1.2em; + vertical-align: top; } + +.reveal small * { + vertical-align: top; } + +/********************************************* + * LINKS + *********************************************/ +.reveal a { + color: #8b743d; + text-decoration: none; + -webkit-transition: color .15s ease; + -moz-transition: color .15s ease; + transition: color .15s ease; } + +.reveal a:hover { + color: #c0a86e; + text-shadow: none; + border: none; } + +.reveal .roll span:after { + color: #fff; + background: #564826; } + +/********************************************* + * IMAGES + *********************************************/ +.reveal section img { + margin: 15px 0px; + background: rgba(255, 255, 255, 0.12); + border: 4px solid #333; + box-shadow: 0 0 10px rgba(0, 0, 0, 0.15); } + +.reveal section img.plain { + border: 0; + box-shadow: none; } + +.reveal a img { + -webkit-transition: all .15s linear; + -moz-transition: all .15s linear; + transition: all .15s linear; } + +.reveal a:hover img { + background: rgba(255, 255, 255, 0.2); + border-color: #8b743d; + box-shadow: 0 0 20px rgba(0, 0, 0, 0.55); } + +/********************************************* + * NAVIGATION CONTROLS + *********************************************/ +.reveal .controls { + color: #8b743d; } + +/********************************************* + * PROGRESS BAR + *********************************************/ +.reveal .progress { + background: rgba(0, 0, 0, 0.2); + color: #8b743d; } + +.reveal .progress span { + -webkit-transition: width 800ms cubic-bezier(0.26, 0.86, 0.44, 0.985); + -moz-transition: width 800ms cubic-bezier(0.26, 0.86, 0.44, 0.985); + transition: width 800ms cubic-bezier(0.26, 0.86, 0.44, 0.985); } + +/********************************************* + * PRINT BACKGROUND + *********************************************/ +@media print { + .backgrounds { + background-color: #f7f3de; } } diff --git a/AdvancedCppV2/css/theme/black.css b/AdvancedCppV2/css/theme/black.css new file mode 100644 index 0000000..7dd88c2 --- /dev/null +++ b/AdvancedCppV2/css/theme/black.css @@ -0,0 +1,273 @@ +/** + * Black theme for reveal.js. This is the opposite of the 'white' theme. + * + * By Hakim El Hattab, http://hakim.se + */ +@import url(../../lib/font/source-sans-pro/source-sans-pro.css); +section.has-light-background, section.has-light-background h1, section.has-light-background h2, section.has-light-background h3, section.has-light-background h4, section.has-light-background h5, section.has-light-background h6 { + color: #222; } + +/********************************************* + * GLOBAL STYLES + *********************************************/ +body { + background: #191919; + background-color: #191919; } + +.reveal { + font-family: "Source Sans Pro", Helvetica, sans-serif; + font-size: 42px; + font-weight: normal; + color: #fff; } + +::selection { + color: #fff; + background: #bee4fd; + text-shadow: none; } + +::-moz-selection { + color: #fff; + background: #bee4fd; + text-shadow: none; } + +.reveal .slides section, +.reveal .slides section > section { + line-height: 1.3; + font-weight: inherit; } + +/********************************************* + * HEADERS + *********************************************/ +.reveal h1, +.reveal h2, +.reveal h3, +.reveal h4, +.reveal h5, +.reveal h6 { + margin: 0 0 20px 0; + color: #fff; + font-family: "Source Sans Pro", Helvetica, sans-serif; + font-weight: 600; + line-height: 1.2; + letter-spacing: normal; + text-transform: uppercase; + text-shadow: none; + word-wrap: break-word; } + +.reveal h1 { + font-size: 2.5em; } + +.reveal h2 { + font-size: 1.6em; } + +.reveal h3 { + font-size: 1.3em; } + +.reveal h4 { + font-size: 1em; } + +.reveal h1 { + text-shadow: none; } + +/********************************************* + * OTHER + *********************************************/ +.reveal p { + margin: 20px 0; + line-height: 1.3; } + +/* Ensure certain elements are never larger than the slide itself */ +.reveal img, +.reveal video, +.reveal iframe { + max-width: 95%; + max-height: 95%; } + +.reveal strong, +.reveal b { + font-weight: bold; } + +.reveal em { + font-style: italic; } + +.reveal ol, +.reveal dl, +.reveal ul { + display: inline-block; + text-align: left; + margin: 0 0 0 1em; } + +.reveal ol { + list-style-type: decimal; } + +.reveal ul { + list-style-type: disc; } + +.reveal ul ul { + list-style-type: square; } + +.reveal ul ul ul { + list-style-type: circle; } + +.reveal ul ul, +.reveal ul ol, +.reveal ol ol, +.reveal ol ul { + display: block; + margin-left: 40px; } + +.reveal dt { + font-weight: bold; } + +.reveal dd { + margin-left: 40px; } + +.reveal blockquote { + display: block; + position: relative; + width: 70%; + margin: 20px auto; + padding: 5px; + font-style: italic; + background: rgba(255, 255, 255, 0.05); + box-shadow: 0px 0px 2px rgba(0, 0, 0, 0.2); } + +.reveal blockquote p:first-child, +.reveal blockquote p:last-child { + display: inline-block; } + +.reveal q { + font-style: italic; } + +.reveal pre { + display: block; + position: relative; + width: 90%; + margin: 20px auto; + text-align: left; + font-size: 0.55em; + font-family: monospace; + line-height: 1.2em; + word-wrap: break-word; + box-shadow: 0px 5px 15px rgba(0, 0, 0, 0.15); } + +.reveal code { + font-family: monospace; + text-transform: none; } + +.reveal pre code { + display: block; + padding: 5px; + overflow: auto; + max-height: 400px; + word-wrap: normal; } + +.reveal table { + margin: auto; + border-collapse: collapse; + border-spacing: 0; } + +.reveal table th { + font-weight: bold; } + +.reveal table th, +.reveal table td { + text-align: left; + padding: 0.2em 0.5em 0.2em 0.5em; + border-bottom: 1px solid; } + +.reveal table th[align="center"], +.reveal table td[align="center"] { + text-align: center; } + +.reveal table th[align="right"], +.reveal table td[align="right"] { + text-align: right; } + +.reveal table tbody tr:last-child th, +.reveal table tbody tr:last-child td { + border-bottom: none; } + +.reveal sup { + vertical-align: super; + font-size: smaller; } + +.reveal sub { + vertical-align: sub; + font-size: smaller; } + +.reveal small { + display: inline-block; + font-size: 0.6em; + line-height: 1.2em; + vertical-align: top; } + +.reveal small * { + vertical-align: top; } + +/********************************************* + * LINKS + *********************************************/ +.reveal a { + color: #42affa; + text-decoration: none; + -webkit-transition: color .15s ease; + -moz-transition: color .15s ease; + transition: color .15s ease; } + +.reveal a:hover { + color: #8dcffc; + text-shadow: none; + border: none; } + +.reveal .roll span:after { + color: #fff; + background: #068de9; } + +/********************************************* + * IMAGES + *********************************************/ +.reveal section img { + margin: 15px 0px; + background: rgba(255, 255, 255, 0.12); + border: 4px solid #fff; + box-shadow: 0 0 10px rgba(0, 0, 0, 0.15); } + +.reveal section img.plain { + border: 0; + box-shadow: none; } + +.reveal a img { + -webkit-transition: all .15s linear; + -moz-transition: all .15s linear; + transition: all .15s linear; } + +.reveal a:hover img { + background: rgba(255, 255, 255, 0.2); + border-color: #42affa; + box-shadow: 0 0 20px rgba(0, 0, 0, 0.55); } + +/********************************************* + * NAVIGATION CONTROLS + *********************************************/ +.reveal .controls { + color: #42affa; } + +/********************************************* + * PROGRESS BAR + *********************************************/ +.reveal .progress { + background: rgba(0, 0, 0, 0.2); + color: #42affa; } + +.reveal .progress span { + -webkit-transition: width 800ms cubic-bezier(0.26, 0.86, 0.44, 0.985); + -moz-transition: width 800ms cubic-bezier(0.26, 0.86, 0.44, 0.985); + transition: width 800ms cubic-bezier(0.26, 0.86, 0.44, 0.985); } + +/********************************************* + * PRINT BACKGROUND + *********************************************/ +@media print { + .backgrounds { + background-color: #191919; } } diff --git a/AdvancedCppV2/css/theme/blood.css b/AdvancedCppV2/css/theme/blood.css new file mode 100644 index 0000000..5cbd488 --- /dev/null +++ b/AdvancedCppV2/css/theme/blood.css @@ -0,0 +1,296 @@ +/** + * Blood theme for reveal.js + * Author: Walther http://github.com/Walther + * + * Designed to be used with highlight.js theme + * "monokai_sublime.css" available from + * https://github.com/isagalaev/highlight.js/ + * + * For other themes, change $codeBackground accordingly. + * + */ +@import url(https://fonts.googleapis.com/css?family=Ubuntu:300,700,300italic,700italic); +/********************************************* + * GLOBAL STYLES + *********************************************/ +body { + background: #222; + background-color: #222; } + +.reveal { + font-family: Ubuntu, "sans-serif"; + font-size: 40px; + font-weight: normal; + color: #eee; } + +::selection { + color: #fff; + background: #a23; + text-shadow: none; } + +::-moz-selection { + color: #fff; + background: #a23; + text-shadow: none; } + +.reveal .slides section, +.reveal .slides section > section { + line-height: 1.3; + font-weight: inherit; } + +/********************************************* + * HEADERS + *********************************************/ +.reveal h1, +.reveal h2, +.reveal h3, +.reveal h4, +.reveal h5, +.reveal h6 { + margin: 0 0 20px 0; + color: #eee; + font-family: Ubuntu, "sans-serif"; + font-weight: normal; + line-height: 1.2; + letter-spacing: normal; + text-transform: uppercase; + text-shadow: 2px 2px 2px #222; + word-wrap: break-word; } + +.reveal h1 { + font-size: 3.77em; } + +.reveal h2 { + font-size: 2.11em; } + +.reveal h3 { + font-size: 1.55em; } + +.reveal h4 { + font-size: 1em; } + +.reveal h1 { + text-shadow: 0 1px 0 #ccc, 0 2px 0 #c9c9c9, 0 3px 0 #bbb, 0 4px 0 #b9b9b9, 0 5px 0 #aaa, 0 6px 1px rgba(0, 0, 0, 0.1), 0 0 5px rgba(0, 0, 0, 0.1), 0 1px 3px rgba(0, 0, 0, 0.3), 0 3px 5px rgba(0, 0, 0, 0.2), 0 5px 10px rgba(0, 0, 0, 0.25), 0 20px 20px rgba(0, 0, 0, 0.15); } + +/********************************************* + * OTHER + *********************************************/ +.reveal p { + margin: 20px 0; + line-height: 1.3; } + +/* Ensure certain elements are never larger than the slide itself */ +.reveal img, +.reveal video, +.reveal iframe { + max-width: 95%; + max-height: 95%; } + +.reveal strong, +.reveal b { + font-weight: bold; } + +.reveal em { + font-style: italic; } + +.reveal ol, +.reveal dl, +.reveal ul { + display: inline-block; + text-align: left; + margin: 0 0 0 1em; } + +.reveal ol { + list-style-type: decimal; } + +.reveal ul { + list-style-type: disc; } + +.reveal ul ul { + list-style-type: square; } + +.reveal ul ul ul { + list-style-type: circle; } + +.reveal ul ul, +.reveal ul ol, +.reveal ol ol, +.reveal ol ul { + display: block; + margin-left: 40px; } + +.reveal dt { + font-weight: bold; } + +.reveal dd { + margin-left: 40px; } + +.reveal blockquote { + display: block; + position: relative; + width: 70%; + margin: 20px auto; + padding: 5px; + font-style: italic; + background: rgba(255, 255, 255, 0.05); + box-shadow: 0px 0px 2px rgba(0, 0, 0, 0.2); } + +.reveal blockquote p:first-child, +.reveal blockquote p:last-child { + display: inline-block; } + +.reveal q { + font-style: italic; } + +.reveal pre { + display: block; + position: relative; + width: 90%; + margin: 20px auto; + text-align: left; + font-size: 0.55em; + font-family: monospace; + line-height: 1.2em; + word-wrap: break-word; + box-shadow: 0px 5px 15px rgba(0, 0, 0, 0.15); } + +.reveal code { + font-family: monospace; + text-transform: none; } + +.reveal pre code { + display: block; + padding: 5px; + overflow: auto; + max-height: 400px; + word-wrap: normal; } + +.reveal table { + margin: auto; + border-collapse: collapse; + border-spacing: 0; } + +.reveal table th { + font-weight: bold; } + +.reveal table th, +.reveal table td { + text-align: left; + padding: 0.2em 0.5em 0.2em 0.5em; + border-bottom: 1px solid; } + +.reveal table th[align="center"], +.reveal table td[align="center"] { + text-align: center; } + +.reveal table th[align="right"], +.reveal table td[align="right"] { + text-align: right; } + +.reveal table tbody tr:last-child th, +.reveal table tbody tr:last-child td { + border-bottom: none; } + +.reveal sup { + vertical-align: super; + font-size: smaller; } + +.reveal sub { + vertical-align: sub; + font-size: smaller; } + +.reveal small { + display: inline-block; + font-size: 0.6em; + line-height: 1.2em; + vertical-align: top; } + +.reveal small * { + vertical-align: top; } + +/********************************************* + * LINKS + *********************************************/ +.reveal a { + color: #a23; + text-decoration: none; + -webkit-transition: color .15s ease; + -moz-transition: color .15s ease; + transition: color .15s ease; } + +.reveal a:hover { + color: #dd5566; + text-shadow: none; + border: none; } + +.reveal .roll span:after { + color: #fff; + background: #6a1520; } + +/********************************************* + * IMAGES + *********************************************/ +.reveal section img { + margin: 15px 0px; + background: rgba(255, 255, 255, 0.12); + border: 4px solid #eee; + box-shadow: 0 0 10px rgba(0, 0, 0, 0.15); } + +.reveal section img.plain { + border: 0; + box-shadow: none; } + +.reveal a img { + -webkit-transition: all .15s linear; + -moz-transition: all .15s linear; + transition: all .15s linear; } + +.reveal a:hover img { + background: rgba(255, 255, 255, 0.2); + border-color: #a23; + box-shadow: 0 0 20px rgba(0, 0, 0, 0.55); } + +/********************************************* + * NAVIGATION CONTROLS + *********************************************/ +.reveal .controls { + color: #a23; } + +/********************************************* + * PROGRESS BAR + *********************************************/ +.reveal .progress { + background: rgba(0, 0, 0, 0.2); + color: #a23; } + +.reveal .progress span { + -webkit-transition: width 800ms cubic-bezier(0.26, 0.86, 0.44, 0.985); + -moz-transition: width 800ms cubic-bezier(0.26, 0.86, 0.44, 0.985); + transition: width 800ms cubic-bezier(0.26, 0.86, 0.44, 0.985); } + +/********************************************* + * PRINT BACKGROUND + *********************************************/ +@media print { + .backgrounds { + background-color: #222; } } + +.reveal p { + font-weight: 300; + text-shadow: 1px 1px #222; } + +.reveal h1, +.reveal h2, +.reveal h3, +.reveal h4, +.reveal h5, +.reveal h6 { + font-weight: 700; } + +.reveal p code { + background-color: #23241f; + display: inline-block; + border-radius: 7px; } + +.reveal small code { + vertical-align: baseline; } diff --git a/AdvancedCppV2/css/theme/coders.css b/AdvancedCppV2/css/theme/coders.css new file mode 100644 index 0000000..133b81e --- /dev/null +++ b/AdvancedCppV2/css/theme/coders.css @@ -0,0 +1,308 @@ +/** + * Coders School theme for reveal.js. + * + * By Łukasz "Lukin" Ziobroń + */ +@import url(../../lib/font/source-sans-pro/source-sans-pro.css); +@import url(../../lib/font/rajdhani/rajdhani.css); +section.has-light-background, section.has-light-background h1, section.has-light-background h2, section.has-light-background h3, section.has-light-background h4, section.has-light-background h5, section.has-light-background h6 { + color: #000; } + +/********************************************* + * GLOBAL STYLES + *********************************************/ +body { + background: #cac7c7; + background-color: #cac7c7; + background-image: url(../../img/altkom_logo.png); + background-size: 12%; + background-repeat: no-repeat; + background-position: 2% 98%; } + +.reveal { + font-family: Rajdhani, "Source Sans Pro", Helvetica, sans-serif; + font-size: 40px; + font-weight: normal; + color: #000; + /* frame for head - streaming + background-image: url(../../img/talking_head_placeholder.png); + background-size: 320px 180px; + background-repeat: no-repeat; + background-position: 98% 2%; */ } + +::selection { + color: #000; + background: #cac7c7; + text-shadow: none; } + +::-moz-selection { + color: #000; + background: #cac7c7; + text-shadow: none; } + +.reveal .slides section, +.reveal .slides section > section { + line-height: 1.3; + font-weight: inherit; } + +/********************************************* + * HEADERS + *********************************************/ +.reveal h1, +.reveal h2, +.reveal h3, +.reveal h4, +.reveal h5, +.reveal h6 { + margin: 10px 0 20px 0; + color: #000; + font-family: "Rajdhani", "Source Sans Pro", Helvetica, sans-serif; + font-weight: 600; + line-height: 1.2; + letter-spacing: normal; + text-transform: uppercase; + text-shadow: none; + word-wrap: break-word; } + +.reveal h1 { + font-size: 2.5em; } + +.reveal h2 { + font-size: 1.6em; } + +.reveal h3 { + font-size: 1.3em; } + +.reveal h4 { + font-size: 1em; } + +.reveal h1 { + text-shadow: none; } + +/********************************************* + * OTHER + *********************************************/ +.reveal p { + margin: 20px 0; + font-size: 0.8em; + line-height: 1.3; + text-align: justify; } + +/* Ensure certain elements are never larger than the slide itself */ +.reveal img, +.reveal video, +.reveal iframe { + max-width: 95%; + max-height: 95%; } + +.reveal strong, +.reveal b { + font-weight: bold; } + +.reveal em { + font-style: italic; } + +.reveal ol, +.reveal dl, +.reveal ul { + display: inline-block; + text-align: justify; + margin: 0 0 0 1em; } + +.reveal ol { + list-style-type: decimal; } + +.reveal ul { + list-style-type: disc; + font-size: 0.8em; } + +.reveal ul ul { + list-style-type: square; } + +.reveal ul ul ul { + list-style-type: circle; } + +.reveal ul ul, +.reveal ul ol, +.reveal ol ol, +.reveal ol ul { + display: block; + margin-left: 40px; } + +.reveal dt { + font-weight: bold; } + +.reveal dd { + margin-left: 40px; } + +.reveal blockquote { + display: block; + position: relative; + width: 70%; + margin: 20px auto; + padding: 5px; + font-style: italic; + background: rgba(255, 255, 255, 0.05); + box-shadow: 0px 0px 2px rgba(0, 0, 0, 0.2); } + +.reveal blockquote p:first-child, +.reveal blockquote p:last-child { + display: inline-block; } + +.reveal q { + font-style: italic; } + +.reveal pre { + display: block; + position: relative; + width: 95%; + margin: 20px auto; + text-align: left; + font-size: 0.6em; + font-family: monospace; + line-height: 1.2em; + word-wrap: break-word; + /*box-shadow: 0px 15px 30px rgba(0, 0, 0, 0.15);*/ } + +.reveal code { + font-family: monospace; + text-transform: none; } + +.reveal pre code { + display: block; + padding: 15px; + overflow: auto; + max-height: 560px; + word-wrap: normal; } + +.reveal table { + margin: auto; + border-collapse: collapse; + border-spacing: 0; } + +.reveal table th { + font-weight: bold; } + +.reveal table th, +.reveal table td { + text-align: left; + padding: 0.2em 0.5em 0.2em 0.5em; + border-bottom: 1px solid; } + +.reveal table th[align="center"], +.reveal table td[align="center"] { + text-align: center; } + +.reveal table th[align="right"], +.reveal table td[align="right"] { + text-align: right; } + +.reveal table tbody tr:last-child th, +.reveal table tbody tr:last-child td { + border-bottom: none; } + +.reveal sup { + vertical-align: super; + font-size: smaller; } + +.reveal sub { + vertical-align: sub; + font-size: smaller; } + +.reveal small { + display: inline-block; + font-size: 0.6em; + line-height: 1.2em; + vertical-align: top; } + +.reveal small * { + vertical-align: top; } + +/********************************************* + * LINKS + *********************************************/ +.reveal a { + color: #cf802a; + text-decoration: none; + -webkit-transition: color .15s ease; + -moz-transition: color .15s ease; + transition: color .15s ease; } + +.reveal a:hover { + color: #ce904e; + text-shadow: none; + border: none; } + +.reveal .roll span:after { + color: #fff; + background: #068de9; } + +/********************************************* + * IMAGES + *********************************************/ +.reveal section img { + margin: 15px 0px; + background: rgba(255, 255, 255, 0.12); + border: 4px solid #fff; + box-shadow: 0 0 10px rgba(0, 0, 0, 0.15); } + +.reveal section img.plain { + border: 0; + background: none; + box-shadow: none; } + +.reveal a img { + -webkit-transition: all .15s linear; + -moz-transition: all .15s linear; + transition: all .15s linear; } + +.reveal a:hover img { + background: rgba(255, 255, 255, 0.05); + border-color: #ce904e; + box-shadow: 0 0 20px rgba(0, 0, 0, 0.55); } + +/********************************************* + * NAVIGATION CONTROLS + *********************************************/ +.reveal .controls { + color: #cf802a; } + +/********************************************* + * PROGRESS BAR + *********************************************/ +.reveal .progress { + background: rgba(0, 0, 0, 0.2); + color: #cf802a; } + +.reveal .progress span { + -webkit-transition: width 800ms cubic-bezier(0.26, 0.86, 0.44, 0.985); + -moz-transition: width 800ms cubic-bezier(0.26, 0.86, 0.44, 0.985); + transition: width 800ms cubic-bezier(0.26, 0.86, 0.44, 0.985); } + +/********************************************* + * PRINT BACKGROUND + *********************************************/ +@media print { + .backgrounds { + background-color: #191919; } } + +/********************************************* + * OWN BOXES + *********************************************/ +.reveal .box { + position: absolute; + /*box-shadow: 0 1px 4px rgba(0,0,0,0.5), 0 5px 25px rgba(0,0,0,0.2);*/ + background-color: rgba(0, 0, 0, 0.7); + color: #fff; + padding: 20px; + margin: 20px 0; + font-size: 0.6em; + text-align: left; } + +/********************************************* + * MULTICOLUMN SUPPORT + *********************************************/ +.multicolumn { + display: flex; } +.col { + flex: 1; } diff --git a/AdvancedCppV2/css/theme/coders_white.css b/AdvancedCppV2/css/theme/coders_white.css new file mode 100644 index 0000000..79b423c --- /dev/null +++ b/AdvancedCppV2/css/theme/coders_white.css @@ -0,0 +1,294 @@ +/** + * Coders School theme for reveal.js. + * + * By Łukasz "Lukin" Ziobroń + */ +@import url(../../lib/font/source-sans-pro/source-sans-pro.css); +section.has-light-background, section.has-light-background h1, section.has-light-background h2, section.has-light-background h3, section.has-light-background h4, section.has-light-background h5, section.has-light-background h6 { + color: #222; } + +/********************************************* + * GLOBAL STYLES + *********************************************/ +body { + background: #fff; + background-color: #fff; + background-image: url(../../img/altkom_logo.png); + background-size: 10%; + background-repeat: no-repeat; + background-position: 1% 98%; } + +.reveal { + font-family: "Source Sans Pro", Helvetica, sans-serif; + font-size: 40px; + font-weight: normal; + color: #222; } + +::selection { + color: #fff; + background: #bee4fd; + text-shadow: none; } + +::-moz-selection { + color: #fff; + background: #bee4fd; + text-shadow: none; } + +.reveal .slides section, +.reveal .slides section > section { + line-height: 1.3; + font-weight: inherit; } + +/********************************************* + * HEADERS + *********************************************/ +.reveal h1, +.reveal h2, +.reveal h3, +.reveal h4, +.reveal h5, +.reveal h6 { + margin: 0 0 20px 0; + color: #222; + font-family: "Source Sans Pro", Helvetica, sans-serif; + font-weight: 600; + line-height: 1.2; + letter-spacing: normal; + text-transform: uppercase; + text-shadow: none; + word-wrap: break-word; } + +.reveal h1 { + font-size: 2.5em; } + +.reveal h2 { + font-size: 1.6em; } + +.reveal h3 { + font-size: 1.3em; } + +.reveal h4 { + font-size: 1em; } + +.reveal h1 { + text-shadow: none; } + +/********************************************* + * OTHER + *********************************************/ +.reveal p { + margin: 20px 0; + font-size: 0.8em; + line-height: 1.3; } + +/* Ensure certain elements are never larger than the slide itself */ +.reveal img, +.reveal video, +.reveal iframe { + max-width: 95%; + max-height: 95%; } + +.reveal strong, +.reveal b { + font-weight: bold; } + +.reveal em { + font-style: italic; } + +.reveal ol, +.reveal dl, +.reveal ul { + display: inline-block; + text-align: left; + margin: 0 0 0 1em; } + +.reveal ol { + list-style-type: decimal; } + +.reveal ul { + list-style-type: disc; + font-size: 0.9em; } + +.reveal ul ul { + list-style-type: square; } + +.reveal ul ul ul { + list-style-type: circle; } + +.reveal ul ul, +.reveal ul ol, +.reveal ol ol, +.reveal ol ul { + display: block; + margin-left: 40px; } + +.reveal dt { + font-weight: bold; } + +.reveal dd { + margin-left: 40px; } + +.reveal blockquote { + display: block; + position: relative; + width: 70%; + margin: 20px auto; + padding: 5px; + font-style: italic; + background: rgba(255, 255, 255, 0.05); + box-shadow: 0px 0px 2px rgba(0, 0, 0, 0.2); } + +.reveal blockquote p:first-child, +.reveal blockquote p:last-child { + display: inline-block; } + +.reveal q { + font-style: italic; } + +.reveal pre { + display: block; + position: relative; + width: 90%; + margin: 20px auto; + text-align: left; + font-size: 0.6em; + font-family: monospace; + line-height: 1.2em; + word-wrap: break-word; + box-shadow: 0px 15px 30px rgba(0, 0, 0, 0.15); } + +.reveal code { + font-family: monospace; + text-transform: none; } + +.reveal pre code { + display: block; + padding: 5px; + overflow: auto; + max-height: 560px; + word-wrap: normal; } + +.reveal table { + margin: auto; + border-collapse: collapse; + border-spacing: 0; } + +.reveal table th { + font-weight: bold; } + +.reveal table th, +.reveal table td { + text-align: left; + padding: 0.2em 0.5em 0.2em 0.5em; + border-bottom: 1px solid; } + +.reveal table th[align="center"], +.reveal table td[align="center"] { + text-align: center; } + +.reveal table th[align="right"], +.reveal table td[align="right"] { + text-align: right; } + +.reveal table tbody tr:last-child th, +.reveal table tbody tr:last-child td { + border-bottom: none; } + +.reveal sup { + vertical-align: super; + font-size: smaller; } + +.reveal sub { + vertical-align: sub; + font-size: smaller; } + +.reveal small { + display: inline-block; + font-size: 0.6em; + line-height: 1.2em; + vertical-align: top; } + +.reveal small * { + vertical-align: top; } + +/********************************************* + * LINKS + *********************************************/ +.reveal a { + color: #cf802a; + text-decoration: none; + -webkit-transition: color .15s ease; + -moz-transition: color .15s ease; + transition: color .15s ease; } + +.reveal a:hover { + color: #ce904e; + text-shadow: none; + border: none; } + +.reveal .roll span:after { + color: #fff; + background: #068de9; } + +/********************************************* + * IMAGES + *********************************************/ +.reveal section img { + margin: 15px 0px; + background: rgba(255, 255, 255, 0.12); + border: 4px solid #222; + box-shadow: 0 0 10px rgba(0, 0, 0, 0.15); } + +.reveal section img.plain { + border: 0; + background: none; + box-shadow: none; } + +.reveal a img { + -webkit-transition: all .15s linear; + -moz-transition: all .15s linear; + transition: all .15s linear; } + +.reveal a:hover img { + background: rgba(255, 255, 255, 0.05); + border-color: #ce904e; + box-shadow: 0 0 20px rgba(0, 0, 0, 0.55); } + +/********************************************* + * NAVIGATION CONTROLS + *********************************************/ +.reveal .controls { + color: #cf802a; } + +/********************************************* + * PROGRESS BAR + *********************************************/ +.reveal .progress { + background: rgba(0, 0, 0, 0.2); + color: #cf802a; } + +.reveal .progress span { + -webkit-transition: width 800ms cubic-bezier(0.26, 0.86, 0.44, 0.985); + -moz-transition: width 800ms cubic-bezier(0.26, 0.86, 0.44, 0.985); + transition: width 800ms cubic-bezier(0.26, 0.86, 0.44, 0.985); } + +/********************************************* + * PRINT BACKGROUND + *********************************************/ +@media print { + .backgrounds { + background-color: #191919; } } + +/********************************************* + * OWN BOXES + *********************************************/ +.reveal .box { + position: absolute; + box-shadow: 0 1px 4px rgba(0,0,0,0.5), 0 5px 25px rgba(0,0,0,0.2); + background-color: rgba(0, 0, 0, 0.7); + color: #fff; + padding: 20px; + margin: 20px 0; + font-size: 0.6em; + text-align: left; +} \ No newline at end of file diff --git a/AdvancedCppV2/css/theme/league.css b/AdvancedCppV2/css/theme/league.css new file mode 100644 index 0000000..f8fba4d --- /dev/null +++ b/AdvancedCppV2/css/theme/league.css @@ -0,0 +1,279 @@ +/** + * League theme for reveal.js. + * + * This was the default theme pre-3.0.0. + * + * Copyright (C) 2011-2012 Hakim El Hattab, http://hakim.se + */ +@import url(../../lib/font/league-gothic/league-gothic.css); +@import url(https://fonts.googleapis.com/css?family=Lato:400,700,400italic,700italic); +/********************************************* + * GLOBAL STYLES + *********************************************/ +body { + background: #1c1e20; + background: -moz-radial-gradient(center, circle cover, #555a5f 0%, #1c1e20 100%); + background: -webkit-gradient(radial, center center, 0px, center center, 100%, color-stop(0%, #555a5f), color-stop(100%, #1c1e20)); + background: -webkit-radial-gradient(center, circle cover, #555a5f 0%, #1c1e20 100%); + background: -o-radial-gradient(center, circle cover, #555a5f 0%, #1c1e20 100%); + background: -ms-radial-gradient(center, circle cover, #555a5f 0%, #1c1e20 100%); + background: radial-gradient(center, circle cover, #555a5f 0%, #1c1e20 100%); + background-color: #2b2b2b; } + +.reveal { + font-family: "Lato", sans-serif; + font-size: 40px; + font-weight: normal; + color: #eee; } + +::selection { + color: #fff; + background: #FF5E99; + text-shadow: none; } + +::-moz-selection { + color: #fff; + background: #FF5E99; + text-shadow: none; } + +.reveal .slides section, +.reveal .slides section > section { + line-height: 1.3; + font-weight: inherit; } + +/********************************************* + * HEADERS + *********************************************/ +.reveal h1, +.reveal h2, +.reveal h3, +.reveal h4, +.reveal h5, +.reveal h6 { + margin: 0 0 20px 0; + color: #eee; + font-family: "League Gothic", Impact, sans-serif; + font-weight: normal; + line-height: 1.2; + letter-spacing: normal; + text-transform: uppercase; + text-shadow: 0px 0px 6px rgba(0, 0, 0, 0.2); + word-wrap: break-word; } + +.reveal h1 { + font-size: 3.77em; } + +.reveal h2 { + font-size: 2.11em; } + +.reveal h3 { + font-size: 1.55em; } + +.reveal h4 { + font-size: 1em; } + +.reveal h1 { + text-shadow: 0 1px 0 #ccc, 0 2px 0 #c9c9c9, 0 3px 0 #bbb, 0 4px 0 #b9b9b9, 0 5px 0 #aaa, 0 6px 1px rgba(0, 0, 0, 0.1), 0 0 5px rgba(0, 0, 0, 0.1), 0 1px 3px rgba(0, 0, 0, 0.3), 0 3px 5px rgba(0, 0, 0, 0.2), 0 5px 10px rgba(0, 0, 0, 0.25), 0 20px 20px rgba(0, 0, 0, 0.15); } + +/********************************************* + * OTHER + *********************************************/ +.reveal p { + margin: 20px 0; + line-height: 1.3; } + +/* Ensure certain elements are never larger than the slide itself */ +.reveal img, +.reveal video, +.reveal iframe { + max-width: 95%; + max-height: 95%; } + +.reveal strong, +.reveal b { + font-weight: bold; } + +.reveal em { + font-style: italic; } + +.reveal ol, +.reveal dl, +.reveal ul { + display: inline-block; + text-align: left; + margin: 0 0 0 1em; } + +.reveal ol { + list-style-type: decimal; } + +.reveal ul { + list-style-type: disc; } + +.reveal ul ul { + list-style-type: square; } + +.reveal ul ul ul { + list-style-type: circle; } + +.reveal ul ul, +.reveal ul ol, +.reveal ol ol, +.reveal ol ul { + display: block; + margin-left: 40px; } + +.reveal dt { + font-weight: bold; } + +.reveal dd { + margin-left: 40px; } + +.reveal blockquote { + display: block; + position: relative; + width: 70%; + margin: 20px auto; + padding: 5px; + font-style: italic; + background: rgba(255, 255, 255, 0.05); + box-shadow: 0px 0px 2px rgba(0, 0, 0, 0.2); } + +.reveal blockquote p:first-child, +.reveal blockquote p:last-child { + display: inline-block; } + +.reveal q { + font-style: italic; } + +.reveal pre { + display: block; + position: relative; + width: 90%; + margin: 20px auto; + text-align: left; + font-size: 0.55em; + font-family: monospace; + line-height: 1.2em; + word-wrap: break-word; + box-shadow: 0px 5px 15px rgba(0, 0, 0, 0.15); } + +.reveal code { + font-family: monospace; + text-transform: none; } + +.reveal pre code { + display: block; + padding: 5px; + overflow: auto; + max-height: 400px; + word-wrap: normal; } + +.reveal table { + margin: auto; + border-collapse: collapse; + border-spacing: 0; } + +.reveal table th { + font-weight: bold; } + +.reveal table th, +.reveal table td { + text-align: left; + padding: 0.2em 0.5em 0.2em 0.5em; + border-bottom: 1px solid; } + +.reveal table th[align="center"], +.reveal table td[align="center"] { + text-align: center; } + +.reveal table th[align="right"], +.reveal table td[align="right"] { + text-align: right; } + +.reveal table tbody tr:last-child th, +.reveal table tbody tr:last-child td { + border-bottom: none; } + +.reveal sup { + vertical-align: super; + font-size: smaller; } + +.reveal sub { + vertical-align: sub; + font-size: smaller; } + +.reveal small { + display: inline-block; + font-size: 0.6em; + line-height: 1.2em; + vertical-align: top; } + +.reveal small * { + vertical-align: top; } + +/********************************************* + * LINKS + *********************************************/ +.reveal a { + color: #13DAEC; + text-decoration: none; + -webkit-transition: color .15s ease; + -moz-transition: color .15s ease; + transition: color .15s ease; } + +.reveal a:hover { + color: #71e9f4; + text-shadow: none; + border: none; } + +.reveal .roll span:after { + color: #fff; + background: #0d99a5; } + +/********************************************* + * IMAGES + *********************************************/ +.reveal section img { + margin: 15px 0px; + background: rgba(255, 255, 255, 0.12); + border: 4px solid #eee; + box-shadow: 0 0 10px rgba(0, 0, 0, 0.15); } + +.reveal section img.plain { + border: 0; + box-shadow: none; } + +.reveal a img { + -webkit-transition: all .15s linear; + -moz-transition: all .15s linear; + transition: all .15s linear; } + +.reveal a:hover img { + background: rgba(255, 255, 255, 0.2); + border-color: #13DAEC; + box-shadow: 0 0 20px rgba(0, 0, 0, 0.55); } + +/********************************************* + * NAVIGATION CONTROLS + *********************************************/ +.reveal .controls { + color: #13DAEC; } + +/********************************************* + * PROGRESS BAR + *********************************************/ +.reveal .progress { + background: rgba(0, 0, 0, 0.2); + color: #13DAEC; } + +.reveal .progress span { + -webkit-transition: width 800ms cubic-bezier(0.26, 0.86, 0.44, 0.985); + -moz-transition: width 800ms cubic-bezier(0.26, 0.86, 0.44, 0.985); + transition: width 800ms cubic-bezier(0.26, 0.86, 0.44, 0.985); } + +/********************************************* + * PRINT BACKGROUND + *********************************************/ +@media print { + .backgrounds { + background-color: #2b2b2b; } } diff --git a/AdvancedCppV2/css/theme/moon.css b/AdvancedCppV2/css/theme/moon.css new file mode 100644 index 0000000..d18f526 --- /dev/null +++ b/AdvancedCppV2/css/theme/moon.css @@ -0,0 +1,277 @@ +/** + * Solarized Dark theme for reveal.js. + * Author: Achim Staebler + */ +@import url(../../lib/font/league-gothic/league-gothic.css); +@import url(https://fonts.googleapis.com/css?family=Lato:400,700,400italic,700italic); +/** + * Solarized colors by Ethan Schoonover + */ +html * { + color-profile: sRGB; + rendering-intent: auto; } + +/********************************************* + * GLOBAL STYLES + *********************************************/ +body { + background: #002b36; + background-color: #002b36; } + +.reveal { + font-family: "Lato", sans-serif; + font-size: 40px; + font-weight: normal; + color: #93a1a1; } + +::selection { + color: #fff; + background: #d33682; + text-shadow: none; } + +::-moz-selection { + color: #fff; + background: #d33682; + text-shadow: none; } + +.reveal .slides section, +.reveal .slides section > section { + line-height: 1.3; + font-weight: inherit; } + +/********************************************* + * HEADERS + *********************************************/ +.reveal h1, +.reveal h2, +.reveal h3, +.reveal h4, +.reveal h5, +.reveal h6 { + margin: 0 0 20px 0; + color: #eee8d5; + font-family: "League Gothic", Impact, sans-serif; + font-weight: normal; + line-height: 1.2; + letter-spacing: normal; + text-transform: uppercase; + text-shadow: none; + word-wrap: break-word; } + +.reveal h1 { + font-size: 3.77em; } + +.reveal h2 { + font-size: 2.11em; } + +.reveal h3 { + font-size: 1.55em; } + +.reveal h4 { + font-size: 1em; } + +.reveal h1 { + text-shadow: none; } + +/********************************************* + * OTHER + *********************************************/ +.reveal p { + margin: 20px 0; + line-height: 1.3; } + +/* Ensure certain elements are never larger than the slide itself */ +.reveal img, +.reveal video, +.reveal iframe { + max-width: 95%; + max-height: 95%; } + +.reveal strong, +.reveal b { + font-weight: bold; } + +.reveal em { + font-style: italic; } + +.reveal ol, +.reveal dl, +.reveal ul { + display: inline-block; + text-align: left; + margin: 0 0 0 1em; } + +.reveal ol { + list-style-type: decimal; } + +.reveal ul { + list-style-type: disc; } + +.reveal ul ul { + list-style-type: square; } + +.reveal ul ul ul { + list-style-type: circle; } + +.reveal ul ul, +.reveal ul ol, +.reveal ol ol, +.reveal ol ul { + display: block; + margin-left: 40px; } + +.reveal dt { + font-weight: bold; } + +.reveal dd { + margin-left: 40px; } + +.reveal blockquote { + display: block; + position: relative; + width: 70%; + margin: 20px auto; + padding: 5px; + font-style: italic; + background: rgba(255, 255, 255, 0.05); + box-shadow: 0px 0px 2px rgba(0, 0, 0, 0.2); } + +.reveal blockquote p:first-child, +.reveal blockquote p:last-child { + display: inline-block; } + +.reveal q { + font-style: italic; } + +.reveal pre { + display: block; + position: relative; + width: 90%; + margin: 20px auto; + text-align: left; + font-size: 0.55em; + font-family: monospace; + line-height: 1.2em; + word-wrap: break-word; + box-shadow: 0px 5px 15px rgba(0, 0, 0, 0.15); } + +.reveal code { + font-family: monospace; + text-transform: none; } + +.reveal pre code { + display: block; + padding: 5px; + overflow: auto; + max-height: 400px; + word-wrap: normal; } + +.reveal table { + margin: auto; + border-collapse: collapse; + border-spacing: 0; } + +.reveal table th { + font-weight: bold; } + +.reveal table th, +.reveal table td { + text-align: left; + padding: 0.2em 0.5em 0.2em 0.5em; + border-bottom: 1px solid; } + +.reveal table th[align="center"], +.reveal table td[align="center"] { + text-align: center; } + +.reveal table th[align="right"], +.reveal table td[align="right"] { + text-align: right; } + +.reveal table tbody tr:last-child th, +.reveal table tbody tr:last-child td { + border-bottom: none; } + +.reveal sup { + vertical-align: super; + font-size: smaller; } + +.reveal sub { + vertical-align: sub; + font-size: smaller; } + +.reveal small { + display: inline-block; + font-size: 0.6em; + line-height: 1.2em; + vertical-align: top; } + +.reveal small * { + vertical-align: top; } + +/********************************************* + * LINKS + *********************************************/ +.reveal a { + color: #268bd2; + text-decoration: none; + -webkit-transition: color .15s ease; + -moz-transition: color .15s ease; + transition: color .15s ease; } + +.reveal a:hover { + color: #78b9e6; + text-shadow: none; + border: none; } + +.reveal .roll span:after { + color: #fff; + background: #1a6091; } + +/********************************************* + * IMAGES + *********************************************/ +.reveal section img { + margin: 15px 0px; + background: rgba(255, 255, 255, 0.12); + border: 4px solid #93a1a1; + box-shadow: 0 0 10px rgba(0, 0, 0, 0.15); } + +.reveal section img.plain { + border: 0; + box-shadow: none; } + +.reveal a img { + -webkit-transition: all .15s linear; + -moz-transition: all .15s linear; + transition: all .15s linear; } + +.reveal a:hover img { + background: rgba(255, 255, 255, 0.2); + border-color: #268bd2; + box-shadow: 0 0 20px rgba(0, 0, 0, 0.55); } + +/********************************************* + * NAVIGATION CONTROLS + *********************************************/ +.reveal .controls { + color: #268bd2; } + +/********************************************* + * PROGRESS BAR + *********************************************/ +.reveal .progress { + background: rgba(0, 0, 0, 0.2); + color: #268bd2; } + +.reveal .progress span { + -webkit-transition: width 800ms cubic-bezier(0.26, 0.86, 0.44, 0.985); + -moz-transition: width 800ms cubic-bezier(0.26, 0.86, 0.44, 0.985); + transition: width 800ms cubic-bezier(0.26, 0.86, 0.44, 0.985); } + +/********************************************* + * PRINT BACKGROUND + *********************************************/ +@media print { + .backgrounds { + background-color: #002b36; } } diff --git a/AdvancedCppV2/css/theme/night.css b/AdvancedCppV2/css/theme/night.css new file mode 100644 index 0000000..f5ccb52 --- /dev/null +++ b/AdvancedCppV2/css/theme/night.css @@ -0,0 +1,271 @@ +/** + * Black theme for reveal.js. + * + * Copyright (C) 2011-2012 Hakim El Hattab, http://hakim.se + */ +@import url(https://fonts.googleapis.com/css?family=Montserrat:700); +@import url(https://fonts.googleapis.com/css?family=Open+Sans:400,700,400italic,700italic); +/********************************************* + * GLOBAL STYLES + *********************************************/ +body { + background: #111; + background-color: #111; } + +.reveal { + font-family: "Open Sans", sans-serif; + font-size: 40px; + font-weight: normal; + color: #eee; } + +::selection { + color: #fff; + background: #e7ad52; + text-shadow: none; } + +::-moz-selection { + color: #fff; + background: #e7ad52; + text-shadow: none; } + +.reveal .slides section, +.reveal .slides section > section { + line-height: 1.3; + font-weight: inherit; } + +/********************************************* + * HEADERS + *********************************************/ +.reveal h1, +.reveal h2, +.reveal h3, +.reveal h4, +.reveal h5, +.reveal h6 { + margin: 0 0 20px 0; + color: #eee; + font-family: "Montserrat", Impact, sans-serif; + font-weight: normal; + line-height: 1.2; + letter-spacing: -0.03em; + text-transform: none; + text-shadow: none; + word-wrap: break-word; } + +.reveal h1 { + font-size: 3.77em; } + +.reveal h2 { + font-size: 2.11em; } + +.reveal h3 { + font-size: 1.55em; } + +.reveal h4 { + font-size: 1em; } + +.reveal h1 { + text-shadow: none; } + +/********************************************* + * OTHER + *********************************************/ +.reveal p { + margin: 20px 0; + line-height: 1.3; } + +/* Ensure certain elements are never larger than the slide itself */ +.reveal img, +.reveal video, +.reveal iframe { + max-width: 95%; + max-height: 95%; } + +.reveal strong, +.reveal b { + font-weight: bold; } + +.reveal em { + font-style: italic; } + +.reveal ol, +.reveal dl, +.reveal ul { + display: inline-block; + text-align: left; + margin: 0 0 0 1em; } + +.reveal ol { + list-style-type: decimal; } + +.reveal ul { + list-style-type: disc; } + +.reveal ul ul { + list-style-type: square; } + +.reveal ul ul ul { + list-style-type: circle; } + +.reveal ul ul, +.reveal ul ol, +.reveal ol ol, +.reveal ol ul { + display: block; + margin-left: 40px; } + +.reveal dt { + font-weight: bold; } + +.reveal dd { + margin-left: 40px; } + +.reveal blockquote { + display: block; + position: relative; + width: 70%; + margin: 20px auto; + padding: 5px; + font-style: italic; + background: rgba(255, 255, 255, 0.05); + box-shadow: 0px 0px 2px rgba(0, 0, 0, 0.2); } + +.reveal blockquote p:first-child, +.reveal blockquote p:last-child { + display: inline-block; } + +.reveal q { + font-style: italic; } + +.reveal pre { + display: block; + position: relative; + width: 90%; + margin: 20px auto; + text-align: left; + font-size: 0.55em; + font-family: monospace; + line-height: 1.2em; + word-wrap: break-word; + box-shadow: 0px 5px 15px rgba(0, 0, 0, 0.15); } + +.reveal code { + font-family: monospace; + text-transform: none; } + +.reveal pre code { + display: block; + padding: 5px; + overflow: auto; + max-height: 400px; + word-wrap: normal; } + +.reveal table { + margin: auto; + border-collapse: collapse; + border-spacing: 0; } + +.reveal table th { + font-weight: bold; } + +.reveal table th, +.reveal table td { + text-align: left; + padding: 0.2em 0.5em 0.2em 0.5em; + border-bottom: 1px solid; } + +.reveal table th[align="center"], +.reveal table td[align="center"] { + text-align: center; } + +.reveal table th[align="right"], +.reveal table td[align="right"] { + text-align: right; } + +.reveal table tbody tr:last-child th, +.reveal table tbody tr:last-child td { + border-bottom: none; } + +.reveal sup { + vertical-align: super; + font-size: smaller; } + +.reveal sub { + vertical-align: sub; + font-size: smaller; } + +.reveal small { + display: inline-block; + font-size: 0.6em; + line-height: 1.2em; + vertical-align: top; } + +.reveal small * { + vertical-align: top; } + +/********************************************* + * LINKS + *********************************************/ +.reveal a { + color: #e7ad52; + text-decoration: none; + -webkit-transition: color .15s ease; + -moz-transition: color .15s ease; + transition: color .15s ease; } + +.reveal a:hover { + color: #f3d7ac; + text-shadow: none; + border: none; } + +.reveal .roll span:after { + color: #fff; + background: #d08a1d; } + +/********************************************* + * IMAGES + *********************************************/ +.reveal section img { + margin: 15px 0px; + background: rgba(255, 255, 255, 0.12); + border: 4px solid #eee; + box-shadow: 0 0 10px rgba(0, 0, 0, 0.15); } + +.reveal section img.plain { + border: 0; + box-shadow: none; } + +.reveal a img { + -webkit-transition: all .15s linear; + -moz-transition: all .15s linear; + transition: all .15s linear; } + +.reveal a:hover img { + background: rgba(255, 255, 255, 0.2); + border-color: #e7ad52; + box-shadow: 0 0 20px rgba(0, 0, 0, 0.55); } + +/********************************************* + * NAVIGATION CONTROLS + *********************************************/ +.reveal .controls { + color: #e7ad52; } + +/********************************************* + * PROGRESS BAR + *********************************************/ +.reveal .progress { + background: rgba(0, 0, 0, 0.2); + color: #e7ad52; } + +.reveal .progress span { + -webkit-transition: width 800ms cubic-bezier(0.26, 0.86, 0.44, 0.985); + -moz-transition: width 800ms cubic-bezier(0.26, 0.86, 0.44, 0.985); + transition: width 800ms cubic-bezier(0.26, 0.86, 0.44, 0.985); } + +/********************************************* + * PRINT BACKGROUND + *********************************************/ +@media print { + .backgrounds { + background-color: #111; } } diff --git a/AdvancedCppV2/css/theme/serif.css b/AdvancedCppV2/css/theme/serif.css new file mode 100644 index 0000000..6514a6f --- /dev/null +++ b/AdvancedCppV2/css/theme/serif.css @@ -0,0 +1,273 @@ +/** + * A simple theme for reveal.js presentations, similar + * to the default theme. The accent color is brown. + * + * This theme is Copyright (C) 2012-2013 Owen Versteeg, http://owenversteeg.com - it is MIT licensed. + */ +.reveal a { + line-height: 1.3em; } + +/********************************************* + * GLOBAL STYLES + *********************************************/ +body { + background: #F0F1EB; + background-color: #F0F1EB; } + +.reveal { + font-family: "Palatino Linotype", "Book Antiqua", Palatino, FreeSerif, serif; + font-size: 40px; + font-weight: normal; + color: #000; } + +::selection { + color: #fff; + background: #26351C; + text-shadow: none; } + +::-moz-selection { + color: #fff; + background: #26351C; + text-shadow: none; } + +.reveal .slides section, +.reveal .slides section > section { + line-height: 1.3; + font-weight: inherit; } + +/********************************************* + * HEADERS + *********************************************/ +.reveal h1, +.reveal h2, +.reveal h3, +.reveal h4, +.reveal h5, +.reveal h6 { + margin: 0 0 20px 0; + color: #383D3D; + font-family: "Palatino Linotype", "Book Antiqua", Palatino, FreeSerif, serif; + font-weight: normal; + line-height: 1.2; + letter-spacing: normal; + text-transform: none; + text-shadow: none; + word-wrap: break-word; } + +.reveal h1 { + font-size: 3.77em; } + +.reveal h2 { + font-size: 2.11em; } + +.reveal h3 { + font-size: 1.55em; } + +.reveal h4 { + font-size: 1em; } + +.reveal h1 { + text-shadow: none; } + +/********************************************* + * OTHER + *********************************************/ +.reveal p { + margin: 20px 0; + line-height: 1.3; } + +/* Ensure certain elements are never larger than the slide itself */ +.reveal img, +.reveal video, +.reveal iframe { + max-width: 95%; + max-height: 95%; } + +.reveal strong, +.reveal b { + font-weight: bold; } + +.reveal em { + font-style: italic; } + +.reveal ol, +.reveal dl, +.reveal ul { + display: inline-block; + text-align: left; + margin: 0 0 0 1em; } + +.reveal ol { + list-style-type: decimal; } + +.reveal ul { + list-style-type: disc; } + +.reveal ul ul { + list-style-type: square; } + +.reveal ul ul ul { + list-style-type: circle; } + +.reveal ul ul, +.reveal ul ol, +.reveal ol ol, +.reveal ol ul { + display: block; + margin-left: 40px; } + +.reveal dt { + font-weight: bold; } + +.reveal dd { + margin-left: 40px; } + +.reveal blockquote { + display: block; + position: relative; + width: 70%; + margin: 20px auto; + padding: 5px; + font-style: italic; + background: rgba(255, 255, 255, 0.05); + box-shadow: 0px 0px 2px rgba(0, 0, 0, 0.2); } + +.reveal blockquote p:first-child, +.reveal blockquote p:last-child { + display: inline-block; } + +.reveal q { + font-style: italic; } + +.reveal pre { + display: block; + position: relative; + width: 90%; + margin: 20px auto; + text-align: left; + font-size: 0.55em; + font-family: monospace; + line-height: 1.2em; + word-wrap: break-word; + box-shadow: 0px 5px 15px rgba(0, 0, 0, 0.15); } + +.reveal code { + font-family: monospace; + text-transform: none; } + +.reveal pre code { + display: block; + padding: 5px; + overflow: auto; + max-height: 400px; + word-wrap: normal; } + +.reveal table { + margin: auto; + border-collapse: collapse; + border-spacing: 0; } + +.reveal table th { + font-weight: bold; } + +.reveal table th, +.reveal table td { + text-align: left; + padding: 0.2em 0.5em 0.2em 0.5em; + border-bottom: 1px solid; } + +.reveal table th[align="center"], +.reveal table td[align="center"] { + text-align: center; } + +.reveal table th[align="right"], +.reveal table td[align="right"] { + text-align: right; } + +.reveal table tbody tr:last-child th, +.reveal table tbody tr:last-child td { + border-bottom: none; } + +.reveal sup { + vertical-align: super; + font-size: smaller; } + +.reveal sub { + vertical-align: sub; + font-size: smaller; } + +.reveal small { + display: inline-block; + font-size: 0.6em; + line-height: 1.2em; + vertical-align: top; } + +.reveal small * { + vertical-align: top; } + +/********************************************* + * LINKS + *********************************************/ +.reveal a { + color: #51483D; + text-decoration: none; + -webkit-transition: color .15s ease; + -moz-transition: color .15s ease; + transition: color .15s ease; } + +.reveal a:hover { + color: #8b7c69; + text-shadow: none; + border: none; } + +.reveal .roll span:after { + color: #fff; + background: #25211c; } + +/********************************************* + * IMAGES + *********************************************/ +.reveal section img { + margin: 15px 0px; + background: rgba(255, 255, 255, 0.12); + border: 4px solid #000; + box-shadow: 0 0 10px rgba(0, 0, 0, 0.15); } + +.reveal section img.plain { + border: 0; + box-shadow: none; } + +.reveal a img { + -webkit-transition: all .15s linear; + -moz-transition: all .15s linear; + transition: all .15s linear; } + +.reveal a:hover img { + background: rgba(255, 255, 255, 0.2); + border-color: #51483D; + box-shadow: 0 0 20px rgba(0, 0, 0, 0.55); } + +/********************************************* + * NAVIGATION CONTROLS + *********************************************/ +.reveal .controls { + color: #51483D; } + +/********************************************* + * PROGRESS BAR + *********************************************/ +.reveal .progress { + background: rgba(0, 0, 0, 0.2); + color: #51483D; } + +.reveal .progress span { + -webkit-transition: width 800ms cubic-bezier(0.26, 0.86, 0.44, 0.985); + -moz-transition: width 800ms cubic-bezier(0.26, 0.86, 0.44, 0.985); + transition: width 800ms cubic-bezier(0.26, 0.86, 0.44, 0.985); } + +/********************************************* + * PRINT BACKGROUND + *********************************************/ +@media print { + .backgrounds { + background-color: #F0F1EB; } } diff --git a/AdvancedCppV2/css/theme/simple.css b/AdvancedCppV2/css/theme/simple.css new file mode 100644 index 0000000..a7a29a6 --- /dev/null +++ b/AdvancedCppV2/css/theme/simple.css @@ -0,0 +1,276 @@ +/** + * A simple theme for reveal.js presentations, similar + * to the default theme. The accent color is darkblue. + * + * This theme is Copyright (C) 2012 Owen Versteeg, https://github.com/StereotypicalApps. It is MIT licensed. + * reveal.js is Copyright (C) 2011-2012 Hakim El Hattab, http://hakim.se + */ +@import url(https://fonts.googleapis.com/css?family=News+Cycle:400,700); +@import url(https://fonts.googleapis.com/css?family=Lato:400,700,400italic,700italic); +section.has-dark-background, section.has-dark-background h1, section.has-dark-background h2, section.has-dark-background h3, section.has-dark-background h4, section.has-dark-background h5, section.has-dark-background h6 { + color: #fff; } + +/********************************************* + * GLOBAL STYLES + *********************************************/ +body { + background: #fff; + background-color: #fff; } + +.reveal { + font-family: "Lato", sans-serif; + font-size: 40px; + font-weight: normal; + color: #000; } + +::selection { + color: #fff; + background: rgba(0, 0, 0, 0.99); + text-shadow: none; } + +::-moz-selection { + color: #fff; + background: rgba(0, 0, 0, 0.99); + text-shadow: none; } + +.reveal .slides section, +.reveal .slides section > section { + line-height: 1.3; + font-weight: inherit; } + +/********************************************* + * HEADERS + *********************************************/ +.reveal h1, +.reveal h2, +.reveal h3, +.reveal h4, +.reveal h5, +.reveal h6 { + margin: 0 0 20px 0; + color: #000; + font-family: "News Cycle", Impact, sans-serif; + font-weight: normal; + line-height: 1.2; + letter-spacing: normal; + text-transform: none; + text-shadow: none; + word-wrap: break-word; } + +.reveal h1 { + font-size: 3.77em; } + +.reveal h2 { + font-size: 2.11em; } + +.reveal h3 { + font-size: 1.55em; } + +.reveal h4 { + font-size: 1em; } + +.reveal h1 { + text-shadow: none; } + +/********************************************* + * OTHER + *********************************************/ +.reveal p { + margin: 20px 0; + line-height: 1.3; } + +/* Ensure certain elements are never larger than the slide itself */ +.reveal img, +.reveal video, +.reveal iframe { + max-width: 95%; + max-height: 95%; } + +.reveal strong, +.reveal b { + font-weight: bold; } + +.reveal em { + font-style: italic; } + +.reveal ol, +.reveal dl, +.reveal ul { + display: inline-block; + text-align: left; + margin: 0 0 0 1em; } + +.reveal ol { + list-style-type: decimal; } + +.reveal ul { + list-style-type: disc; } + +.reveal ul ul { + list-style-type: square; } + +.reveal ul ul ul { + list-style-type: circle; } + +.reveal ul ul, +.reveal ul ol, +.reveal ol ol, +.reveal ol ul { + display: block; + margin-left: 40px; } + +.reveal dt { + font-weight: bold; } + +.reveal dd { + margin-left: 40px; } + +.reveal blockquote { + display: block; + position: relative; + width: 70%; + margin: 20px auto; + padding: 5px; + font-style: italic; + background: rgba(255, 255, 255, 0.05); + box-shadow: 0px 0px 2px rgba(0, 0, 0, 0.2); } + +.reveal blockquote p:first-child, +.reveal blockquote p:last-child { + display: inline-block; } + +.reveal q { + font-style: italic; } + +.reveal pre { + display: block; + position: relative; + width: 90%; + margin: 20px auto; + text-align: left; + font-size: 0.55em; + font-family: monospace; + line-height: 1.2em; + word-wrap: break-word; + box-shadow: 0px 5px 15px rgba(0, 0, 0, 0.15); } + +.reveal code { + font-family: monospace; + text-transform: none; } + +.reveal pre code { + display: block; + padding: 5px; + overflow: auto; + max-height: 400px; + word-wrap: normal; } + +.reveal table { + margin: auto; + border-collapse: collapse; + border-spacing: 0; } + +.reveal table th { + font-weight: bold; } + +.reveal table th, +.reveal table td { + text-align: left; + padding: 0.2em 0.5em 0.2em 0.5em; + border-bottom: 1px solid; } + +.reveal table th[align="center"], +.reveal table td[align="center"] { + text-align: center; } + +.reveal table th[align="right"], +.reveal table td[align="right"] { + text-align: right; } + +.reveal table tbody tr:last-child th, +.reveal table tbody tr:last-child td { + border-bottom: none; } + +.reveal sup { + vertical-align: super; + font-size: smaller; } + +.reveal sub { + vertical-align: sub; + font-size: smaller; } + +.reveal small { + display: inline-block; + font-size: 0.6em; + line-height: 1.2em; + vertical-align: top; } + +.reveal small * { + vertical-align: top; } + +/********************************************* + * LINKS + *********************************************/ +.reveal a { + color: #00008B; + text-decoration: none; + -webkit-transition: color .15s ease; + -moz-transition: color .15s ease; + transition: color .15s ease; } + +.reveal a:hover { + color: #0000f1; + text-shadow: none; + border: none; } + +.reveal .roll span:after { + color: #fff; + background: #00003f; } + +/********************************************* + * IMAGES + *********************************************/ +.reveal section img { + margin: 15px 0px; + background: rgba(255, 255, 255, 0.12); + border: 4px solid #000; + box-shadow: 0 0 10px rgba(0, 0, 0, 0.15); } + +.reveal section img.plain { + border: 0; + box-shadow: none; } + +.reveal a img { + -webkit-transition: all .15s linear; + -moz-transition: all .15s linear; + transition: all .15s linear; } + +.reveal a:hover img { + background: rgba(255, 255, 255, 0.2); + border-color: #00008B; + box-shadow: 0 0 20px rgba(0, 0, 0, 0.55); } + +/********************************************* + * NAVIGATION CONTROLS + *********************************************/ +.reveal .controls { + color: #00008B; } + +/********************************************* + * PROGRESS BAR + *********************************************/ +.reveal .progress { + background: rgba(0, 0, 0, 0.2); + color: #00008B; } + +.reveal .progress span { + -webkit-transition: width 800ms cubic-bezier(0.26, 0.86, 0.44, 0.985); + -moz-transition: width 800ms cubic-bezier(0.26, 0.86, 0.44, 0.985); + transition: width 800ms cubic-bezier(0.26, 0.86, 0.44, 0.985); } + +/********************************************* + * PRINT BACKGROUND + *********************************************/ +@media print { + .backgrounds { + background-color: #fff; } } diff --git a/AdvancedCppV2/css/theme/sky.css b/AdvancedCppV2/css/theme/sky.css new file mode 100644 index 0000000..d8734c9 --- /dev/null +++ b/AdvancedCppV2/css/theme/sky.css @@ -0,0 +1,280 @@ +/** + * Sky theme for reveal.js. + * + * Copyright (C) 2011-2012 Hakim El Hattab, http://hakim.se + */ +@import url(https://fonts.googleapis.com/css?family=Quicksand:400,700,400italic,700italic); +@import url(https://fonts.googleapis.com/css?family=Open+Sans:400italic,700italic,400,700); +.reveal a { + line-height: 1.3em; } + +/********************************************* + * GLOBAL STYLES + *********************************************/ +body { + background: #add9e4; + background: -moz-radial-gradient(center, circle cover, #f7fbfc 0%, #add9e4 100%); + background: -webkit-gradient(radial, center center, 0px, center center, 100%, color-stop(0%, #f7fbfc), color-stop(100%, #add9e4)); + background: -webkit-radial-gradient(center, circle cover, #f7fbfc 0%, #add9e4 100%); + background: -o-radial-gradient(center, circle cover, #f7fbfc 0%, #add9e4 100%); + background: -ms-radial-gradient(center, circle cover, #f7fbfc 0%, #add9e4 100%); + background: radial-gradient(center, circle cover, #f7fbfc 0%, #add9e4 100%); + background-color: #f7fbfc; } + +.reveal { + font-family: "Open Sans", sans-serif; + font-size: 40px; + font-weight: normal; + color: #333; } + +::selection { + color: #fff; + background: #134674; + text-shadow: none; } + +::-moz-selection { + color: #fff; + background: #134674; + text-shadow: none; } + +.reveal .slides section, +.reveal .slides section > section { + line-height: 1.3; + font-weight: inherit; } + +/********************************************* + * HEADERS + *********************************************/ +.reveal h1, +.reveal h2, +.reveal h3, +.reveal h4, +.reveal h5, +.reveal h6 { + margin: 0 0 20px 0; + color: #333; + font-family: "Quicksand", sans-serif; + font-weight: normal; + line-height: 1.2; + letter-spacing: -0.08em; + text-transform: uppercase; + text-shadow: none; + word-wrap: break-word; } + +.reveal h1 { + font-size: 3.77em; } + +.reveal h2 { + font-size: 2.11em; } + +.reveal h3 { + font-size: 1.55em; } + +.reveal h4 { + font-size: 1em; } + +.reveal h1 { + text-shadow: none; } + +/********************************************* + * OTHER + *********************************************/ +.reveal p { + margin: 20px 0; + line-height: 1.3; } + +/* Ensure certain elements are never larger than the slide itself */ +.reveal img, +.reveal video, +.reveal iframe { + max-width: 95%; + max-height: 95%; } + +.reveal strong, +.reveal b { + font-weight: bold; } + +.reveal em { + font-style: italic; } + +.reveal ol, +.reveal dl, +.reveal ul { + display: inline-block; + text-align: left; + margin: 0 0 0 1em; } + +.reveal ol { + list-style-type: decimal; } + +.reveal ul { + list-style-type: disc; } + +.reveal ul ul { + list-style-type: square; } + +.reveal ul ul ul { + list-style-type: circle; } + +.reveal ul ul, +.reveal ul ol, +.reveal ol ol, +.reveal ol ul { + display: block; + margin-left: 40px; } + +.reveal dt { + font-weight: bold; } + +.reveal dd { + margin-left: 40px; } + +.reveal blockquote { + display: block; + position: relative; + width: 70%; + margin: 20px auto; + padding: 5px; + font-style: italic; + background: rgba(255, 255, 255, 0.05); + box-shadow: 0px 0px 2px rgba(0, 0, 0, 0.2); } + +.reveal blockquote p:first-child, +.reveal blockquote p:last-child { + display: inline-block; } + +.reveal q { + font-style: italic; } + +.reveal pre { + display: block; + position: relative; + width: 90%; + margin: 20px auto; + text-align: left; + font-size: 0.55em; + font-family: monospace; + line-height: 1.2em; + word-wrap: break-word; + box-shadow: 0px 5px 15px rgba(0, 0, 0, 0.15); } + +.reveal code { + font-family: monospace; + text-transform: none; } + +.reveal pre code { + display: block; + padding: 5px; + overflow: auto; + max-height: 400px; + word-wrap: normal; } + +.reveal table { + margin: auto; + border-collapse: collapse; + border-spacing: 0; } + +.reveal table th { + font-weight: bold; } + +.reveal table th, +.reveal table td { + text-align: left; + padding: 0.2em 0.5em 0.2em 0.5em; + border-bottom: 1px solid; } + +.reveal table th[align="center"], +.reveal table td[align="center"] { + text-align: center; } + +.reveal table th[align="right"], +.reveal table td[align="right"] { + text-align: right; } + +.reveal table tbody tr:last-child th, +.reveal table tbody tr:last-child td { + border-bottom: none; } + +.reveal sup { + vertical-align: super; + font-size: smaller; } + +.reveal sub { + vertical-align: sub; + font-size: smaller; } + +.reveal small { + display: inline-block; + font-size: 0.6em; + line-height: 1.2em; + vertical-align: top; } + +.reveal small * { + vertical-align: top; } + +/********************************************* + * LINKS + *********************************************/ +.reveal a { + color: #3b759e; + text-decoration: none; + -webkit-transition: color .15s ease; + -moz-transition: color .15s ease; + transition: color .15s ease; } + +.reveal a:hover { + color: #74a7cb; + text-shadow: none; + border: none; } + +.reveal .roll span:after { + color: #fff; + background: #264c66; } + +/********************************************* + * IMAGES + *********************************************/ +.reveal section img { + margin: 15px 0px; + background: rgba(255, 255, 255, 0.12); + border: 4px solid #333; + box-shadow: 0 0 10px rgba(0, 0, 0, 0.15); } + +.reveal section img.plain { + border: 0; + box-shadow: none; } + +.reveal a img { + -webkit-transition: all .15s linear; + -moz-transition: all .15s linear; + transition: all .15s linear; } + +.reveal a:hover img { + background: rgba(255, 255, 255, 0.2); + border-color: #3b759e; + box-shadow: 0 0 20px rgba(0, 0, 0, 0.55); } + +/********************************************* + * NAVIGATION CONTROLS + *********************************************/ +.reveal .controls { + color: #3b759e; } + +/********************************************* + * PROGRESS BAR + *********************************************/ +.reveal .progress { + background: rgba(0, 0, 0, 0.2); + color: #3b759e; } + +.reveal .progress span { + -webkit-transition: width 800ms cubic-bezier(0.26, 0.86, 0.44, 0.985); + -moz-transition: width 800ms cubic-bezier(0.26, 0.86, 0.44, 0.985); + transition: width 800ms cubic-bezier(0.26, 0.86, 0.44, 0.985); } + +/********************************************* + * PRINT BACKGROUND + *********************************************/ +@media print { + .backgrounds { + background-color: #f7fbfc; } } diff --git a/AdvancedCppV2/css/theme/solarized.css b/AdvancedCppV2/css/theme/solarized.css new file mode 100644 index 0000000..f1a2b9e --- /dev/null +++ b/AdvancedCppV2/css/theme/solarized.css @@ -0,0 +1,277 @@ +/** + * Solarized Light theme for reveal.js. + * Author: Achim Staebler + */ +@import url(../../lib/font/league-gothic/league-gothic.css); +@import url(https://fonts.googleapis.com/css?family=Lato:400,700,400italic,700italic); +/** + * Solarized colors by Ethan Schoonover + */ +html * { + color-profile: sRGB; + rendering-intent: auto; } + +/********************************************* + * GLOBAL STYLES + *********************************************/ +body { + background: #fdf6e3; + background-color: #fdf6e3; } + +.reveal { + font-family: "Lato", sans-serif; + font-size: 40px; + font-weight: normal; + color: #657b83; } + +::selection { + color: #fff; + background: #d33682; + text-shadow: none; } + +::-moz-selection { + color: #fff; + background: #d33682; + text-shadow: none; } + +.reveal .slides section, +.reveal .slides section > section { + line-height: 1.3; + font-weight: inherit; } + +/********************************************* + * HEADERS + *********************************************/ +.reveal h1, +.reveal h2, +.reveal h3, +.reveal h4, +.reveal h5, +.reveal h6 { + margin: 0 0 20px 0; + color: #586e75; + font-family: "League Gothic", Impact, sans-serif; + font-weight: normal; + line-height: 1.2; + letter-spacing: normal; + text-transform: uppercase; + text-shadow: none; + word-wrap: break-word; } + +.reveal h1 { + font-size: 3.77em; } + +.reveal h2 { + font-size: 2.11em; } + +.reveal h3 { + font-size: 1.55em; } + +.reveal h4 { + font-size: 1em; } + +.reveal h1 { + text-shadow: none; } + +/********************************************* + * OTHER + *********************************************/ +.reveal p { + margin: 20px 0; + line-height: 1.3; } + +/* Ensure certain elements are never larger than the slide itself */ +.reveal img, +.reveal video, +.reveal iframe { + max-width: 95%; + max-height: 95%; } + +.reveal strong, +.reveal b { + font-weight: bold; } + +.reveal em { + font-style: italic; } + +.reveal ol, +.reveal dl, +.reveal ul { + display: inline-block; + text-align: left; + margin: 0 0 0 1em; } + +.reveal ol { + list-style-type: decimal; } + +.reveal ul { + list-style-type: disc; } + +.reveal ul ul { + list-style-type: square; } + +.reveal ul ul ul { + list-style-type: circle; } + +.reveal ul ul, +.reveal ul ol, +.reveal ol ol, +.reveal ol ul { + display: block; + margin-left: 40px; } + +.reveal dt { + font-weight: bold; } + +.reveal dd { + margin-left: 40px; } + +.reveal blockquote { + display: block; + position: relative; + width: 70%; + margin: 20px auto; + padding: 5px; + font-style: italic; + background: rgba(255, 255, 255, 0.05); + box-shadow: 0px 0px 2px rgba(0, 0, 0, 0.2); } + +.reveal blockquote p:first-child, +.reveal blockquote p:last-child { + display: inline-block; } + +.reveal q { + font-style: italic; } + +.reveal pre { + display: block; + position: relative; + width: 90%; + margin: 20px auto; + text-align: left; + font-size: 0.55em; + font-family: monospace; + line-height: 1.2em; + word-wrap: break-word; + box-shadow: 0px 5px 15px rgba(0, 0, 0, 0.15); } + +.reveal code { + font-family: monospace; + text-transform: none; } + +.reveal pre code { + display: block; + padding: 5px; + overflow: auto; + max-height: 400px; + word-wrap: normal; } + +.reveal table { + margin: auto; + border-collapse: collapse; + border-spacing: 0; } + +.reveal table th { + font-weight: bold; } + +.reveal table th, +.reveal table td { + text-align: left; + padding: 0.2em 0.5em 0.2em 0.5em; + border-bottom: 1px solid; } + +.reveal table th[align="center"], +.reveal table td[align="center"] { + text-align: center; } + +.reveal table th[align="right"], +.reveal table td[align="right"] { + text-align: right; } + +.reveal table tbody tr:last-child th, +.reveal table tbody tr:last-child td { + border-bottom: none; } + +.reveal sup { + vertical-align: super; + font-size: smaller; } + +.reveal sub { + vertical-align: sub; + font-size: smaller; } + +.reveal small { + display: inline-block; + font-size: 0.6em; + line-height: 1.2em; + vertical-align: top; } + +.reveal small * { + vertical-align: top; } + +/********************************************* + * LINKS + *********************************************/ +.reveal a { + color: #268bd2; + text-decoration: none; + -webkit-transition: color .15s ease; + -moz-transition: color .15s ease; + transition: color .15s ease; } + +.reveal a:hover { + color: #78b9e6; + text-shadow: none; + border: none; } + +.reveal .roll span:after { + color: #fff; + background: #1a6091; } + +/********************************************* + * IMAGES + *********************************************/ +.reveal section img { + margin: 15px 0px; + background: rgba(255, 255, 255, 0.12); + border: 4px solid #657b83; + box-shadow: 0 0 10px rgba(0, 0, 0, 0.15); } + +.reveal section img.plain { + border: 0; + box-shadow: none; } + +.reveal a img { + -webkit-transition: all .15s linear; + -moz-transition: all .15s linear; + transition: all .15s linear; } + +.reveal a:hover img { + background: rgba(255, 255, 255, 0.2); + border-color: #268bd2; + box-shadow: 0 0 20px rgba(0, 0, 0, 0.55); } + +/********************************************* + * NAVIGATION CONTROLS + *********************************************/ +.reveal .controls { + color: #268bd2; } + +/********************************************* + * PROGRESS BAR + *********************************************/ +.reveal .progress { + background: rgba(0, 0, 0, 0.2); + color: #268bd2; } + +.reveal .progress span { + -webkit-transition: width 800ms cubic-bezier(0.26, 0.86, 0.44, 0.985); + -moz-transition: width 800ms cubic-bezier(0.26, 0.86, 0.44, 0.985); + transition: width 800ms cubic-bezier(0.26, 0.86, 0.44, 0.985); } + +/********************************************* + * PRINT BACKGROUND + *********************************************/ +@media print { + .backgrounds { + background-color: #fdf6e3; } } diff --git a/AdvancedCppV2/css/theme/source/beige.scss b/AdvancedCppV2/css/theme/source/beige.scss new file mode 100644 index 0000000..5564f53 --- /dev/null +++ b/AdvancedCppV2/css/theme/source/beige.scss @@ -0,0 +1,39 @@ +/** + * Beige theme for reveal.js. + * + * Copyright (C) 2011-2012 Hakim El Hattab, http://hakim.se + */ + + +// Default mixins and settings ----------------- +@import "../template/mixins"; +@import "../template/settings"; +// --------------------------------------------- + + + +// Include theme-specific fonts +@import url(../../lib/font/league-gothic/league-gothic.css); +@import url(https://fonts.googleapis.com/css?family=Lato:400,700,400italic,700italic); + + +// Override theme settings (see ../template/settings.scss) +$mainColor: #333; +$headingColor: #333; +$headingTextShadow: none; +$backgroundColor: #f7f3de; +$linkColor: #8b743d; +$linkColorHover: lighten( $linkColor, 20% ); +$selectionBackgroundColor: rgba(79, 64, 28, 0.99); +$heading1TextShadow: 0 1px 0 #ccc, 0 2px 0 #c9c9c9, 0 3px 0 #bbb, 0 4px 0 #b9b9b9, 0 5px 0 #aaa, 0 6px 1px rgba(0,0,0,.1), 0 0 5px rgba(0,0,0,.1), 0 1px 3px rgba(0,0,0,.3), 0 3px 5px rgba(0,0,0,.2), 0 5px 10px rgba(0,0,0,.25), 0 20px 20px rgba(0,0,0,.15); + +// Background generator +@mixin bodyBackground() { + @include radial-gradient( rgba(247,242,211,1), rgba(255,255,255,1) ); +} + + + +// Theme template ------------------------------ +@import "../template/theme"; +// --------------------------------------------- \ No newline at end of file diff --git a/AdvancedCppV2/css/theme/source/black.scss b/AdvancedCppV2/css/theme/source/black.scss new file mode 100644 index 0000000..4720c8a --- /dev/null +++ b/AdvancedCppV2/css/theme/source/black.scss @@ -0,0 +1,49 @@ +/** + * Black theme for reveal.js. This is the opposite of the 'white' theme. + * + * By Hakim El Hattab, http://hakim.se + */ + + +// Default mixins and settings ----------------- +@import "../template/mixins"; +@import "../template/settings"; +// --------------------------------------------- + + +// Include theme-specific fonts +@import url(../../lib/font/source-sans-pro/source-sans-pro.css); + + +// Override theme settings (see ../template/settings.scss) +$backgroundColor: #191919; + +$mainColor: #fff; +$headingColor: #fff; + +$mainFontSize: 42px; +$mainFont: 'Source Sans Pro', Helvetica, sans-serif; +$headingFont: 'Source Sans Pro', Helvetica, sans-serif; +$headingTextShadow: none; +$headingLetterSpacing: normal; +$headingTextTransform: uppercase; +$headingFontWeight: 600; +$linkColor: #42affa; +$linkColorHover: lighten( $linkColor, 15% ); +$selectionBackgroundColor: lighten( $linkColor, 25% ); + +$heading1Size: 2.5em; +$heading2Size: 1.6em; +$heading3Size: 1.3em; +$heading4Size: 1.0em; + +section.has-light-background { + &, h1, h2, h3, h4, h5, h6 { + color: #222; + } +} + + +// Theme template ------------------------------ +@import "../template/theme"; +// --------------------------------------------- \ No newline at end of file diff --git a/AdvancedCppV2/css/theme/source/blood.scss b/AdvancedCppV2/css/theme/source/blood.scss new file mode 100644 index 0000000..4533fc0 --- /dev/null +++ b/AdvancedCppV2/css/theme/source/blood.scss @@ -0,0 +1,78 @@ +/** + * Blood theme for reveal.js + * Author: Walther http://github.com/Walther + * + * Designed to be used with highlight.js theme + * "monokai_sublime.css" available from + * https://github.com/isagalaev/highlight.js/ + * + * For other themes, change $codeBackground accordingly. + * + */ + + // Default mixins and settings ----------------- +@import "../template/mixins"; +@import "../template/settings"; +// --------------------------------------------- + +// Include theme-specific fonts + +@import url(https://fonts.googleapis.com/css?family=Ubuntu:300,700,300italic,700italic); + +// Colors used in the theme +$blood: #a23; +$coal: #222; +$codeBackground: #23241f; + +$backgroundColor: $coal; + +// Main text +$mainFont: Ubuntu, 'sans-serif'; +$mainColor: #eee; + +// Headings +$headingFont: Ubuntu, 'sans-serif'; +$headingTextShadow: 2px 2px 2px $coal; + +// h1 shadow, borrowed humbly from +// (c) Default theme by Hakim El Hattab +$heading1TextShadow: 0 1px 0 #ccc, 0 2px 0 #c9c9c9, 0 3px 0 #bbb, 0 4px 0 #b9b9b9, 0 5px 0 #aaa, 0 6px 1px rgba(0,0,0,.1), 0 0 5px rgba(0,0,0,.1), 0 1px 3px rgba(0,0,0,.3), 0 3px 5px rgba(0,0,0,.2), 0 5px 10px rgba(0,0,0,.25), 0 20px 20px rgba(0,0,0,.15); + +// Links +$linkColor: $blood; +$linkColorHover: lighten( $linkColor, 20% ); + +// Text selection +$selectionBackgroundColor: $blood; +$selectionColor: #fff; + + +// Theme template ------------------------------ +@import "../template/theme"; +// --------------------------------------------- + +// some overrides after theme template import + +.reveal p { + font-weight: 300; + text-shadow: 1px 1px $coal; +} + +.reveal h1, +.reveal h2, +.reveal h3, +.reveal h4, +.reveal h5, +.reveal h6 { + font-weight: 700; +} + +.reveal p code { + background-color: $codeBackground; + display: inline-block; + border-radius: 7px; +} + +.reveal small code { + vertical-align: baseline; +} \ No newline at end of file diff --git a/AdvancedCppV2/css/theme/source/league.scss b/AdvancedCppV2/css/theme/source/league.scss new file mode 100644 index 0000000..46ea04a --- /dev/null +++ b/AdvancedCppV2/css/theme/source/league.scss @@ -0,0 +1,34 @@ +/** + * League theme for reveal.js. + * + * This was the default theme pre-3.0.0. + * + * Copyright (C) 2011-2012 Hakim El Hattab, http://hakim.se + */ + + +// Default mixins and settings ----------------- +@import "../template/mixins"; +@import "../template/settings"; +// --------------------------------------------- + + + +// Include theme-specific fonts +@import url(../../lib/font/league-gothic/league-gothic.css); +@import url(https://fonts.googleapis.com/css?family=Lato:400,700,400italic,700italic); + +// Override theme settings (see ../template/settings.scss) +$headingTextShadow: 0px 0px 6px rgba(0,0,0,0.2); +$heading1TextShadow: 0 1px 0 #ccc, 0 2px 0 #c9c9c9, 0 3px 0 #bbb, 0 4px 0 #b9b9b9, 0 5px 0 #aaa, 0 6px 1px rgba(0,0,0,.1), 0 0 5px rgba(0,0,0,.1), 0 1px 3px rgba(0,0,0,.3), 0 3px 5px rgba(0,0,0,.2), 0 5px 10px rgba(0,0,0,.25), 0 20px 20px rgba(0,0,0,.15); + +// Background generator +@mixin bodyBackground() { + @include radial-gradient( rgba(28,30,32,1), rgba(85,90,95,1) ); +} + + + +// Theme template ------------------------------ +@import "../template/theme"; +// --------------------------------------------- \ No newline at end of file diff --git a/AdvancedCppV2/css/theme/source/moon.scss b/AdvancedCppV2/css/theme/source/moon.scss new file mode 100644 index 0000000..e47e5b5 --- /dev/null +++ b/AdvancedCppV2/css/theme/source/moon.scss @@ -0,0 +1,57 @@ +/** + * Solarized Dark theme for reveal.js. + * Author: Achim Staebler + */ + + +// Default mixins and settings ----------------- +@import "../template/mixins"; +@import "../template/settings"; +// --------------------------------------------- + + + +// Include theme-specific fonts +@import url(../../lib/font/league-gothic/league-gothic.css); +@import url(https://fonts.googleapis.com/css?family=Lato:400,700,400italic,700italic); + +/** + * Solarized colors by Ethan Schoonover + */ +html * { + color-profile: sRGB; + rendering-intent: auto; +} + +// Solarized colors +$base03: #002b36; +$base02: #073642; +$base01: #586e75; +$base00: #657b83; +$base0: #839496; +$base1: #93a1a1; +$base2: #eee8d5; +$base3: #fdf6e3; +$yellow: #b58900; +$orange: #cb4b16; +$red: #dc322f; +$magenta: #d33682; +$violet: #6c71c4; +$blue: #268bd2; +$cyan: #2aa198; +$green: #859900; + +// Override theme settings (see ../template/settings.scss) +$mainColor: $base1; +$headingColor: $base2; +$headingTextShadow: none; +$backgroundColor: $base03; +$linkColor: $blue; +$linkColorHover: lighten( $linkColor, 20% ); +$selectionBackgroundColor: $magenta; + + + +// Theme template ------------------------------ +@import "../template/theme"; +// --------------------------------------------- diff --git a/AdvancedCppV2/css/theme/source/night.scss b/AdvancedCppV2/css/theme/source/night.scss new file mode 100644 index 0000000..d49a282 --- /dev/null +++ b/AdvancedCppV2/css/theme/source/night.scss @@ -0,0 +1,34 @@ +/** + * Black theme for reveal.js. + * + * Copyright (C) 2011-2012 Hakim El Hattab, http://hakim.se + */ + + +// Default mixins and settings ----------------- +@import "../template/mixins"; +@import "../template/settings"; +// --------------------------------------------- + + +// Include theme-specific fonts +@import url(https://fonts.googleapis.com/css?family=Montserrat:700); +@import url(https://fonts.googleapis.com/css?family=Open+Sans:400,700,400italic,700italic); + + +// Override theme settings (see ../template/settings.scss) +$backgroundColor: #111; + +$mainFont: 'Open Sans', sans-serif; +$linkColor: #e7ad52; +$linkColorHover: lighten( $linkColor, 20% ); +$headingFont: 'Montserrat', Impact, sans-serif; +$headingTextShadow: none; +$headingLetterSpacing: -0.03em; +$headingTextTransform: none; +$selectionBackgroundColor: #e7ad52; + + +// Theme template ------------------------------ +@import "../template/theme"; +// --------------------------------------------- \ No newline at end of file diff --git a/AdvancedCppV2/css/theme/source/serif.scss b/AdvancedCppV2/css/theme/source/serif.scss new file mode 100644 index 0000000..ec3fcb3 --- /dev/null +++ b/AdvancedCppV2/css/theme/source/serif.scss @@ -0,0 +1,35 @@ +/** + * A simple theme for reveal.js presentations, similar + * to the default theme. The accent color is brown. + * + * This theme is Copyright (C) 2012-2013 Owen Versteeg, http://owenversteeg.com - it is MIT licensed. + */ + + +// Default mixins and settings ----------------- +@import "../template/mixins"; +@import "../template/settings"; +// --------------------------------------------- + + + +// Override theme settings (see ../template/settings.scss) +$mainFont: 'Palatino Linotype', 'Book Antiqua', Palatino, FreeSerif, serif; +$mainColor: #000; +$headingFont: 'Palatino Linotype', 'Book Antiqua', Palatino, FreeSerif, serif; +$headingColor: #383D3D; +$headingTextShadow: none; +$headingTextTransform: none; +$backgroundColor: #F0F1EB; +$linkColor: #51483D; +$linkColorHover: lighten( $linkColor, 20% ); +$selectionBackgroundColor: #26351C; + +.reveal a { + line-height: 1.3em; +} + + +// Theme template ------------------------------ +@import "../template/theme"; +// --------------------------------------------- diff --git a/AdvancedCppV2/css/theme/source/simple.scss b/AdvancedCppV2/css/theme/source/simple.scss new file mode 100644 index 0000000..394c9cd --- /dev/null +++ b/AdvancedCppV2/css/theme/source/simple.scss @@ -0,0 +1,43 @@ +/** + * A simple theme for reveal.js presentations, similar + * to the default theme. The accent color is darkblue. + * + * This theme is Copyright (C) 2012 Owen Versteeg, https://github.com/StereotypicalApps. It is MIT licensed. + * reveal.js is Copyright (C) 2011-2012 Hakim El Hattab, http://hakim.se + */ + + +// Default mixins and settings ----------------- +@import "../template/mixins"; +@import "../template/settings"; +// --------------------------------------------- + + + +// Include theme-specific fonts +@import url(https://fonts.googleapis.com/css?family=News+Cycle:400,700); +@import url(https://fonts.googleapis.com/css?family=Lato:400,700,400italic,700italic); + + +// Override theme settings (see ../template/settings.scss) +$mainFont: 'Lato', sans-serif; +$mainColor: #000; +$headingFont: 'News Cycle', Impact, sans-serif; +$headingColor: #000; +$headingTextShadow: none; +$headingTextTransform: none; +$backgroundColor: #fff; +$linkColor: #00008B; +$linkColorHover: lighten( $linkColor, 20% ); +$selectionBackgroundColor: rgba(0, 0, 0, 0.99); + +section.has-dark-background { + &, h1, h2, h3, h4, h5, h6 { + color: #fff; + } +} + + +// Theme template ------------------------------ +@import "../template/theme"; +// --------------------------------------------- \ No newline at end of file diff --git a/AdvancedCppV2/css/theme/source/sky.scss b/AdvancedCppV2/css/theme/source/sky.scss new file mode 100644 index 0000000..3fee67c --- /dev/null +++ b/AdvancedCppV2/css/theme/source/sky.scss @@ -0,0 +1,46 @@ +/** + * Sky theme for reveal.js. + * + * Copyright (C) 2011-2012 Hakim El Hattab, http://hakim.se + */ + + +// Default mixins and settings ----------------- +@import "../template/mixins"; +@import "../template/settings"; +// --------------------------------------------- + + + +// Include theme-specific fonts +@import url(https://fonts.googleapis.com/css?family=Quicksand:400,700,400italic,700italic); +@import url(https://fonts.googleapis.com/css?family=Open+Sans:400italic,700italic,400,700); + + +// Override theme settings (see ../template/settings.scss) +$mainFont: 'Open Sans', sans-serif; +$mainColor: #333; +$headingFont: 'Quicksand', sans-serif; +$headingColor: #333; +$headingLetterSpacing: -0.08em; +$headingTextShadow: none; +$backgroundColor: #f7fbfc; +$linkColor: #3b759e; +$linkColorHover: lighten( $linkColor, 20% ); +$selectionBackgroundColor: #134674; + +// Fix links so they are not cut off +.reveal a { + line-height: 1.3em; +} + +// Background generator +@mixin bodyBackground() { + @include radial-gradient( #add9e4, #f7fbfc ); +} + + + +// Theme template ------------------------------ +@import "../template/theme"; +// --------------------------------------------- diff --git a/AdvancedCppV2/css/theme/source/solarized.scss b/AdvancedCppV2/css/theme/source/solarized.scss new file mode 100644 index 0000000..912be56 --- /dev/null +++ b/AdvancedCppV2/css/theme/source/solarized.scss @@ -0,0 +1,63 @@ +/** + * Solarized Light theme for reveal.js. + * Author: Achim Staebler + */ + + +// Default mixins and settings ----------------- +@import "../template/mixins"; +@import "../template/settings"; +// --------------------------------------------- + + + +// Include theme-specific fonts +@import url(../../lib/font/league-gothic/league-gothic.css); +@import url(https://fonts.googleapis.com/css?family=Lato:400,700,400italic,700italic); + + +/** + * Solarized colors by Ethan Schoonover + */ +html * { + color-profile: sRGB; + rendering-intent: auto; +} + +// Solarized colors +$base03: #002b36; +$base02: #073642; +$base01: #586e75; +$base00: #657b83; +$base0: #839496; +$base1: #93a1a1; +$base2: #eee8d5; +$base3: #fdf6e3; +$yellow: #b58900; +$orange: #cb4b16; +$red: #dc322f; +$magenta: #d33682; +$violet: #6c71c4; +$blue: #268bd2; +$cyan: #2aa198; +$green: #859900; + +// Override theme settings (see ../template/settings.scss) +$mainColor: $base00; +$headingColor: $base01; +$headingTextShadow: none; +$backgroundColor: $base3; +$linkColor: $blue; +$linkColorHover: lighten( $linkColor, 20% ); +$selectionBackgroundColor: $magenta; + +// Background generator +// @mixin bodyBackground() { +// @include radial-gradient( rgba($base3,1), rgba(lighten($base3, 20%),1) ); +// } + + + +// Theme template ------------------------------ +@import "../template/theme"; +// --------------------------------------------- diff --git a/AdvancedCppV2/css/theme/source/white.scss b/AdvancedCppV2/css/theme/source/white.scss new file mode 100644 index 0000000..7f06ffd --- /dev/null +++ b/AdvancedCppV2/css/theme/source/white.scss @@ -0,0 +1,49 @@ +/** + * White theme for reveal.js. This is the opposite of the 'black' theme. + * + * By Hakim El Hattab, http://hakim.se + */ + + +// Default mixins and settings ----------------- +@import "../template/mixins"; +@import "../template/settings"; +// --------------------------------------------- + + +// Include theme-specific fonts +@import url(../../lib/font/source-sans-pro/source-sans-pro.css); + + +// Override theme settings (see ../template/settings.scss) +$backgroundColor: #fff; + +$mainColor: #222; +$headingColor: #222; + +$mainFontSize: 42px; +$mainFont: 'Source Sans Pro', Helvetica, sans-serif; +$headingFont: 'Source Sans Pro', Helvetica, sans-serif; +$headingTextShadow: none; +$headingLetterSpacing: normal; +$headingTextTransform: uppercase; +$headingFontWeight: 600; +$linkColor: #2a76dd; +$linkColorHover: lighten( $linkColor, 15% ); +$selectionBackgroundColor: lighten( $linkColor, 25% ); + +$heading1Size: 2.5em; +$heading2Size: 1.6em; +$heading3Size: 1.3em; +$heading4Size: 1.0em; + +section.has-dark-background { + &, h1, h2, h3, h4, h5, h6 { + color: #fff; + } +} + + +// Theme template ------------------------------ +@import "../template/theme"; +// --------------------------------------------- \ No newline at end of file diff --git a/AdvancedCppV2/css/theme/template/mixins.scss b/AdvancedCppV2/css/theme/template/mixins.scss new file mode 100644 index 0000000..e0c5606 --- /dev/null +++ b/AdvancedCppV2/css/theme/template/mixins.scss @@ -0,0 +1,29 @@ +@mixin vertical-gradient( $top, $bottom ) { + background: $top; + background: -moz-linear-gradient( top, $top 0%, $bottom 100% ); + background: -webkit-gradient( linear, left top, left bottom, color-stop(0%,$top), color-stop(100%,$bottom) ); + background: -webkit-linear-gradient( top, $top 0%, $bottom 100% ); + background: -o-linear-gradient( top, $top 0%, $bottom 100% ); + background: -ms-linear-gradient( top, $top 0%, $bottom 100% ); + background: linear-gradient( top, $top 0%, $bottom 100% ); +} + +@mixin horizontal-gradient( $top, $bottom ) { + background: $top; + background: -moz-linear-gradient( left, $top 0%, $bottom 100% ); + background: -webkit-gradient( linear, left top, right top, color-stop(0%,$top), color-stop(100%,$bottom) ); + background: -webkit-linear-gradient( left, $top 0%, $bottom 100% ); + background: -o-linear-gradient( left, $top 0%, $bottom 100% ); + background: -ms-linear-gradient( left, $top 0%, $bottom 100% ); + background: linear-gradient( left, $top 0%, $bottom 100% ); +} + +@mixin radial-gradient( $outer, $inner, $type: circle ) { + background: $outer; + background: -moz-radial-gradient( center, $type cover, $inner 0%, $outer 100% ); + background: -webkit-gradient( radial, center center, 0px, center center, 100%, color-stop(0%,$inner), color-stop(100%,$outer) ); + background: -webkit-radial-gradient( center, $type cover, $inner 0%, $outer 100% ); + background: -o-radial-gradient( center, $type cover, $inner 0%, $outer 100% ); + background: -ms-radial-gradient( center, $type cover, $inner 0%, $outer 100% ); + background: radial-gradient( center, $type cover, $inner 0%, $outer 100% ); +} \ No newline at end of file diff --git a/AdvancedCppV2/css/theme/template/settings.scss b/AdvancedCppV2/css/theme/template/settings.scss new file mode 100644 index 0000000..5a917f8 --- /dev/null +++ b/AdvancedCppV2/css/theme/template/settings.scss @@ -0,0 +1,45 @@ +// Base settings for all themes that can optionally be +// overridden by the super-theme + +// Background of the presentation +$backgroundColor: #2b2b2b; + +// Primary/body text +$mainFont: 'Lato', sans-serif; +$mainFontSize: 40px; +$mainColor: #eee; + +// Vertical spacing between blocks of text +$blockMargin: 20px; + +// Headings +$headingMargin: 0 0 $blockMargin 0; +$headingFont: 'League Gothic', Impact, sans-serif; +$headingColor: #eee; +$headingLineHeight: 1.2; +$headingLetterSpacing: normal; +$headingTextTransform: uppercase; +$headingTextShadow: none; +$headingFontWeight: normal; +$heading1TextShadow: $headingTextShadow; + +$heading1Size: 3.77em; +$heading2Size: 2.11em; +$heading3Size: 1.55em; +$heading4Size: 1.00em; + +$codeFont: monospace; + +// Links and actions +$linkColor: #13DAEC; +$linkColorHover: lighten( $linkColor, 20% ); + +// Text selection +$selectionBackgroundColor: #FF5E99; +$selectionColor: #fff; + +// Generates the presentation background, can be overridden +// to return a background image or gradient +@mixin bodyBackground() { + background: $backgroundColor; +} diff --git a/AdvancedCppV2/css/theme/template/theme.scss b/AdvancedCppV2/css/theme/template/theme.scss new file mode 100644 index 0000000..9ccfaf5 --- /dev/null +++ b/AdvancedCppV2/css/theme/template/theme.scss @@ -0,0 +1,325 @@ +// Base theme template for reveal.js + +/********************************************* + * GLOBAL STYLES + *********************************************/ + +body { + @include bodyBackground(); + background-color: $backgroundColor; +} + +.reveal { + font-family: $mainFont; + font-size: $mainFontSize; + font-weight: normal; + color: $mainColor; +} + +::selection { + color: $selectionColor; + background: $selectionBackgroundColor; + text-shadow: none; +} + +::-moz-selection { + color: $selectionColor; + background: $selectionBackgroundColor; + text-shadow: none; +} + +.reveal .slides section, +.reveal .slides section>section { + line-height: 1.3; + font-weight: inherit; +} + +/********************************************* + * HEADERS + *********************************************/ + +.reveal h1, +.reveal h2, +.reveal h3, +.reveal h4, +.reveal h5, +.reveal h6 { + margin: $headingMargin; + color: $headingColor; + + font-family: $headingFont; + font-weight: $headingFontWeight; + line-height: $headingLineHeight; + letter-spacing: $headingLetterSpacing; + + text-transform: $headingTextTransform; + text-shadow: $headingTextShadow; + + word-wrap: break-word; +} + +.reveal h1 {font-size: $heading1Size; } +.reveal h2 {font-size: $heading2Size; } +.reveal h3 {font-size: $heading3Size; } +.reveal h4 {font-size: $heading4Size; } + +.reveal h1 { + text-shadow: $heading1TextShadow; +} + + +/********************************************* + * OTHER + *********************************************/ + +.reveal p { + margin: $blockMargin 0; + line-height: 1.3; +} + +/* Ensure certain elements are never larger than the slide itself */ +.reveal img, +.reveal video, +.reveal iframe { + max-width: 95%; + max-height: 95%; +} +.reveal strong, +.reveal b { + font-weight: bold; +} + +.reveal em { + font-style: italic; +} + +.reveal ol, +.reveal dl, +.reveal ul { + display: inline-block; + + text-align: left; + margin: 0 0 0 1em; +} + +.reveal ol { + list-style-type: decimal; +} + +.reveal ul { + list-style-type: disc; +} + +.reveal ul ul { + list-style-type: square; +} + +.reveal ul ul ul { + list-style-type: circle; +} + +.reveal ul ul, +.reveal ul ol, +.reveal ol ol, +.reveal ol ul { + display: block; + margin-left: 40px; +} + +.reveal dt { + font-weight: bold; +} + +.reveal dd { + margin-left: 40px; +} + +.reveal blockquote { + display: block; + position: relative; + width: 70%; + margin: $blockMargin auto; + padding: 5px; + + font-style: italic; + background: rgba(255, 255, 255, 0.05); + box-shadow: 0px 0px 2px rgba(0,0,0,0.2); +} + .reveal blockquote p:first-child, + .reveal blockquote p:last-child { + display: inline-block; + } + +.reveal q { + font-style: italic; +} + +.reveal pre { + display: block; + position: relative; + width: 90%; + margin: $blockMargin auto; + + text-align: left; + font-size: 0.55em; + font-family: $codeFont; + line-height: 1.2em; + + word-wrap: break-word; + + box-shadow: 0px 5px 15px rgba(0, 0, 0, 0.15); +} + +.reveal code { + font-family: $codeFont; + text-transform: none; +} + +.reveal pre code { + display: block; + padding: 5px; + overflow: auto; + max-height: 400px; + word-wrap: normal; +} + +.reveal table { + margin: auto; + border-collapse: collapse; + border-spacing: 0; +} + +.reveal table th { + font-weight: bold; +} + +.reveal table th, +.reveal table td { + text-align: left; + padding: 0.2em 0.5em 0.2em 0.5em; + border-bottom: 1px solid; +} + +.reveal table th[align="center"], +.reveal table td[align="center"] { + text-align: center; +} + +.reveal table th[align="right"], +.reveal table td[align="right"] { + text-align: right; +} + +.reveal table tbody tr:last-child th, +.reveal table tbody tr:last-child td { + border-bottom: none; +} + +.reveal sup { + vertical-align: super; + font-size: smaller; +} +.reveal sub { + vertical-align: sub; + font-size: smaller; +} + +.reveal small { + display: inline-block; + font-size: 0.6em; + line-height: 1.2em; + vertical-align: top; +} + +.reveal small * { + vertical-align: top; +} + + +/********************************************* + * LINKS + *********************************************/ + +.reveal a { + color: $linkColor; + text-decoration: none; + + -webkit-transition: color .15s ease; + -moz-transition: color .15s ease; + transition: color .15s ease; +} + .reveal a:hover { + color: $linkColorHover; + + text-shadow: none; + border: none; + } + +.reveal .roll span:after { + color: #fff; + background: darken( $linkColor, 15% ); +} + + +/********************************************* + * IMAGES + *********************************************/ + +.reveal section img { + margin: 15px 0px; + background: rgba(255,255,255,0.12); + border: 4px solid $mainColor; + + box-shadow: 0 0 10px rgba(0, 0, 0, 0.15); +} + + .reveal section img.plain { + border: 0; + box-shadow: none; + } + + .reveal a img { + -webkit-transition: all .15s linear; + -moz-transition: all .15s linear; + transition: all .15s linear; + } + + .reveal a:hover img { + background: rgba(255,255,255,0.2); + border-color: $linkColor; + + box-shadow: 0 0 20px rgba(0, 0, 0, 0.55); + } + + +/********************************************* + * NAVIGATION CONTROLS + *********************************************/ + +.reveal .controls { + color: $linkColor; +} + + +/********************************************* + * PROGRESS BAR + *********************************************/ + +.reveal .progress { + background: rgba(0,0,0,0.2); + color: $linkColor; +} + .reveal .progress span { + -webkit-transition: width 800ms cubic-bezier(0.260, 0.860, 0.440, 0.985); + -moz-transition: width 800ms cubic-bezier(0.260, 0.860, 0.440, 0.985); + transition: width 800ms cubic-bezier(0.260, 0.860, 0.440, 0.985); + } + +/********************************************* + * PRINT BACKGROUND + *********************************************/ + @media print { + .backgrounds { + background-color: $backgroundColor; + } +} diff --git a/AdvancedCppV2/css/theme/white.css b/AdvancedCppV2/css/theme/white.css new file mode 100644 index 0000000..43ef2c7 --- /dev/null +++ b/AdvancedCppV2/css/theme/white.css @@ -0,0 +1,273 @@ +/** + * White theme for reveal.js. This is the opposite of the 'black' theme. + * + * By Hakim El Hattab, http://hakim.se + */ +@import url(../../lib/font/source-sans-pro/source-sans-pro.css); +section.has-dark-background, section.has-dark-background h1, section.has-dark-background h2, section.has-dark-background h3, section.has-dark-background h4, section.has-dark-background h5, section.has-dark-background h6 { + color: #fff; } + +/********************************************* + * GLOBAL STYLES + *********************************************/ +body { + background: #fff; + background-color: #fff; } + +.reveal { + font-family: "Source Sans Pro", Helvetica, sans-serif; + font-size: 42px; + font-weight: normal; + color: #222; } + +::selection { + color: #fff; + background: #98bdef; + text-shadow: none; } + +::-moz-selection { + color: #fff; + background: #98bdef; + text-shadow: none; } + +.reveal .slides section, +.reveal .slides section > section { + line-height: 1.3; + font-weight: inherit; } + +/********************************************* + * HEADERS + *********************************************/ +.reveal h1, +.reveal h2, +.reveal h3, +.reveal h4, +.reveal h5, +.reveal h6 { + margin: 0 0 20px 0; + color: #222; + font-family: "Source Sans Pro", Helvetica, sans-serif; + font-weight: 600; + line-height: 1.2; + letter-spacing: normal; + text-transform: uppercase; + text-shadow: none; + word-wrap: break-word; } + +.reveal h1 { + font-size: 2.5em; } + +.reveal h2 { + font-size: 1.6em; } + +.reveal h3 { + font-size: 1.3em; } + +.reveal h4 { + font-size: 1em; } + +.reveal h1 { + text-shadow: none; } + +/********************************************* + * OTHER + *********************************************/ +.reveal p { + margin: 20px 0; + line-height: 1.3; } + +/* Ensure certain elements are never larger than the slide itself */ +.reveal img, +.reveal video, +.reveal iframe { + max-width: 95%; + max-height: 95%; } + +.reveal strong, +.reveal b { + font-weight: bold; } + +.reveal em { + font-style: italic; } + +.reveal ol, +.reveal dl, +.reveal ul { + display: inline-block; + text-align: left; + margin: 0 0 0 1em; } + +.reveal ol { + list-style-type: decimal; } + +.reveal ul { + list-style-type: disc; } + +.reveal ul ul { + list-style-type: square; } + +.reveal ul ul ul { + list-style-type: circle; } + +.reveal ul ul, +.reveal ul ol, +.reveal ol ol, +.reveal ol ul { + display: block; + margin-left: 40px; } + +.reveal dt { + font-weight: bold; } + +.reveal dd { + margin-left: 40px; } + +.reveal blockquote { + display: block; + position: relative; + width: 70%; + margin: 20px auto; + padding: 5px; + font-style: italic; + background: rgba(255, 255, 255, 0.05); + box-shadow: 0px 0px 2px rgba(0, 0, 0, 0.2); } + +.reveal blockquote p:first-child, +.reveal blockquote p:last-child { + display: inline-block; } + +.reveal q { + font-style: italic; } + +.reveal pre { + display: block; + position: relative; + width: 90%; + margin: 20px auto; + text-align: left; + font-size: 0.55em; + font-family: monospace; + line-height: 1.2em; + word-wrap: break-word; + box-shadow: 0px 5px 15px rgba(0, 0, 0, 0.15); } + +.reveal code { + font-family: monospace; + text-transform: none; } + +.reveal pre code { + display: block; + padding: 5px; + overflow: auto; + max-height: 400px; + word-wrap: normal; } + +.reveal table { + margin: auto; + border-collapse: collapse; + border-spacing: 0; } + +.reveal table th { + font-weight: bold; } + +.reveal table th, +.reveal table td { + text-align: left; + padding: 0.2em 0.5em 0.2em 0.5em; + border-bottom: 1px solid; } + +.reveal table th[align="center"], +.reveal table td[align="center"] { + text-align: center; } + +.reveal table th[align="right"], +.reveal table td[align="right"] { + text-align: right; } + +.reveal table tbody tr:last-child th, +.reveal table tbody tr:last-child td { + border-bottom: none; } + +.reveal sup { + vertical-align: super; + font-size: smaller; } + +.reveal sub { + vertical-align: sub; + font-size: smaller; } + +.reveal small { + display: inline-block; + font-size: 0.6em; + line-height: 1.2em; + vertical-align: top; } + +.reveal small * { + vertical-align: top; } + +/********************************************* + * LINKS + *********************************************/ +.reveal a { + color: #2a76dd; + text-decoration: none; + -webkit-transition: color .15s ease; + -moz-transition: color .15s ease; + transition: color .15s ease; } + +.reveal a:hover { + color: #6ca0e8; + text-shadow: none; + border: none; } + +.reveal .roll span:after { + color: #fff; + background: #1a53a1; } + +/********************************************* + * IMAGES + *********************************************/ +.reveal section img { + margin: 15px 0px; + background: rgba(255, 255, 255, 0.12); + border: 4px solid #222; + box-shadow: 0 0 10px rgba(0, 0, 0, 0.15); } + +.reveal section img.plain { + border: 0; + box-shadow: none; } + +.reveal a img { + -webkit-transition: all .15s linear; + -moz-transition: all .15s linear; + transition: all .15s linear; } + +.reveal a:hover img { + background: rgba(255, 255, 255, 0.2); + border-color: #2a76dd; + box-shadow: 0 0 20px rgba(0, 0, 0, 0.55); } + +/********************************************* + * NAVIGATION CONTROLS + *********************************************/ +.reveal .controls { + color: #2a76dd; } + +/********************************************* + * PROGRESS BAR + *********************************************/ +.reveal .progress { + background: rgba(0, 0, 0, 0.2); + color: #2a76dd; } + +.reveal .progress span { + -webkit-transition: width 800ms cubic-bezier(0.26, 0.86, 0.44, 0.985); + -moz-transition: width 800ms cubic-bezier(0.26, 0.86, 0.44, 0.985); + transition: width 800ms cubic-bezier(0.26, 0.86, 0.44, 0.985); } + +/********************************************* + * PRINT BACKGROUND + *********************************************/ +@media print { + .backgrounds { + background-color: #fff; } } diff --git a/AdvancedCppV2/demo.html b/AdvancedCppV2/demo.html new file mode 100644 index 0000000..cf05e88 --- /dev/null +++ b/AdvancedCppV2/demo.html @@ -0,0 +1,425 @@ + + + + + + + reveal.js – The HTML Presentation Framework + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+
+

Reveal.js

+

The HTML Presentation Framework

+

+ Created by Hakim El Hattab and contributors +

+
+ +
+

Hello There

+

+ reveal.js enables you to create beautiful interactive slide decks using HTML. This presentation will show you examples of what it can do. +

+
+ + +
+
+

Vertical Slides

+

Slides can be nested inside of each other.

+

Use the Space key to navigate through all slides.

+
+ + Down arrow + +
+
+

Basement Level 1

+

Nested slides are useful for adding additional detail underneath a high level horizontal slide.

+
+
+

Basement Level 2

+

That's it, time to go back up.

+
+ + Up arrow + +
+
+ +
+

Slides

+

+ Not a coder? Not a problem. There's a fully-featured visual editor for authoring these, try it out at https://slides.com. +

+
+ +
+

Point of View

+

+ Press ESC to enter the slide overview. +

+

+ Hold down the alt key (ctrl in Linux) and click on any element to zoom towards it using zoom.js. Click again to zoom back out. +

+

+ (NOTE: Use ctrl + click in Linux.) +

+
+ +
+

Touch Optimized

+

+ Presentations look great on touch devices, like mobile phones and tablets. Simply swipe through your slides. +

+
+ +
+ +
+ +
+
+

Fragments

+

Hit the next arrow...

+

... to step through ...

+

... a fragmented slide.

+ + +
+
+

Fragment Styles

+

There's different types of fragments, like:

+

grow

+

shrink

+

fade-out

+

+ fade-right, + up, + down, + left +

+

fade-in-then-out

+

fade-in-then-semi-out

+

Highlight red blue green

+
+
+ +
+

Transition Styles

+

+ You can select from different transitions, like:
+ None - + Fade - + Slide - + Convex - + Concave - + Zoom +

+
+ +
+

Themes

+

+ reveal.js comes with a few themes built in:
+ + Black (default) - + White - + League - + Sky - + Beige - + Simple
+ Serif - + Blood - + Night - + Moon - + Solarized +

+
+ +
+
+

Slide Backgrounds

+

+ Set data-background="#dddddd" on a slide to change the background color. All CSS color formats are supported. +

+ + Down arrow + +
+
+

Image Backgrounds

+
<section data-background="image.png">
+
+
+

Tiled Backgrounds

+
<section data-background="image.png" data-background-repeat="repeat" data-background-size="100px">
+
+
+
+

Video Backgrounds

+
<section data-background-video="video.mp4,video.webm">
+
+
+
+

... and GIFs!

+
+
+ +
+

Background Transitions

+

+ Different background transitions are available via the backgroundTransition option. This one's called "zoom". +

+
Reveal.configure({ backgroundTransition: 'zoom' })
+
+ +
+

Background Transitions

+

+ You can override background transitions per-slide. +

+
<section data-background-transition="zoom">
+
+ +
+
+

Iframe Backgrounds

+

Since reveal.js runs on the web, you can easily embed other web content. Try interacting with the page in the background.

+
+
+ +
+

Pretty Code

+

+import React, { useState } from 'react';
+
+function Example() {
+  const [count, setCount] = useState(0);
+
+  return (
+    <div>
+      <p>You clicked {count} times</p>
+      <button onClick={() => setCount(count + 1)}>
+        Click me
+      </button>
+    </div>
+  );
+}
+					
+

Code syntax highlighting courtesy of highlight.js.

+
+ +
+

Marvelous List

+
    +
  • No order here
  • +
  • Or here
  • +
  • Or here
  • +
  • Or here
  • +
+
+ +
+

Fantastic Ordered List

+
    +
  1. One is smaller than...
  2. +
  3. Two is smaller than...
  4. +
  5. Three!
  6. +
+
+ +
+

Tabular Tables

+ + + + + + + + + + + + + + + + + + + + + + + + + +
ItemValueQuantity
Apples$17
Lemonade$218
Bread$32
+
+ +
+

Clever Quotes

+

+ These guys come in two forms, inline: The nice thing about standards is that there are so many to choose from and block: +

+
+ “For years there has been a theory that millions of monkeys typing at random on millions of typewriters would + reproduce the entire works of Shakespeare. The Internet has proven this theory to be untrue.” +
+
+ +
+

Intergalactic Interconnections

+

+ You can link between slides internally, + like this. +

+
+ +
+

Speaker View

+

There's a speaker view. It includes a timer, preview of the upcoming slide as well as your speaker notes.

+

Press the S key to try it out.

+ + +
+ +
+

Export to PDF

+

Presentations can be exported to PDF, here's an example:

+ +
+ +
+

Global State

+

+ Set data-state="something" on a slide and "something" + will be added as a class to the document element when the slide is open. This lets you + apply broader style changes, like switching the page background. +

+
+ +
+

State Events

+

+ Additionally custom events can be triggered on a per slide basis by binding to the data-state name. +

+

+Reveal.addEventListener( 'customevent', function() {
+	console.log( '"customevent" has fired' );
+} );
+					
+
+ +
+

Take a Moment

+

+ Press B or . on your keyboard to pause the presentation. This is helpful when you're on stage and want to take distracting slides off the screen. +

+
+ +
+

Much more

+ +
+ +
+

THE END

+

+ - Try the online editor
+ - Source code & documentation +

+
+ +
+ +
+ + + + + + + diff --git a/AdvancedCppV2/gruntfile.js b/AdvancedCppV2/gruntfile.js new file mode 100644 index 0000000..acf34b6 --- /dev/null +++ b/AdvancedCppV2/gruntfile.js @@ -0,0 +1,189 @@ +const sass = require('node-sass'); + +module.exports = grunt => { + + require('load-grunt-tasks')(grunt); + + let port = grunt.option('port') || 8000; + let root = grunt.option('root') || '.'; + + if (!Array.isArray(root)) root = [root]; + + // Project configuration + grunt.initConfig({ + pkg: grunt.file.readJSON('package.json'), + meta: { + banner: + '/*!\n' + + ' * reveal.js <%= pkg.version %> (<%= grunt.template.today("yyyy-mm-dd, HH:MM") %>)\n' + + ' * http://revealjs.com\n' + + ' * MIT licensed\n' + + ' *\n' + + ' * Copyright (C) 2020 Hakim El Hattab, http://hakim.se\n' + + ' */' + }, + + qunit: { + files: [ 'test/*.html' ] + }, + + uglify: { + options: { + banner: '<%= meta.banner %>\n', + ie8: true + }, + build: { + src: 'js/reveal.js', + dest: 'js/reveal.min.js' + } + }, + + sass: { + options: { + implementation: sass, + sourceMap: false + }, + core: { + src: 'css/reveal.scss', + dest: 'css/reveal.css' + }, + themes: { + expand: true, + cwd: 'css/theme/source', + src: ['*.sass', '*.scss'], + dest: 'css/theme', + ext: '.css' + } + }, + + autoprefixer: { + core: { + src: 'css/reveal.css' + } + }, + + cssmin: { + options: { + compatibility: 'ie9' + }, + compress: { + src: 'css/reveal.css', + dest: 'css/reveal.min.css' + } + }, + + jshint: { + options: { + curly: false, + eqeqeq: true, + immed: true, + esnext: true, + latedef: 'nofunc', + newcap: true, + noarg: true, + sub: true, + undef: true, + eqnull: true, + browser: true, + expr: true, + loopfunc: true, + globals: { + head: false, + module: false, + console: false, + unescape: false, + define: false, + exports: false, + require: false + } + }, + files: [ 'gruntfile.js', 'js/reveal.js' ] + }, + + connect: { + server: { + options: { + port: port, + base: root, + livereload: true, + open: true, + useAvailablePort: true + } + } + }, + + zip: { + bundle: { + src: [ + 'index.html', + 'css/**', + 'js/**', + 'lib/**', + 'images/**', + 'plugin/**', + '**.md' + ], + dest: 'reveal-js-presentation.zip' + } + }, + + watch: { + js: { + files: [ 'gruntfile.js', 'js/reveal.js' ], + tasks: 'js' + }, + theme: { + files: [ + 'css/theme/source/*.sass', + 'css/theme/source/*.scss', + 'css/theme/template/*.sass', + 'css/theme/template/*.scss' + ], + tasks: 'css-themes' + }, + css: { + files: [ 'css/reveal.scss' ], + tasks: 'css-core' + }, + test: { + files: [ 'test/*.html' ], + tasks: 'test' + }, + html: { + files: root.map(path => path + '/*.html') + }, + markdown: { + files: root.map(path => path + '/*.md') + }, + options: { + livereload: true + } + } + + }); + + // Default task + grunt.registerTask( 'default', [ 'css', 'js' ] ); + + // JS task + grunt.registerTask( 'js', [ 'jshint', 'uglify', 'qunit' ] ); + + // Theme CSS + grunt.registerTask( 'css-themes', [ 'sass:themes' ] ); + + // Core framework CSS + grunt.registerTask( 'css-core', [ 'sass:core', 'autoprefixer', 'cssmin' ] ); + + // All CSS + grunt.registerTask( 'css', [ 'sass', 'autoprefixer', 'cssmin' ] ); + + // Package presentation to archive + grunt.registerTask( 'package', [ 'default', 'zip' ] ); + + // Serve presentation locally + grunt.registerTask( 'serve', [ 'connect', 'watch' ] ); + + // Run tests + grunt.registerTask( 'test', [ 'jshint', 'qunit' ] ); + +}; diff --git a/AdvancedCppV2/img/altkom_logo.png b/AdvancedCppV2/img/altkom_logo.png new file mode 100644 index 0000000..abf0643 Binary files /dev/null and b/AdvancedCppV2/img/altkom_logo.png differ diff --git a/AdvancedCppV2/img/altkom_logo2.png b/AdvancedCppV2/img/altkom_logo2.png new file mode 100644 index 0000000..b995fc7 Binary files /dev/null and b/AdvancedCppV2/img/altkom_logo2.png differ diff --git a/AdvancedCppV2/img/cpp_logo.png b/AdvancedCppV2/img/cpp_logo.png new file mode 100644 index 0000000..432d4eb Binary files /dev/null and b/AdvancedCppV2/img/cpp_logo.png differ diff --git a/AdvancedCppV2/img/mateusz.png b/AdvancedCppV2/img/mateusz.png new file mode 100644 index 0000000..139f905 Binary files /dev/null and b/AdvancedCppV2/img/mateusz.png differ diff --git a/AdvancedCppV2/js/reveal.js b/AdvancedCppV2/js/reveal.js new file mode 100644 index 0000000..a1357a6 --- /dev/null +++ b/AdvancedCppV2/js/reveal.js @@ -0,0 +1,6191 @@ +/*! + * reveal.js + * http://revealjs.com + * MIT licensed + * + * Copyright (C) 2020 Hakim El Hattab, http://hakim.se + */ +(function( root, factory ) { + if( typeof define === 'function' && define.amd ) { + // AMD. Register as an anonymous module. + define( function() { + root.Reveal = factory(); + return root.Reveal; + } ); + } else if( typeof exports === 'object' ) { + // Node. Does not work with strict CommonJS. + module.exports = factory(); + } else { + // Browser globals. + root.Reveal = factory(); + } +}( this, function() { + + 'use strict'; + + var Reveal; + + // The reveal.js version + var VERSION = '3.9.2'; + + var SLIDES_SELECTOR = '.slides section', + HORIZONTAL_SLIDES_SELECTOR = '.slides>section', + VERTICAL_SLIDES_SELECTOR = '.slides>section.present>section', + HOME_SLIDE_SELECTOR = '.slides>section:first-of-type', + + UA = navigator.userAgent, + + // Methods that may not be invoked via the postMessage API + POST_MESSAGE_METHOD_BLACKLIST = /registerPlugin|registerKeyboardShortcut|addKeyBinding|addEventListener/, + + // Configuration defaults, can be overridden at initialization time + config = { + + // The "normal" size of the presentation, aspect ratio will be preserved + // when the presentation is scaled to fit different resolutions + width: 960, + height: 700, + + // Factor of the display size that should remain empty around the content + margin: 0.04, + + // Bounds for smallest/largest possible scale to apply to content + minScale: 0.2, + maxScale: 2.0, + + // Display presentation control arrows + controls: true, + + // Help the user learn the controls by providing hints, for example by + // bouncing the down arrow when they first encounter a vertical slide + controlsTutorial: true, + + // Determines where controls appear, "edges" or "bottom-right" + controlsLayout: 'bottom-right', + + // Visibility rule for backwards navigation arrows; "faded", "hidden" + // or "visible" + controlsBackArrows: 'faded', + + // Display a presentation progress bar + progress: true, + + // Display the page number of the current slide + // - true: Show slide number + // - false: Hide slide number + // + // Can optionally be set as a string that specifies the number formatting: + // - "h.v": Horizontal . vertical slide number (default) + // - "h/v": Horizontal / vertical slide number + // - "c": Flattened slide number + // - "c/t": Flattened slide number / total slides + // + // Alternatively, you can provide a function that returns the slide + // number for the current slide. The function should take in a slide + // object and return an array with one string [slideNumber] or + // three strings [n1,delimiter,n2]. See #formatSlideNumber(). + slideNumber: false, + + // Can be used to limit the contexts in which the slide number appears + // - "all": Always show the slide number + // - "print": Only when printing to PDF + // - "speaker": Only in the speaker view + showSlideNumber: 'all', + + // Use 1 based indexing for # links to match slide number (default is zero + // based) + hashOneBasedIndex: false, + + // Add the current slide number to the URL hash so that reloading the + // page/copying the URL will return you to the same slide + hash: false, + + // Push each slide change to the browser history. Implies `hash: true` + history: false, + + // Enable keyboard shortcuts for navigation + keyboard: true, + + // Optional function that blocks keyboard events when retuning false + keyboardCondition: null, + + // Enable the slide overview mode + overview: true, + + // Disables the default reveal.js slide layout so that you can use + // custom CSS layout + disableLayout: false, + + // Vertical centering of slides + center: true, + + // Enables touch navigation on devices with touch input + touch: true, + + // Loop the presentation + loop: false, + + // Change the presentation direction to be RTL + rtl: false, + + // Changes the behavior of our navigation directions. + // + // "default" + // Left/right arrow keys step between horizontal slides, up/down + // arrow keys step between vertical slides. Space key steps through + // all slides (both horizontal and vertical). + // + // "linear" + // Removes the up/down arrows. Left/right arrows step through all + // slides (both horizontal and vertical). + // + // "grid" + // When this is enabled, stepping left/right from a vertical stack + // to an adjacent vertical stack will land you at the same vertical + // index. + // + // Consider a deck with six slides ordered in two vertical stacks: + // 1.1 2.1 + // 1.2 2.2 + // 1.3 2.3 + // + // If you're on slide 1.3 and navigate right, you will normally move + // from 1.3 -> 2.1. If "grid" is used, the same navigation takes you + // from 1.3 -> 2.3. + navigationMode: 'default', + + // Randomizes the order of slides each time the presentation loads + shuffle: false, + + // Turns fragments on and off globally + fragments: true, + + // Flags whether to include the current fragment in the URL, + // so that reloading brings you to the same fragment position + fragmentInURL: false, + + // Flags if the presentation is running in an embedded mode, + // i.e. contained within a limited portion of the screen + embedded: false, + + // Flags if we should show a help overlay when the question-mark + // key is pressed + help: true, + + // Flags if it should be possible to pause the presentation (blackout) + pause: true, + + // Flags if speaker notes should be visible to all viewers + showNotes: false, + + // Global override for autolaying embedded media (video/audio/iframe) + // - null: Media will only autoplay if data-autoplay is present + // - true: All media will autoplay, regardless of individual setting + // - false: No media will autoplay, regardless of individual setting + autoPlayMedia: null, + + // Global override for preloading lazy-loaded iframes + // - null: Iframes with data-src AND data-preload will be loaded when within + // the viewDistance, iframes with only data-src will be loaded when visible + // - true: All iframes with data-src will be loaded when within the viewDistance + // - false: All iframes with data-src will be loaded only when visible + preloadIframes: null, + + // Controls automatic progression to the next slide + // - 0: Auto-sliding only happens if the data-autoslide HTML attribute + // is present on the current slide or fragment + // - 1+: All slides will progress automatically at the given interval + // - false: No auto-sliding, even if data-autoslide is present + autoSlide: 0, + + // Stop auto-sliding after user input + autoSlideStoppable: true, + + // Use this method for navigation when auto-sliding (defaults to navigateNext) + autoSlideMethod: null, + + // Specify the average time in seconds that you think you will spend + // presenting each slide. This is used to show a pacing timer in the + // speaker view + defaultTiming: null, + + // Enable slide navigation via mouse wheel + mouseWheel: false, + + // Apply a 3D roll to links on hover + rollingLinks: false, + + // Hides the address bar on mobile devices + hideAddressBar: true, + + // Opens links in an iframe preview overlay + // Add `data-preview-link` and `data-preview-link="false"` to customise each link + // individually + previewLinks: false, + + // Exposes the reveal.js API through window.postMessage + postMessage: true, + + // Dispatches all reveal.js events to the parent window through postMessage + postMessageEvents: false, + + // Focuses body when page changes visibility to ensure keyboard shortcuts work + focusBodyOnPageVisibilityChange: true, + + // Transition style + transition: 'slide', // none/fade/slide/convex/concave/zoom + + // Transition speed + transitionSpeed: 'default', // default/fast/slow + + // Transition style for full page slide backgrounds + backgroundTransition: 'fade', // none/fade/slide/convex/concave/zoom + + // Parallax background image + parallaxBackgroundImage: '', // CSS syntax, e.g. "a.jpg" + + // Parallax background size + parallaxBackgroundSize: '', // CSS syntax, e.g. "3000px 2000px" + + // Parallax background repeat + parallaxBackgroundRepeat: '', // repeat/repeat-x/repeat-y/no-repeat/initial/inherit + + // Parallax background position + parallaxBackgroundPosition: '', // CSS syntax, e.g. "top left" + + // Amount of pixels to move the parallax background per slide step + parallaxBackgroundHorizontal: null, + parallaxBackgroundVertical: null, + + // The maximum number of pages a single slide can expand onto when printing + // to PDF, unlimited by default + pdfMaxPagesPerSlide: Number.POSITIVE_INFINITY, + + // Prints each fragment on a separate slide + pdfSeparateFragments: true, + + // Offset used to reduce the height of content within exported PDF pages. + // This exists to account for environment differences based on how you + // print to PDF. CLI printing options, like phantomjs and wkpdf, can end + // on precisely the total height of the document whereas in-browser + // printing has to end one pixel before. + pdfPageHeightOffset: -1, + + // Number of slides away from the current that are visible + viewDistance: 3, + + // Number of slides away from the current that are visible on mobile + // devices. It is advisable to set this to a lower number than + // viewDistance in order to save resources. + mobileViewDistance: 2, + + // The display mode that will be used to show slides + display: 'block', + + // Hide cursor if inactive + hideInactiveCursor: true, + + // Time before the cursor is hidden (in ms) + hideCursorTime: 5000, + + // Script dependencies to load + dependencies: [] + + }, + + // Flags if Reveal.initialize() has been called + initialized = false, + + // Flags if reveal.js is loaded (has dispatched the 'ready' event) + loaded = false, + + // Flags if the overview mode is currently active + overview = false, + + // Holds the dimensions of our overview slides, including margins + overviewSlideWidth = null, + overviewSlideHeight = null, + + // The horizontal and vertical index of the currently active slide + indexh, + indexv, + + // The previous and current slide HTML elements + previousSlide, + currentSlide, + + previousBackground, + + // Remember which directions that the user has navigated towards + hasNavigatedRight = false, + hasNavigatedDown = false, + + // Slides may hold a data-state attribute which we pick up and apply + // as a class to the body. This list contains the combined state of + // all current slides. + state = [], + + // The current scale of the presentation (see width/height config) + scale = 1, + + // CSS transform that is currently applied to the slides container, + // split into two groups + slidesTransform = { layout: '', overview: '' }, + + // Cached references to DOM elements + dom = {}, + + // A list of registered reveal.js plugins + plugins = {}, + + // List of asynchronously loaded reveal.js dependencies + asyncDependencies = [], + + // Features supported by the browser, see #checkCapabilities() + features = {}, + + // Client is a mobile device, see #checkCapabilities() + isMobileDevice, + + // Client is a desktop Chrome, see #checkCapabilities() + isChrome, + + // Throttles mouse wheel navigation + lastMouseWheelStep = 0, + + // Delays updates to the URL due to a Chrome thumbnailer bug + writeURLTimeout = 0, + + // Is the mouse pointer currently hidden from view + cursorHidden = false, + + // Timeout used to determine when the cursor is inactive + cursorInactiveTimeout = 0, + + // Flags if the interaction event listeners are bound + eventsAreBound = false, + + // The current auto-slide duration + autoSlide = 0, + + // Auto slide properties + autoSlidePlayer, + autoSlideTimeout = 0, + autoSlideStartTime = -1, + autoSlidePaused = false, + + // Holds information about the currently ongoing touch input + touch = { + startX: 0, + startY: 0, + startCount: 0, + captured: false, + threshold: 40 + }, + + // A key:value map of shortcut keyboard keys and descriptions of + // the actions they trigger, generated in #configure() + keyboardShortcuts = {}, + + // Holds custom key code mappings + registeredKeyBindings = {}; + + /** + * Starts up the presentation if the client is capable. + */ + function initialize( options ) { + + // Make sure we only initialize once + if( initialized === true ) return; + + initialized = true; + + checkCapabilities(); + + if( !features.transforms2d && !features.transforms3d ) { + document.body.setAttribute( 'class', 'no-transforms' ); + + // Since JS won't be running any further, we load all lazy + // loading elements upfront + var images = toArray( document.getElementsByTagName( 'img' ) ), + iframes = toArray( document.getElementsByTagName( 'iframe' ) ); + + var lazyLoadable = images.concat( iframes ); + + for( var i = 0, len = lazyLoadable.length; i < len; i++ ) { + var element = lazyLoadable[i]; + if( element.getAttribute( 'data-src' ) ) { + element.setAttribute( 'src', element.getAttribute( 'data-src' ) ); + element.removeAttribute( 'data-src' ); + } + } + + // If the browser doesn't support core features we won't be + // using JavaScript to control the presentation + return; + } + + // Cache references to key DOM elements + dom.wrapper = document.querySelector( '.reveal' ); + dom.slides = document.querySelector( '.reveal .slides' ); + + // Force a layout when the whole page, incl fonts, has loaded + window.addEventListener( 'load', layout, false ); + + var query = Reveal.getQueryHash(); + + // Do not accept new dependencies via query config to avoid + // the potential of malicious script injection + if( typeof query['dependencies'] !== 'undefined' ) delete query['dependencies']; + + // Copy options over to our config object + extend( config, options ); + extend( config, query ); + + // Hide the address bar in mobile browsers + hideAddressBar(); + + // Loads dependencies and continues to #start() once done + load(); + + } + + /** + * Inspect the client to see what it's capable of, this + * should only happens once per runtime. + */ + function checkCapabilities() { + + isMobileDevice = /(iphone|ipod|ipad|android)/gi.test( UA ) || + ( navigator.platform === 'MacIntel' && navigator.maxTouchPoints > 1 ); // iPadOS + isChrome = /chrome/i.test( UA ) && !/edge/i.test( UA ); + + var testElement = document.createElement( 'div' ); + + features.transforms3d = 'WebkitPerspective' in testElement.style || + 'MozPerspective' in testElement.style || + 'msPerspective' in testElement.style || + 'OPerspective' in testElement.style || + 'perspective' in testElement.style; + + features.transforms2d = 'WebkitTransform' in testElement.style || + 'MozTransform' in testElement.style || + 'msTransform' in testElement.style || + 'OTransform' in testElement.style || + 'transform' in testElement.style; + + features.requestAnimationFrameMethod = window.requestAnimationFrame || window.webkitRequestAnimationFrame || window.mozRequestAnimationFrame; + features.requestAnimationFrame = typeof features.requestAnimationFrameMethod === 'function'; + + features.canvas = !!document.createElement( 'canvas' ).getContext; + + // Transitions in the overview are disabled in desktop and + // Safari due to lag + features.overviewTransitions = !/Version\/[\d\.]+.*Safari/.test( UA ); + + // Flags if we should use zoom instead of transform to scale + // up slides. Zoom produces crisper results but has a lot of + // xbrowser quirks so we only use it in whitelsited browsers. + features.zoom = 'zoom' in testElement.style && !isMobileDevice && + ( isChrome || /Version\/[\d\.]+.*Safari/.test( UA ) ); + + } + + /** + * Loads the dependencies of reveal.js. Dependencies are + * defined via the configuration option 'dependencies' + * and will be loaded prior to starting/binding reveal.js. + * Some dependencies may have an 'async' flag, if so they + * will load after reveal.js has been started up. + */ + function load() { + + var scripts = [], + scriptsToLoad = 0; + + config.dependencies.forEach( function( s ) { + // Load if there's no condition or the condition is truthy + if( !s.condition || s.condition() ) { + if( s.async ) { + asyncDependencies.push( s ); + } + else { + scripts.push( s ); + } + } + } ); + + if( scripts.length ) { + scriptsToLoad = scripts.length; + + // Load synchronous scripts + scripts.forEach( function( s ) { + loadScript( s.src, function() { + + if( typeof s.callback === 'function' ) s.callback(); + + if( --scriptsToLoad === 0 ) { + initPlugins(); + } + + } ); + } ); + } + else { + initPlugins(); + } + + } + + /** + * Initializes our plugins and waits for them to be ready + * before proceeding. + */ + function initPlugins() { + + var pluginsToInitialize = Object.keys( plugins ).length; + + // If there are no plugins, skip this step + if( pluginsToInitialize === 0 ) { + loadAsyncDependencies(); + } + // ... otherwise initialize plugins + else { + + var afterPlugInitialized = function() { + if( --pluginsToInitialize === 0 ) { + loadAsyncDependencies(); + } + }; + + for( var i in plugins ) { + + var plugin = plugins[i]; + + // If the plugin has an 'init' method, invoke it + if( typeof plugin.init === 'function' ) { + var callback = plugin.init(); + + // If the plugin returned a Promise, wait for it + if( callback && typeof callback.then === 'function' ) { + callback.then( afterPlugInitialized ); + } + else { + afterPlugInitialized(); + } + } + else { + afterPlugInitialized(); + } + + } + + } + + } + + /** + * Loads all async reveal.js dependencies. + */ + function loadAsyncDependencies() { + + if( asyncDependencies.length ) { + asyncDependencies.forEach( function( s ) { + loadScript( s.src, s.callback ); + } ); + } + + start(); + + } + + /** + * Loads a JavaScript file from the given URL and executes it. + * + * @param {string} url Address of the .js file to load + * @param {function} callback Method to invoke when the script + * has loaded and executed + */ + function loadScript( url, callback ) { + + var script = document.createElement( 'script' ); + script.type = 'text/javascript'; + script.async = false; + script.defer = false; + script.src = url; + + if( callback ) { + + // Success callback + script.onload = script.onreadystatechange = function( event ) { + if( event.type === "load" || (/loaded|complete/.test( script.readyState ) ) ) { + + // Kill event listeners + script.onload = script.onreadystatechange = script.onerror = null; + + callback(); + + } + }; + + // Error callback + script.onerror = function( err ) { + + // Kill event listeners + script.onload = script.onreadystatechange = script.onerror = null; + + callback( new Error( 'Failed loading script: ' + script.src + '\n' + err) ); + + }; + + } + + // Append the script at the end of + var head = document.querySelector( 'head' ); + head.insertBefore( script, head.lastChild ); + + } + + /** + * Starts up reveal.js by binding input events and navigating + * to the current URL deeplink if there is one. + */ + function start() { + + loaded = true; + + // Make sure we've got all the DOM elements we need + setupDOM(); + + // Listen to messages posted to this window + setupPostMessage(); + + // Prevent the slides from being scrolled out of view + setupScrollPrevention(); + + // Resets all vertical slides so that only the first is visible + resetVerticalSlides(); + + // Updates the presentation to match the current configuration values + configure(); + + // Read the initial hash + readURL(); + + // Update all backgrounds + updateBackground( true ); + + // Notify listeners that the presentation is ready but use a 1ms + // timeout to ensure it's not fired synchronously after #initialize() + setTimeout( function() { + // Enable transitions now that we're loaded + dom.slides.classList.remove( 'no-transition' ); + + dom.wrapper.classList.add( 'ready' ); + + dispatchEvent( 'ready', { + 'indexh': indexh, + 'indexv': indexv, + 'currentSlide': currentSlide + } ); + }, 1 ); + + // Special setup and config is required when printing to PDF + if( isPrintingPDF() ) { + removeEventListeners(); + + // The document needs to have loaded for the PDF layout + // measurements to be accurate + if( document.readyState === 'complete' ) { + setupPDF(); + } + else { + window.addEventListener( 'load', setupPDF ); + } + } + + } + + /** + * Finds and stores references to DOM elements which are + * required by the presentation. If a required element is + * not found, it is created. + */ + function setupDOM() { + + // Prevent transitions while we're loading + dom.slides.classList.add( 'no-transition' ); + + if( isMobileDevice ) { + dom.wrapper.classList.add( 'no-hover' ); + } + else { + dom.wrapper.classList.remove( 'no-hover' ); + } + + if( /iphone/gi.test( UA ) ) { + dom.wrapper.classList.add( 'ua-iphone' ); + } + else { + dom.wrapper.classList.remove( 'ua-iphone' ); + } + + // Background element + dom.background = createSingletonNode( dom.wrapper, 'div', 'backgrounds', null ); + + // Progress bar + dom.progress = createSingletonNode( dom.wrapper, 'div', 'progress', '' ); + dom.progressbar = dom.progress.querySelector( 'span' ); + + // Arrow controls + dom.controls = createSingletonNode( dom.wrapper, 'aside', 'controls', + '' + + '' + + '' + + '' ); + + // Slide number + dom.slideNumber = createSingletonNode( dom.wrapper, 'div', 'slide-number', '' ); + + // Element containing notes that are visible to the audience + dom.speakerNotes = createSingletonNode( dom.wrapper, 'div', 'speaker-notes', null ); + dom.speakerNotes.setAttribute( 'data-prevent-swipe', '' ); + dom.speakerNotes.setAttribute( 'tabindex', '0' ); + + // Overlay graphic which is displayed during the paused mode + dom.pauseOverlay = createSingletonNode( dom.wrapper, 'div', 'pause-overlay', config.controls ? '' : null ); + + dom.wrapper.setAttribute( 'role', 'application' ); + + // There can be multiple instances of controls throughout the page + dom.controlsLeft = toArray( document.querySelectorAll( '.navigate-left' ) ); + dom.controlsRight = toArray( document.querySelectorAll( '.navigate-right' ) ); + dom.controlsUp = toArray( document.querySelectorAll( '.navigate-up' ) ); + dom.controlsDown = toArray( document.querySelectorAll( '.navigate-down' ) ); + dom.controlsPrev = toArray( document.querySelectorAll( '.navigate-prev' ) ); + dom.controlsNext = toArray( document.querySelectorAll( '.navigate-next' ) ); + + // The right and down arrows in the standard reveal.js controls + dom.controlsRightArrow = dom.controls.querySelector( '.navigate-right' ); + dom.controlsDownArrow = dom.controls.querySelector( '.navigate-down' ); + + dom.statusDiv = createStatusDiv(); + } + + /** + * Creates a hidden div with role aria-live to announce the + * current slide content. Hide the div off-screen to make it + * available only to Assistive Technologies. + * + * @return {HTMLElement} + */ + function createStatusDiv() { + + var statusDiv = document.getElementById( 'aria-status-div' ); + if( !statusDiv ) { + statusDiv = document.createElement( 'div' ); + statusDiv.style.position = 'absolute'; + statusDiv.style.height = '1px'; + statusDiv.style.width = '1px'; + statusDiv.style.overflow = 'hidden'; + statusDiv.style.clip = 'rect( 1px, 1px, 1px, 1px )'; + statusDiv.setAttribute( 'id', 'aria-status-div' ); + statusDiv.setAttribute( 'aria-live', 'polite' ); + statusDiv.setAttribute( 'aria-atomic','true' ); + dom.wrapper.appendChild( statusDiv ); + } + return statusDiv; + + } + + /** + * Converts the given HTML element into a string of text + * that can be announced to a screen reader. Hidden + * elements are excluded. + */ + function getStatusText( node ) { + + var text = ''; + + // Text node + if( node.nodeType === 3 ) { + text += node.textContent; + } + // Element node + else if( node.nodeType === 1 ) { + + var isAriaHidden = node.getAttribute( 'aria-hidden' ); + var isDisplayHidden = window.getComputedStyle( node )['display'] === 'none'; + if( isAriaHidden !== 'true' && !isDisplayHidden ) { + + toArray( node.childNodes ).forEach( function( child ) { + text += getStatusText( child ); + } ); + + } + + } + + return text; + + } + + /** + * Configures the presentation for printing to a static + * PDF. + */ + function setupPDF() { + + var slideSize = getComputedSlideSize( window.innerWidth, window.innerHeight ); + + // Dimensions of the PDF pages + var pageWidth = Math.floor( slideSize.width * ( 1 + config.margin ) ), + pageHeight = Math.floor( slideSize.height * ( 1 + config.margin ) ); + + // Dimensions of slides within the pages + var slideWidth = slideSize.width, + slideHeight = slideSize.height; + + // Let the browser know what page size we want to print + injectStyleSheet( '@page{size:'+ pageWidth +'px '+ pageHeight +'px; margin: 0px;}' ); + + // Limit the size of certain elements to the dimensions of the slide + injectStyleSheet( '.reveal section>img, .reveal section>video, .reveal section>iframe{max-width: '+ slideWidth +'px; max-height:'+ slideHeight +'px}' ); + + document.body.classList.add( 'print-pdf' ); + document.body.style.width = pageWidth + 'px'; + document.body.style.height = pageHeight + 'px'; + + // Make sure stretch elements fit on slide + layoutSlideContents( slideWidth, slideHeight ); + + // Compute slide numbers now, before we start duplicating slides + var doingSlideNumbers = config.slideNumber && /all|print/i.test( config.showSlideNumber ); + toArray( dom.wrapper.querySelectorAll( SLIDES_SELECTOR ) ).forEach( function( slide ) { + slide.setAttribute( 'data-slide-number', getSlideNumber( slide ) ); + } ); + + // Slide and slide background layout + toArray( dom.wrapper.querySelectorAll( SLIDES_SELECTOR ) ).forEach( function( slide ) { + + // Vertical stacks are not centred since their section + // children will be + if( slide.classList.contains( 'stack' ) === false ) { + // Center the slide inside of the page, giving the slide some margin + var left = ( pageWidth - slideWidth ) / 2, + top = ( pageHeight - slideHeight ) / 2; + + var contentHeight = slide.scrollHeight; + var numberOfPages = Math.max( Math.ceil( contentHeight / pageHeight ), 1 ); + + // Adhere to configured pages per slide limit + numberOfPages = Math.min( numberOfPages, config.pdfMaxPagesPerSlide ); + + // Center slides vertically + if( numberOfPages === 1 && config.center || slide.classList.contains( 'center' ) ) { + top = Math.max( ( pageHeight - contentHeight ) / 2, 0 ); + } + + // Wrap the slide in a page element and hide its overflow + // so that no page ever flows onto another + var page = document.createElement( 'div' ); + page.className = 'pdf-page'; + page.style.height = ( ( pageHeight + config.pdfPageHeightOffset ) * numberOfPages ) + 'px'; + slide.parentNode.insertBefore( page, slide ); + page.appendChild( slide ); + + // Position the slide inside of the page + slide.style.left = left + 'px'; + slide.style.top = top + 'px'; + slide.style.width = slideWidth + 'px'; + + if( slide.slideBackgroundElement ) { + page.insertBefore( slide.slideBackgroundElement, slide ); + } + + // Inject notes if `showNotes` is enabled + if( config.showNotes ) { + + // Are there notes for this slide? + var notes = getSlideNotes( slide ); + if( notes ) { + + var notesSpacing = 8; + var notesLayout = typeof config.showNotes === 'string' ? config.showNotes : 'inline'; + var notesElement = document.createElement( 'div' ); + notesElement.classList.add( 'speaker-notes' ); + notesElement.classList.add( 'speaker-notes-pdf' ); + notesElement.setAttribute( 'data-layout', notesLayout ); + notesElement.innerHTML = notes; + + if( notesLayout === 'separate-page' ) { + page.parentNode.insertBefore( notesElement, page.nextSibling ); + } + else { + notesElement.style.left = notesSpacing + 'px'; + notesElement.style.bottom = notesSpacing + 'px'; + notesElement.style.width = ( pageWidth - notesSpacing*2 ) + 'px'; + page.appendChild( notesElement ); + } + + } + + } + + // Inject slide numbers if `slideNumbers` are enabled + if( doingSlideNumbers ) { + var numberElement = document.createElement( 'div' ); + numberElement.classList.add( 'slide-number' ); + numberElement.classList.add( 'slide-number-pdf' ); + numberElement.innerHTML = slide.getAttribute( 'data-slide-number' ); + page.appendChild( numberElement ); + } + + // Copy page and show fragments one after another + if( config.pdfSeparateFragments ) { + + // Each fragment 'group' is an array containing one or more + // fragments. Multiple fragments that appear at the same time + // are part of the same group. + var fragmentGroups = sortFragments( page.querySelectorAll( '.fragment' ), true ); + + var previousFragmentStep; + var previousPage; + + fragmentGroups.forEach( function( fragments ) { + + // Remove 'current-fragment' from the previous group + if( previousFragmentStep ) { + previousFragmentStep.forEach( function( fragment ) { + fragment.classList.remove( 'current-fragment' ); + } ); + } + + // Show the fragments for the current index + fragments.forEach( function( fragment ) { + fragment.classList.add( 'visible', 'current-fragment' ); + } ); + + // Create a separate page for the current fragment state + var clonedPage = page.cloneNode( true ); + page.parentNode.insertBefore( clonedPage, ( previousPage || page ).nextSibling ); + + previousFragmentStep = fragments; + previousPage = clonedPage; + + } ); + + // Reset the first/original page so that all fragments are hidden + fragmentGroups.forEach( function( fragments ) { + fragments.forEach( function( fragment ) { + fragment.classList.remove( 'visible', 'current-fragment' ); + } ); + } ); + + } + // Show all fragments + else { + toArray( page.querySelectorAll( '.fragment:not(.fade-out)' ) ).forEach( function( fragment ) { + fragment.classList.add( 'visible' ); + } ); + } + + } + + } ); + + // Notify subscribers that the PDF layout is good to go + dispatchEvent( 'pdf-ready' ); + + } + + /** + * This is an unfortunate necessity. Some actions – such as + * an input field being focused in an iframe or using the + * keyboard to expand text selection beyond the bounds of + * a slide – can trigger our content to be pushed out of view. + * This scrolling can not be prevented by hiding overflow in + * CSS (we already do) so we have to resort to repeatedly + * checking if the slides have been offset :( + */ + function setupScrollPrevention() { + + setInterval( function() { + if( dom.wrapper.scrollTop !== 0 || dom.wrapper.scrollLeft !== 0 ) { + dom.wrapper.scrollTop = 0; + dom.wrapper.scrollLeft = 0; + } + }, 1000 ); + + } + + /** + * Creates an HTML element and returns a reference to it. + * If the element already exists the existing instance will + * be returned. + * + * @param {HTMLElement} container + * @param {string} tagname + * @param {string} classname + * @param {string} innerHTML + * + * @return {HTMLElement} + */ + function createSingletonNode( container, tagname, classname, innerHTML ) { + + // Find all nodes matching the description + var nodes = container.querySelectorAll( '.' + classname ); + + // Check all matches to find one which is a direct child of + // the specified container + for( var i = 0; i < nodes.length; i++ ) { + var testNode = nodes[i]; + if( testNode.parentNode === container ) { + return testNode; + } + } + + // If no node was found, create it now + var node = document.createElement( tagname ); + node.className = classname; + if( typeof innerHTML === 'string' ) { + node.innerHTML = innerHTML; + } + container.appendChild( node ); + + return node; + + } + + /** + * Creates the slide background elements and appends them + * to the background container. One element is created per + * slide no matter if the given slide has visible background. + */ + function createBackgrounds() { + + var printMode = isPrintingPDF(); + + // Clear prior backgrounds + dom.background.innerHTML = ''; + dom.background.classList.add( 'no-transition' ); + + // Iterate over all horizontal slides + toArray( dom.wrapper.querySelectorAll( HORIZONTAL_SLIDES_SELECTOR ) ).forEach( function( slideh ) { + + var backgroundStack = createBackground( slideh, dom.background ); + + // Iterate over all vertical slides + toArray( slideh.querySelectorAll( 'section' ) ).forEach( function( slidev ) { + + createBackground( slidev, backgroundStack ); + + backgroundStack.classList.add( 'stack' ); + + } ); + + } ); + + // Add parallax background if specified + if( config.parallaxBackgroundImage ) { + + dom.background.style.backgroundImage = 'url("' + config.parallaxBackgroundImage + '")'; + dom.background.style.backgroundSize = config.parallaxBackgroundSize; + dom.background.style.backgroundRepeat = config.parallaxBackgroundRepeat; + dom.background.style.backgroundPosition = config.parallaxBackgroundPosition; + + // Make sure the below properties are set on the element - these properties are + // needed for proper transitions to be set on the element via CSS. To remove + // annoying background slide-in effect when the presentation starts, apply + // these properties after short time delay + setTimeout( function() { + dom.wrapper.classList.add( 'has-parallax-background' ); + }, 1 ); + + } + else { + + dom.background.style.backgroundImage = ''; + dom.wrapper.classList.remove( 'has-parallax-background' ); + + } + + } + + /** + * Creates a background for the given slide. + * + * @param {HTMLElement} slide + * @param {HTMLElement} container The element that the background + * should be appended to + * @return {HTMLElement} New background div + */ + function createBackground( slide, container ) { + + + // Main slide background element + var element = document.createElement( 'div' ); + element.className = 'slide-background ' + slide.className.replace( /present|past|future/, '' ); + + // Inner background element that wraps images/videos/iframes + var contentElement = document.createElement( 'div' ); + contentElement.className = 'slide-background-content'; + + element.appendChild( contentElement ); + container.appendChild( element ); + + slide.slideBackgroundElement = element; + slide.slideBackgroundContentElement = contentElement; + + // Syncs the background to reflect all current background settings + syncBackground( slide ); + + return element; + + } + + /** + * Renders all of the visual properties of a slide background + * based on the various background attributes. + * + * @param {HTMLElement} slide + */ + function syncBackground( slide ) { + + var element = slide.slideBackgroundElement, + contentElement = slide.slideBackgroundContentElement; + + // Reset the prior background state in case this is not the + // initial sync + slide.classList.remove( 'has-dark-background' ); + slide.classList.remove( 'has-light-background' ); + + element.removeAttribute( 'data-loaded' ); + element.removeAttribute( 'data-background-hash' ); + element.removeAttribute( 'data-background-size' ); + element.removeAttribute( 'data-background-transition' ); + element.style.backgroundColor = ''; + + contentElement.style.backgroundSize = ''; + contentElement.style.backgroundRepeat = ''; + contentElement.style.backgroundPosition = ''; + contentElement.style.backgroundImage = ''; + contentElement.style.opacity = ''; + contentElement.innerHTML = ''; + + var data = { + background: slide.getAttribute( 'data-background' ), + backgroundSize: slide.getAttribute( 'data-background-size' ), + backgroundImage: slide.getAttribute( 'data-background-image' ), + backgroundVideo: slide.getAttribute( 'data-background-video' ), + backgroundIframe: slide.getAttribute( 'data-background-iframe' ), + backgroundColor: slide.getAttribute( 'data-background-color' ), + backgroundRepeat: slide.getAttribute( 'data-background-repeat' ), + backgroundPosition: slide.getAttribute( 'data-background-position' ), + backgroundTransition: slide.getAttribute( 'data-background-transition' ), + backgroundOpacity: slide.getAttribute( 'data-background-opacity' ) + }; + + if( data.background ) { + // Auto-wrap image urls in url(...) + if( /^(http|file|\/\/)/gi.test( data.background ) || /\.(svg|png|jpg|jpeg|gif|bmp)([?#\s]|$)/gi.test( data.background ) ) { + slide.setAttribute( 'data-background-image', data.background ); + } + else { + element.style.background = data.background; + } + } + + // Create a hash for this combination of background settings. + // This is used to determine when two slide backgrounds are + // the same. + if( data.background || data.backgroundColor || data.backgroundImage || data.backgroundVideo || data.backgroundIframe ) { + element.setAttribute( 'data-background-hash', data.background + + data.backgroundSize + + data.backgroundImage + + data.backgroundVideo + + data.backgroundIframe + + data.backgroundColor + + data.backgroundRepeat + + data.backgroundPosition + + data.backgroundTransition + + data.backgroundOpacity ); + } + + // Additional and optional background properties + if( data.backgroundSize ) element.setAttribute( 'data-background-size', data.backgroundSize ); + if( data.backgroundColor ) element.style.backgroundColor = data.backgroundColor; + if( data.backgroundTransition ) element.setAttribute( 'data-background-transition', data.backgroundTransition ); + + if( slide.hasAttribute( 'data-preload' ) ) element.setAttribute( 'data-preload', '' ); + + // Background image options are set on the content wrapper + if( data.backgroundSize ) contentElement.style.backgroundSize = data.backgroundSize; + if( data.backgroundRepeat ) contentElement.style.backgroundRepeat = data.backgroundRepeat; + if( data.backgroundPosition ) contentElement.style.backgroundPosition = data.backgroundPosition; + if( data.backgroundOpacity ) contentElement.style.opacity = data.backgroundOpacity; + + // If this slide has a background color, we add a class that + // signals if it is light or dark. If the slide has no background + // color, no class will be added + var contrastColor = data.backgroundColor; + + // If no bg color was found, check the computed background + if( !contrastColor ) { + var computedBackgroundStyle = window.getComputedStyle( element ); + if( computedBackgroundStyle && computedBackgroundStyle.backgroundColor ) { + contrastColor = computedBackgroundStyle.backgroundColor; + } + } + + if( contrastColor ) { + var rgb = colorToRgb( contrastColor ); + + // Ignore fully transparent backgrounds. Some browsers return + // rgba(0,0,0,0) when reading the computed background color of + // an element with no background + if( rgb && rgb.a !== 0 ) { + if( colorBrightness( contrastColor ) < 128 ) { + slide.classList.add( 'has-dark-background' ); + } + else { + slide.classList.add( 'has-light-background' ); + } + } + } + + } + + /** + * Registers a listener to postMessage events, this makes it + * possible to call all reveal.js API methods from another + * window. For example: + * + * revealWindow.postMessage( JSON.stringify({ + * method: 'slide', + * args: [ 2 ] + * }), '*' ); + */ + function setupPostMessage() { + + if( config.postMessage ) { + window.addEventListener( 'message', function ( event ) { + var data = event.data; + + // Make sure we're dealing with JSON + if( typeof data === 'string' && data.charAt( 0 ) === '{' && data.charAt( data.length - 1 ) === '}' ) { + data = JSON.parse( data ); + + // Check if the requested method can be found + if( data.method && typeof Reveal[data.method] === 'function' ) { + + if( POST_MESSAGE_METHOD_BLACKLIST.test( data.method ) === false ) { + + var result = Reveal[data.method].apply( Reveal, data.args ); + + // Dispatch a postMessage event with the returned value from + // our method invocation for getter functions + dispatchPostMessage( 'callback', { method: data.method, result: result } ); + + } + else { + console.warn( 'reveal.js: "'+ data.method +'" is is blacklisted from the postMessage API' ); + } + + } + } + }, false ); + } + + } + + /** + * Applies the configuration settings from the config + * object. May be called multiple times. + * + * @param {object} options + */ + function configure( options ) { + + var oldTransition = config.transition; + + // New config options may be passed when this method + // is invoked through the API after initialization + if( typeof options === 'object' ) extend( config, options ); + + // Abort if reveal.js hasn't finished loading, config + // changes will be applied automatically once loading + // finishes + if( loaded === false ) return; + + var numberOfSlides = dom.wrapper.querySelectorAll( SLIDES_SELECTOR ).length; + + // Remove the previously configured transition class + dom.wrapper.classList.remove( oldTransition ); + + // Force linear transition based on browser capabilities + if( features.transforms3d === false ) config.transition = 'linear'; + + dom.wrapper.classList.add( config.transition ); + + dom.wrapper.setAttribute( 'data-transition-speed', config.transitionSpeed ); + dom.wrapper.setAttribute( 'data-background-transition', config.backgroundTransition ); + + dom.controls.style.display = config.controls ? 'block' : 'none'; + dom.progress.style.display = config.progress ? 'block' : 'none'; + + dom.controls.setAttribute( 'data-controls-layout', config.controlsLayout ); + dom.controls.setAttribute( 'data-controls-back-arrows', config.controlsBackArrows ); + + if( config.shuffle ) { + shuffle(); + } + + if( config.rtl ) { + dom.wrapper.classList.add( 'rtl' ); + } + else { + dom.wrapper.classList.remove( 'rtl' ); + } + + if( config.center ) { + dom.wrapper.classList.add( 'center' ); + } + else { + dom.wrapper.classList.remove( 'center' ); + } + + // Exit the paused mode if it was configured off + if( config.pause === false ) { + resume(); + } + + if( config.showNotes ) { + dom.speakerNotes.setAttribute( 'data-layout', typeof config.showNotes === 'string' ? config.showNotes : 'inline' ); + } + + if( config.mouseWheel ) { + document.addEventListener( 'DOMMouseScroll', onDocumentMouseScroll, false ); // FF + document.addEventListener( 'mousewheel', onDocumentMouseScroll, false ); + } + else { + document.removeEventListener( 'DOMMouseScroll', onDocumentMouseScroll, false ); // FF + document.removeEventListener( 'mousewheel', onDocumentMouseScroll, false ); + } + + // Rolling 3D links + if( config.rollingLinks ) { + enableRollingLinks(); + } + else { + disableRollingLinks(); + } + + // Auto-hide the mouse pointer when its inactive + if( config.hideInactiveCursor ) { + document.addEventListener( 'mousemove', onDocumentCursorActive, false ); + document.addEventListener( 'mousedown', onDocumentCursorActive, false ); + } + else { + showCursor(); + + document.removeEventListener( 'mousemove', onDocumentCursorActive, false ); + document.removeEventListener( 'mousedown', onDocumentCursorActive, false ); + } + + // Iframe link previews + if( config.previewLinks ) { + enablePreviewLinks(); + disablePreviewLinks( '[data-preview-link=false]' ); + } + else { + disablePreviewLinks(); + enablePreviewLinks( '[data-preview-link]:not([data-preview-link=false])' ); + } + + // Remove existing auto-slide controls + if( autoSlidePlayer ) { + autoSlidePlayer.destroy(); + autoSlidePlayer = null; + } + + // Generate auto-slide controls if needed + if( numberOfSlides > 1 && config.autoSlide && config.autoSlideStoppable && features.canvas && features.requestAnimationFrame ) { + autoSlidePlayer = new Playback( dom.wrapper, function() { + return Math.min( Math.max( ( Date.now() - autoSlideStartTime ) / autoSlide, 0 ), 1 ); + } ); + + autoSlidePlayer.on( 'click', onAutoSlidePlayerClick ); + autoSlidePaused = false; + } + + // When fragments are turned off they should be visible + if( config.fragments === false ) { + toArray( dom.slides.querySelectorAll( '.fragment' ) ).forEach( function( element ) { + element.classList.add( 'visible' ); + element.classList.remove( 'current-fragment' ); + } ); + } + + // Slide numbers + var slideNumberDisplay = 'none'; + if( config.slideNumber && !isPrintingPDF() ) { + if( config.showSlideNumber === 'all' ) { + slideNumberDisplay = 'block'; + } + else if( config.showSlideNumber === 'speaker' && isSpeakerNotes() ) { + slideNumberDisplay = 'block'; + } + } + + dom.slideNumber.style.display = slideNumberDisplay; + + // Add the navigation mode to the DOM so we can adjust styling + if( config.navigationMode !== 'default' ) { + dom.wrapper.setAttribute( 'data-navigation-mode', config.navigationMode ); + } + else { + dom.wrapper.removeAttribute( 'data-navigation-mode' ); + } + + // Define our contextual list of keyboard shortcuts + if( config.navigationMode === 'linear' ) { + keyboardShortcuts['→ , ↓ , SPACE , N , L , J'] = 'Next slide'; + keyboardShortcuts['← , ↑ , P , H , K'] = 'Previous slide'; + } + else { + keyboardShortcuts['N , SPACE'] = 'Next slide'; + keyboardShortcuts['P'] = 'Previous slide'; + keyboardShortcuts['← , H'] = 'Navigate left'; + keyboardShortcuts['→ , L'] = 'Navigate right'; + keyboardShortcuts['↑ , K'] = 'Navigate up'; + keyboardShortcuts['↓ , J'] = 'Navigate down'; + } + + keyboardShortcuts['Home , Shift ←'] = 'First slide'; + keyboardShortcuts['End , Shift →'] = 'Last slide'; + keyboardShortcuts['B , .'] = 'Pause'; + keyboardShortcuts['F'] = 'Fullscreen'; + keyboardShortcuts['ESC, O'] = 'Slide overview'; + + sync(); + + } + + /** + * Binds all event listeners. + */ + function addEventListeners() { + + eventsAreBound = true; + + window.addEventListener( 'hashchange', onWindowHashChange, false ); + window.addEventListener( 'resize', onWindowResize, false ); + + if( config.touch ) { + if( 'onpointerdown' in window ) { + // Use W3C pointer events + dom.wrapper.addEventListener( 'pointerdown', onPointerDown, false ); + dom.wrapper.addEventListener( 'pointermove', onPointerMove, false ); + dom.wrapper.addEventListener( 'pointerup', onPointerUp, false ); + } + else if( window.navigator.msPointerEnabled ) { + // IE 10 uses prefixed version of pointer events + dom.wrapper.addEventListener( 'MSPointerDown', onPointerDown, false ); + dom.wrapper.addEventListener( 'MSPointerMove', onPointerMove, false ); + dom.wrapper.addEventListener( 'MSPointerUp', onPointerUp, false ); + } + else { + // Fall back to touch events + dom.wrapper.addEventListener( 'touchstart', onTouchStart, false ); + dom.wrapper.addEventListener( 'touchmove', onTouchMove, false ); + dom.wrapper.addEventListener( 'touchend', onTouchEnd, false ); + } + } + + if( config.keyboard ) { + document.addEventListener( 'keydown', onDocumentKeyDown, false ); + document.addEventListener( 'keypress', onDocumentKeyPress, false ); + } + + if( config.progress && dom.progress ) { + dom.progress.addEventListener( 'click', onProgressClicked, false ); + } + + dom.pauseOverlay.addEventListener( 'click', resume, false ); + + if( config.focusBodyOnPageVisibilityChange ) { + var visibilityChange; + + if( 'hidden' in document ) { + visibilityChange = 'visibilitychange'; + } + else if( 'msHidden' in document ) { + visibilityChange = 'msvisibilitychange'; + } + else if( 'webkitHidden' in document ) { + visibilityChange = 'webkitvisibilitychange'; + } + + if( visibilityChange ) { + document.addEventListener( visibilityChange, onPageVisibilityChange, false ); + } + } + + // Listen to both touch and click events, in case the device + // supports both + var pointerEvents = [ 'touchstart', 'click' ]; + + // Only support touch for Android, fixes double navigations in + // stock browser + if( UA.match( /android/gi ) ) { + pointerEvents = [ 'touchstart' ]; + } + + pointerEvents.forEach( function( eventName ) { + dom.controlsLeft.forEach( function( el ) { el.addEventListener( eventName, onNavigateLeftClicked, false ); } ); + dom.controlsRight.forEach( function( el ) { el.addEventListener( eventName, onNavigateRightClicked, false ); } ); + dom.controlsUp.forEach( function( el ) { el.addEventListener( eventName, onNavigateUpClicked, false ); } ); + dom.controlsDown.forEach( function( el ) { el.addEventListener( eventName, onNavigateDownClicked, false ); } ); + dom.controlsPrev.forEach( function( el ) { el.addEventListener( eventName, onNavigatePrevClicked, false ); } ); + dom.controlsNext.forEach( function( el ) { el.addEventListener( eventName, onNavigateNextClicked, false ); } ); + } ); + + } + + /** + * Unbinds all event listeners. + */ + function removeEventListeners() { + + eventsAreBound = false; + + document.removeEventListener( 'keydown', onDocumentKeyDown, false ); + document.removeEventListener( 'keypress', onDocumentKeyPress, false ); + window.removeEventListener( 'hashchange', onWindowHashChange, false ); + window.removeEventListener( 'resize', onWindowResize, false ); + + dom.wrapper.removeEventListener( 'pointerdown', onPointerDown, false ); + dom.wrapper.removeEventListener( 'pointermove', onPointerMove, false ); + dom.wrapper.removeEventListener( 'pointerup', onPointerUp, false ); + + dom.wrapper.removeEventListener( 'MSPointerDown', onPointerDown, false ); + dom.wrapper.removeEventListener( 'MSPointerMove', onPointerMove, false ); + dom.wrapper.removeEventListener( 'MSPointerUp', onPointerUp, false ); + + dom.wrapper.removeEventListener( 'touchstart', onTouchStart, false ); + dom.wrapper.removeEventListener( 'touchmove', onTouchMove, false ); + dom.wrapper.removeEventListener( 'touchend', onTouchEnd, false ); + + dom.pauseOverlay.removeEventListener( 'click', resume, false ); + + if ( config.progress && dom.progress ) { + dom.progress.removeEventListener( 'click', onProgressClicked, false ); + } + + [ 'touchstart', 'click' ].forEach( function( eventName ) { + dom.controlsLeft.forEach( function( el ) { el.removeEventListener( eventName, onNavigateLeftClicked, false ); } ); + dom.controlsRight.forEach( function( el ) { el.removeEventListener( eventName, onNavigateRightClicked, false ); } ); + dom.controlsUp.forEach( function( el ) { el.removeEventListener( eventName, onNavigateUpClicked, false ); } ); + dom.controlsDown.forEach( function( el ) { el.removeEventListener( eventName, onNavigateDownClicked, false ); } ); + dom.controlsPrev.forEach( function( el ) { el.removeEventListener( eventName, onNavigatePrevClicked, false ); } ); + dom.controlsNext.forEach( function( el ) { el.removeEventListener( eventName, onNavigateNextClicked, false ); } ); + } ); + + } + + /** + * Registers a new plugin with this reveal.js instance. + * + * reveal.js waits for all regisered plugins to initialize + * before considering itself ready, as long as the plugin + * is registered before calling `Reveal.initialize()`. + */ + function registerPlugin( id, plugin ) { + + if( plugins[id] === undefined ) { + plugins[id] = plugin; + + // If a plugin is registered after reveal.js is loaded, + // initialize it right away + if( loaded && typeof plugin.init === 'function' ) { + plugin.init(); + } + } + else { + console.warn( 'reveal.js: "'+ id +'" plugin has already been registered' ); + } + + } + + /** + * Checks if a specific plugin has been registered. + * + * @param {String} id Unique plugin identifier + */ + function hasPlugin( id ) { + + return !!plugins[id]; + + } + + /** + * Returns the specific plugin instance, if a plugin + * with the given ID has been registered. + * + * @param {String} id Unique plugin identifier + */ + function getPlugin( id ) { + + return plugins[id]; + + } + + /** + * Add a custom key binding with optional description to + * be added to the help screen. + */ + function addKeyBinding( binding, callback ) { + + if( typeof binding === 'object' && binding.keyCode ) { + registeredKeyBindings[binding.keyCode] = { + callback: callback, + key: binding.key, + description: binding.description + }; + } + else { + registeredKeyBindings[binding] = { + callback: callback, + key: null, + description: null + }; + } + + } + + /** + * Removes the specified custom key binding. + */ + function removeKeyBinding( keyCode ) { + + delete registeredKeyBindings[keyCode]; + + } + + /** + * Extend object a with the properties of object b. + * If there's a conflict, object b takes precedence. + * + * @param {object} a + * @param {object} b + */ + function extend( a, b ) { + + for( var i in b ) { + a[ i ] = b[ i ]; + } + + return a; + + } + + /** + * Converts the target object to an array. + * + * @param {object} o + * @return {object[]} + */ + function toArray( o ) { + + return Array.prototype.slice.call( o ); + + } + + /** + * Utility for deserializing a value. + * + * @param {*} value + * @return {*} + */ + function deserialize( value ) { + + if( typeof value === 'string' ) { + if( value === 'null' ) return null; + else if( value === 'true' ) return true; + else if( value === 'false' ) return false; + else if( value.match( /^-?[\d\.]+$/ ) ) return parseFloat( value ); + } + + return value; + + } + + /** + * Measures the distance in pixels between point a + * and point b. + * + * @param {object} a point with x/y properties + * @param {object} b point with x/y properties + * + * @return {number} + */ + function distanceBetween( a, b ) { + + var dx = a.x - b.x, + dy = a.y - b.y; + + return Math.sqrt( dx*dx + dy*dy ); + + } + + /** + * Applies a CSS transform to the target element. + * + * @param {HTMLElement} element + * @param {string} transform + */ + function transformElement( element, transform ) { + + element.style.WebkitTransform = transform; + element.style.MozTransform = transform; + element.style.msTransform = transform; + element.style.transform = transform; + + } + + /** + * Applies CSS transforms to the slides container. The container + * is transformed from two separate sources: layout and the overview + * mode. + * + * @param {object} transforms + */ + function transformSlides( transforms ) { + + // Pick up new transforms from arguments + if( typeof transforms.layout === 'string' ) slidesTransform.layout = transforms.layout; + if( typeof transforms.overview === 'string' ) slidesTransform.overview = transforms.overview; + + // Apply the transforms to the slides container + if( slidesTransform.layout ) { + transformElement( dom.slides, slidesTransform.layout + ' ' + slidesTransform.overview ); + } + else { + transformElement( dom.slides, slidesTransform.overview ); + } + + } + + /** + * Injects the given CSS styles into the DOM. + * + * @param {string} value + */ + function injectStyleSheet( value ) { + + var tag = document.createElement( 'style' ); + tag.type = 'text/css'; + if( tag.styleSheet ) { + tag.styleSheet.cssText = value; + } + else { + tag.appendChild( document.createTextNode( value ) ); + } + document.getElementsByTagName( 'head' )[0].appendChild( tag ); + + } + + /** + * Find the closest parent that matches the given + * selector. + * + * @param {HTMLElement} target The child element + * @param {String} selector The CSS selector to match + * the parents against + * + * @return {HTMLElement} The matched parent or null + * if no matching parent was found + */ + function closestParent( target, selector ) { + + var parent = target.parentNode; + + while( parent ) { + + // There's some overhead doing this each time, we don't + // want to rewrite the element prototype but should still + // be enough to feature detect once at startup... + var matchesMethod = parent.matches || parent.matchesSelector || parent.msMatchesSelector; + + // If we find a match, we're all set + if( matchesMethod && matchesMethod.call( parent, selector ) ) { + return parent; + } + + // Keep searching + parent = parent.parentNode; + + } + + return null; + + } + + /** + * Converts various color input formats to an {r:0,g:0,b:0} object. + * + * @param {string} color The string representation of a color + * @example + * colorToRgb('#000'); + * @example + * colorToRgb('#000000'); + * @example + * colorToRgb('rgb(0,0,0)'); + * @example + * colorToRgb('rgba(0,0,0)'); + * + * @return {{r: number, g: number, b: number, [a]: number}|null} + */ + function colorToRgb( color ) { + + var hex3 = color.match( /^#([0-9a-f]{3})$/i ); + if( hex3 && hex3[1] ) { + hex3 = hex3[1]; + return { + r: parseInt( hex3.charAt( 0 ), 16 ) * 0x11, + g: parseInt( hex3.charAt( 1 ), 16 ) * 0x11, + b: parseInt( hex3.charAt( 2 ), 16 ) * 0x11 + }; + } + + var hex6 = color.match( /^#([0-9a-f]{6})$/i ); + if( hex6 && hex6[1] ) { + hex6 = hex6[1]; + return { + r: parseInt( hex6.substr( 0, 2 ), 16 ), + g: parseInt( hex6.substr( 2, 2 ), 16 ), + b: parseInt( hex6.substr( 4, 2 ), 16 ) + }; + } + + var rgb = color.match( /^rgb\s*\(\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*\)$/i ); + if( rgb ) { + return { + r: parseInt( rgb[1], 10 ), + g: parseInt( rgb[2], 10 ), + b: parseInt( rgb[3], 10 ) + }; + } + + var rgba = color.match( /^rgba\s*\(\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*\,\s*([\d]+|[\d]*.[\d]+)\s*\)$/i ); + if( rgba ) { + return { + r: parseInt( rgba[1], 10 ), + g: parseInt( rgba[2], 10 ), + b: parseInt( rgba[3], 10 ), + a: parseFloat( rgba[4] ) + }; + } + + return null; + + } + + /** + * Calculates brightness on a scale of 0-255. + * + * @param {string} color See colorToRgb for supported formats. + * @see {@link colorToRgb} + */ + function colorBrightness( color ) { + + if( typeof color === 'string' ) color = colorToRgb( color ); + + if( color ) { + return ( color.r * 299 + color.g * 587 + color.b * 114 ) / 1000; + } + + return null; + + } + + /** + * Returns the remaining height within the parent of the + * target element. + * + * remaining height = [ configured parent height ] - [ current parent height ] + * + * @param {HTMLElement} element + * @param {number} [height] + */ + function getRemainingHeight( element, height ) { + + height = height || 0; + + if( element ) { + var newHeight, oldHeight = element.style.height; + + // Change the .stretch element height to 0 in order find the height of all + // the other elements + element.style.height = '0px'; + + // In Overview mode, the parent (.slide) height is set of 700px. + // Restore it temporarily to its natural height. + element.parentNode.style.height = 'auto'; + + newHeight = height - element.parentNode.offsetHeight; + + // Restore the old height, just in case + element.style.height = oldHeight + 'px'; + + // Clear the parent (.slide) height. .removeProperty works in IE9+ + element.parentNode.style.removeProperty('height'); + + return newHeight; + } + + return height; + + } + + /** + * Checks if this instance is being used to print a PDF. + */ + function isPrintingPDF() { + + return ( /print-pdf/gi ).test( window.location.search ); + + } + + /** + * Hides the address bar if we're on a mobile device. + */ + function hideAddressBar() { + + if( config.hideAddressBar && isMobileDevice ) { + // Events that should trigger the address bar to hide + window.addEventListener( 'load', removeAddressBar, false ); + window.addEventListener( 'orientationchange', removeAddressBar, false ); + } + + } + + /** + * Causes the address bar to hide on mobile devices, + * more vertical space ftw. + */ + function removeAddressBar() { + + setTimeout( function() { + window.scrollTo( 0, 1 ); + }, 10 ); + + } + + /** + * Dispatches an event of the specified type from the + * reveal DOM element. + */ + function dispatchEvent( type, args ) { + + var event = document.createEvent( 'HTMLEvents', 1, 2 ); + event.initEvent( type, true, true ); + extend( event, args ); + dom.wrapper.dispatchEvent( event ); + + // If we're in an iframe, post each reveal.js event to the + // parent window. Used by the notes plugin + dispatchPostMessage( type ); + + } + + /** + * Dispatched a postMessage of the given type from our window. + */ + function dispatchPostMessage( type, data ) { + + if( config.postMessageEvents && window.parent !== window.self ) { + var message = { + namespace: 'reveal', + eventName: type, + state: getState() + }; + + extend( message, data ); + + window.parent.postMessage( JSON.stringify( message ), '*' ); + } + + } + + /** + * Wrap all links in 3D goodness. + */ + function enableRollingLinks() { + + if( features.transforms3d && !( 'msPerspective' in document.body.style ) ) { + var anchors = dom.wrapper.querySelectorAll( SLIDES_SELECTOR + ' a' ); + + for( var i = 0, len = anchors.length; i < len; i++ ) { + var anchor = anchors[i]; + + if( anchor.textContent && !anchor.querySelector( '*' ) && ( !anchor.className || !anchor.classList.contains( anchor, 'roll' ) ) ) { + var span = document.createElement('span'); + span.setAttribute('data-title', anchor.text); + span.innerHTML = anchor.innerHTML; + + anchor.classList.add( 'roll' ); + anchor.innerHTML = ''; + anchor.appendChild(span); + } + } + } + + } + + /** + * Unwrap all 3D links. + */ + function disableRollingLinks() { + + var anchors = dom.wrapper.querySelectorAll( SLIDES_SELECTOR + ' a.roll' ); + + for( var i = 0, len = anchors.length; i < len; i++ ) { + var anchor = anchors[i]; + var span = anchor.querySelector( 'span' ); + + if( span ) { + anchor.classList.remove( 'roll' ); + anchor.innerHTML = span.innerHTML; + } + } + + } + + /** + * Bind preview frame links. + * + * @param {string} [selector=a] - selector for anchors + */ + function enablePreviewLinks( selector ) { + + var anchors = toArray( document.querySelectorAll( selector ? selector : 'a' ) ); + + anchors.forEach( function( element ) { + if( /^(http|www)/gi.test( element.getAttribute( 'href' ) ) ) { + element.addEventListener( 'click', onPreviewLinkClicked, false ); + } + } ); + + } + + /** + * Unbind preview frame links. + */ + function disablePreviewLinks( selector ) { + + var anchors = toArray( document.querySelectorAll( selector ? selector : 'a' ) ); + + anchors.forEach( function( element ) { + if( /^(http|www)/gi.test( element.getAttribute( 'href' ) ) ) { + element.removeEventListener( 'click', onPreviewLinkClicked, false ); + } + } ); + + } + + /** + * Opens a preview window for the target URL. + * + * @param {string} url - url for preview iframe src + */ + function showPreview( url ) { + + closeOverlay(); + + dom.overlay = document.createElement( 'div' ); + dom.overlay.classList.add( 'overlay' ); + dom.overlay.classList.add( 'overlay-preview' ); + dom.wrapper.appendChild( dom.overlay ); + + dom.overlay.innerHTML = [ + '
', + '', + '', + '
', + '
', + '
', + '', + '', + 'Unable to load iframe. This is likely due to the site\'s policy (x-frame-options).', + '', + '
' + ].join(''); + + dom.overlay.querySelector( 'iframe' ).addEventListener( 'load', function( event ) { + dom.overlay.classList.add( 'loaded' ); + }, false ); + + dom.overlay.querySelector( '.close' ).addEventListener( 'click', function( event ) { + closeOverlay(); + event.preventDefault(); + }, false ); + + dom.overlay.querySelector( '.external' ).addEventListener( 'click', function( event ) { + closeOverlay(); + }, false ); + + setTimeout( function() { + dom.overlay.classList.add( 'visible' ); + }, 1 ); + + } + + /** + * Open or close help overlay window. + * + * @param {Boolean} [override] Flag which overrides the + * toggle logic and forcibly sets the desired state. True means + * help is open, false means it's closed. + */ + function toggleHelp( override ){ + + if( typeof override === 'boolean' ) { + override ? showHelp() : closeOverlay(); + } + else { + if( dom.overlay ) { + closeOverlay(); + } + else { + showHelp(); + } + } + } + + /** + * Opens an overlay window with help material. + */ + function showHelp() { + + if( config.help ) { + + closeOverlay(); + + dom.overlay = document.createElement( 'div' ); + dom.overlay.classList.add( 'overlay' ); + dom.overlay.classList.add( 'overlay-help' ); + dom.wrapper.appendChild( dom.overlay ); + + var html = '

Keyboard Shortcuts


'; + + html += ''; + for( var key in keyboardShortcuts ) { + html += ''; + } + + // Add custom key bindings that have associated descriptions + for( var binding in registeredKeyBindings ) { + if( registeredKeyBindings[binding].key && registeredKeyBindings[binding].description ) { + html += ''; + } + } + + html += '
KEYACTION
' + key + '' + keyboardShortcuts[ key ] + '
' + registeredKeyBindings[binding].key + '' + registeredKeyBindings[binding].description + '
'; + + dom.overlay.innerHTML = [ + '
', + '', + '
', + '
', + '
'+ html +'
', + '
' + ].join(''); + + dom.overlay.querySelector( '.close' ).addEventListener( 'click', function( event ) { + closeOverlay(); + event.preventDefault(); + }, false ); + + setTimeout( function() { + dom.overlay.classList.add( 'visible' ); + }, 1 ); + + } + + } + + /** + * Closes any currently open overlay. + */ + function closeOverlay() { + + if( dom.overlay ) { + dom.overlay.parentNode.removeChild( dom.overlay ); + dom.overlay = null; + } + + } + + /** + * Applies JavaScript-controlled layout rules to the + * presentation. + */ + function layout() { + + if( dom.wrapper && !isPrintingPDF() ) { + + if( !config.disableLayout ) { + + // On some mobile devices '100vh' is taller than the visible + // viewport which leads to part of the presentation being + // cut off. To work around this we define our own '--vh' custom + // property where 100x adds up to the correct height. + // + // https://css-tricks.com/the-trick-to-viewport-units-on-mobile/ + if( isMobileDevice ) { + document.documentElement.style.setProperty( '--vh', ( window.innerHeight * 0.01 ) + 'px' ); + } + + var size = getComputedSlideSize(); + + var oldScale = scale; + + // Layout the contents of the slides + layoutSlideContents( config.width, config.height ); + + dom.slides.style.width = size.width + 'px'; + dom.slides.style.height = size.height + 'px'; + + // Determine scale of content to fit within available space + scale = Math.min( size.presentationWidth / size.width, size.presentationHeight / size.height ); + + // Respect max/min scale settings + scale = Math.max( scale, config.minScale ); + scale = Math.min( scale, config.maxScale ); + + // Don't apply any scaling styles if scale is 1 + if( scale === 1 ) { + dom.slides.style.zoom = ''; + dom.slides.style.left = ''; + dom.slides.style.top = ''; + dom.slides.style.bottom = ''; + dom.slides.style.right = ''; + transformSlides( { layout: '' } ); + } + else { + // Zoom Scaling + // Content remains crisp no matter how much we scale. Side + // effects are minor differences in text layout and iframe + // viewports changing size. A 200x200 iframe viewport in a + // 2x zoomed presentation ends up having a 400x400 viewport. + if( scale > 1 && features.zoom && window.devicePixelRatio < 2 ) { + dom.slides.style.zoom = scale; + dom.slides.style.left = ''; + dom.slides.style.top = ''; + dom.slides.style.bottom = ''; + dom.slides.style.right = ''; + transformSlides( { layout: '' } ); + } + // Transform Scaling + // Content layout remains the exact same when scaled up. + // Side effect is content becoming blurred, especially with + // high scale values on ldpi screens. + else { + dom.slides.style.zoom = ''; + dom.slides.style.left = '50%'; + dom.slides.style.top = '50%'; + dom.slides.style.bottom = 'auto'; + dom.slides.style.right = 'auto'; + transformSlides( { layout: 'translate(-50%, -50%) scale('+ scale +')' } ); + } + } + + // Select all slides, vertical and horizontal + var slides = toArray( dom.wrapper.querySelectorAll( SLIDES_SELECTOR ) ); + + for( var i = 0, len = slides.length; i < len; i++ ) { + var slide = slides[ i ]; + + // Don't bother updating invisible slides + if( slide.style.display === 'none' ) { + continue; + } + + if( config.center || slide.classList.contains( 'center' ) ) { + // Vertical stacks are not centred since their section + // children will be + if( slide.classList.contains( 'stack' ) ) { + slide.style.top = 0; + } + else { + slide.style.top = Math.max( ( size.height - slide.scrollHeight ) / 2, 0 ) + 'px'; + } + } + else { + slide.style.top = ''; + } + + } + + if( oldScale !== scale ) { + dispatchEvent( 'resize', { + 'oldScale': oldScale, + 'scale': scale, + 'size': size + } ); + } + } + + updateProgress(); + updateParallax(); + + if( isOverview() ) { + updateOverview(); + } + + } + + } + + /** + * Applies layout logic to the contents of all slides in + * the presentation. + * + * @param {string|number} width + * @param {string|number} height + */ + function layoutSlideContents( width, height ) { + + // Handle sizing of elements with the 'stretch' class + toArray( dom.slides.querySelectorAll( 'section > .stretch' ) ).forEach( function( element ) { + + // Determine how much vertical space we can use + var remainingHeight = getRemainingHeight( element, height ); + + // Consider the aspect ratio of media elements + if( /(img|video)/gi.test( element.nodeName ) ) { + var nw = element.naturalWidth || element.videoWidth, + nh = element.naturalHeight || element.videoHeight; + + var es = Math.min( width / nw, remainingHeight / nh ); + + element.style.width = ( nw * es ) + 'px'; + element.style.height = ( nh * es ) + 'px'; + + } + else { + element.style.width = width + 'px'; + element.style.height = remainingHeight + 'px'; + } + + } ); + + } + + /** + * Calculates the computed pixel size of our slides. These + * values are based on the width and height configuration + * options. + * + * @param {number} [presentationWidth=dom.wrapper.offsetWidth] + * @param {number} [presentationHeight=dom.wrapper.offsetHeight] + */ + function getComputedSlideSize( presentationWidth, presentationHeight ) { + + var size = { + // Slide size + width: config.width, + height: config.height, + + // Presentation size + presentationWidth: presentationWidth || dom.wrapper.offsetWidth, + presentationHeight: presentationHeight || dom.wrapper.offsetHeight + }; + + // Reduce available space by margin + size.presentationWidth -= ( size.presentationWidth * config.margin ); + size.presentationHeight -= ( size.presentationHeight * config.margin ); + + // Slide width may be a percentage of available width + if( typeof size.width === 'string' && /%$/.test( size.width ) ) { + size.width = parseInt( size.width, 10 ) / 100 * size.presentationWidth; + } + + // Slide height may be a percentage of available height + if( typeof size.height === 'string' && /%$/.test( size.height ) ) { + size.height = parseInt( size.height, 10 ) / 100 * size.presentationHeight; + } + + return size; + + } + + /** + * Stores the vertical index of a stack so that the same + * vertical slide can be selected when navigating to and + * from the stack. + * + * @param {HTMLElement} stack The vertical stack element + * @param {string|number} [v=0] Index to memorize + */ + function setPreviousVerticalIndex( stack, v ) { + + if( typeof stack === 'object' && typeof stack.setAttribute === 'function' ) { + stack.setAttribute( 'data-previous-indexv', v || 0 ); + } + + } + + /** + * Retrieves the vertical index which was stored using + * #setPreviousVerticalIndex() or 0 if no previous index + * exists. + * + * @param {HTMLElement} stack The vertical stack element + */ + function getPreviousVerticalIndex( stack ) { + + if( typeof stack === 'object' && typeof stack.setAttribute === 'function' && stack.classList.contains( 'stack' ) ) { + // Prefer manually defined start-indexv + var attributeName = stack.hasAttribute( 'data-start-indexv' ) ? 'data-start-indexv' : 'data-previous-indexv'; + + return parseInt( stack.getAttribute( attributeName ) || 0, 10 ); + } + + return 0; + + } + + /** + * Displays the overview of slides (quick nav) by scaling + * down and arranging all slide elements. + */ + function activateOverview() { + + // Only proceed if enabled in config + if( config.overview && !isOverview() ) { + + overview = true; + + dom.wrapper.classList.add( 'overview' ); + dom.wrapper.classList.remove( 'overview-deactivating' ); + + if( features.overviewTransitions ) { + setTimeout( function() { + dom.wrapper.classList.add( 'overview-animated' ); + }, 1 ); + } + + // Don't auto-slide while in overview mode + cancelAutoSlide(); + + // Move the backgrounds element into the slide container to + // that the same scaling is applied + dom.slides.appendChild( dom.background ); + + // Clicking on an overview slide navigates to it + toArray( dom.wrapper.querySelectorAll( SLIDES_SELECTOR ) ).forEach( function( slide ) { + if( !slide.classList.contains( 'stack' ) ) { + slide.addEventListener( 'click', onOverviewSlideClicked, true ); + } + } ); + + // Calculate slide sizes + var margin = 70; + var slideSize = getComputedSlideSize(); + overviewSlideWidth = slideSize.width + margin; + overviewSlideHeight = slideSize.height + margin; + + // Reverse in RTL mode + if( config.rtl ) { + overviewSlideWidth = -overviewSlideWidth; + } + + updateSlidesVisibility(); + layoutOverview(); + updateOverview(); + + layout(); + + // Notify observers of the overview showing + dispatchEvent( 'overviewshown', { + 'indexh': indexh, + 'indexv': indexv, + 'currentSlide': currentSlide + } ); + + } + + } + + /** + * Uses CSS transforms to position all slides in a grid for + * display inside of the overview mode. + */ + function layoutOverview() { + + // Layout slides + toArray( dom.wrapper.querySelectorAll( HORIZONTAL_SLIDES_SELECTOR ) ).forEach( function( hslide, h ) { + hslide.setAttribute( 'data-index-h', h ); + transformElement( hslide, 'translate3d(' + ( h * overviewSlideWidth ) + 'px, 0, 0)' ); + + if( hslide.classList.contains( 'stack' ) ) { + + toArray( hslide.querySelectorAll( 'section' ) ).forEach( function( vslide, v ) { + vslide.setAttribute( 'data-index-h', h ); + vslide.setAttribute( 'data-index-v', v ); + + transformElement( vslide, 'translate3d(0, ' + ( v * overviewSlideHeight ) + 'px, 0)' ); + } ); + + } + } ); + + // Layout slide backgrounds + toArray( dom.background.childNodes ).forEach( function( hbackground, h ) { + transformElement( hbackground, 'translate3d(' + ( h * overviewSlideWidth ) + 'px, 0, 0)' ); + + toArray( hbackground.querySelectorAll( '.slide-background' ) ).forEach( function( vbackground, v ) { + transformElement( vbackground, 'translate3d(0, ' + ( v * overviewSlideHeight ) + 'px, 0)' ); + } ); + } ); + + } + + /** + * Moves the overview viewport to the current slides. + * Called each time the current slide changes. + */ + function updateOverview() { + + var vmin = Math.min( window.innerWidth, window.innerHeight ); + var scale = Math.max( vmin / 5, 150 ) / vmin; + + transformSlides( { + overview: [ + 'scale('+ scale +')', + 'translateX('+ ( -indexh * overviewSlideWidth ) +'px)', + 'translateY('+ ( -indexv * overviewSlideHeight ) +'px)' + ].join( ' ' ) + } ); + + } + + /** + * Exits the slide overview and enters the currently + * active slide. + */ + function deactivateOverview() { + + // Only proceed if enabled in config + if( config.overview ) { + + overview = false; + + dom.wrapper.classList.remove( 'overview' ); + dom.wrapper.classList.remove( 'overview-animated' ); + + // Temporarily add a class so that transitions can do different things + // depending on whether they are exiting/entering overview, or just + // moving from slide to slide + dom.wrapper.classList.add( 'overview-deactivating' ); + + setTimeout( function () { + dom.wrapper.classList.remove( 'overview-deactivating' ); + }, 1 ); + + // Move the background element back out + dom.wrapper.appendChild( dom.background ); + + // Clean up changes made to slides + toArray( dom.wrapper.querySelectorAll( SLIDES_SELECTOR ) ).forEach( function( slide ) { + transformElement( slide, '' ); + + slide.removeEventListener( 'click', onOverviewSlideClicked, true ); + } ); + + // Clean up changes made to backgrounds + toArray( dom.background.querySelectorAll( '.slide-background' ) ).forEach( function( background ) { + transformElement( background, '' ); + } ); + + transformSlides( { overview: '' } ); + + slide( indexh, indexv ); + + layout(); + + cueAutoSlide(); + + // Notify observers of the overview hiding + dispatchEvent( 'overviewhidden', { + 'indexh': indexh, + 'indexv': indexv, + 'currentSlide': currentSlide + } ); + + } + } + + /** + * Toggles the slide overview mode on and off. + * + * @param {Boolean} [override] Flag which overrides the + * toggle logic and forcibly sets the desired state. True means + * overview is open, false means it's closed. + */ + function toggleOverview( override ) { + + if( typeof override === 'boolean' ) { + override ? activateOverview() : deactivateOverview(); + } + else { + isOverview() ? deactivateOverview() : activateOverview(); + } + + } + + /** + * Checks if the overview is currently active. + * + * @return {Boolean} true if the overview is active, + * false otherwise + */ + function isOverview() { + + return overview; + + } + + /** + * Return a hash URL that will resolve to the given slide location. + * + * @param {HTMLElement} [slide=currentSlide] The slide to link to + */ + function locationHash( slide ) { + + var url = '/'; + + // Attempt to create a named link based on the slide's ID + var s = slide || currentSlide; + var id = s ? s.getAttribute( 'id' ) : null; + if( id ) { + id = encodeURIComponent( id ); + } + + var index = getIndices( slide ); + if( !config.fragmentInURL ) { + index.f = undefined; + } + + // If the current slide has an ID, use that as a named link, + // but we don't support named links with a fragment index + if( typeof id === 'string' && id.length && index.f === undefined ) { + url = '/' + id; + } + // Otherwise use the /h/v index + else { + var hashIndexBase = config.hashOneBasedIndex ? 1 : 0; + if( index.h > 0 || index.v > 0 || index.f !== undefined ) url += index.h + hashIndexBase; + if( index.v > 0 || index.f !== undefined ) url += '/' + (index.v + hashIndexBase ); + if( index.f !== undefined ) url += '/' + index.f; + } + + return url; + + } + + /** + * Checks if the current or specified slide is vertical + * (nested within another slide). + * + * @param {HTMLElement} [slide=currentSlide] The slide to check + * orientation of + * @return {Boolean} + */ + function isVerticalSlide( slide ) { + + // Prefer slide argument, otherwise use current slide + slide = slide ? slide : currentSlide; + + return slide && slide.parentNode && !!slide.parentNode.nodeName.match( /section/i ); + + } + + /** + * Handling the fullscreen functionality via the fullscreen API + * + * @see http://fullscreen.spec.whatwg.org/ + * @see https://developer.mozilla.org/en-US/docs/DOM/Using_fullscreen_mode + */ + function enterFullscreen() { + + var element = document.documentElement; + + // Check which implementation is available + var requestMethod = element.requestFullscreen || + element.webkitRequestFullscreen || + element.webkitRequestFullScreen || + element.mozRequestFullScreen || + element.msRequestFullscreen; + + if( requestMethod ) { + requestMethod.apply( element ); + } + + } + + /** + * Shows the mouse pointer after it has been hidden with + * #hideCursor. + */ + function showCursor() { + + if( cursorHidden ) { + cursorHidden = false; + dom.wrapper.style.cursor = ''; + } + + } + + /** + * Hides the mouse pointer when it's on top of the .reveal + * container. + */ + function hideCursor() { + + if( cursorHidden === false ) { + cursorHidden = true; + dom.wrapper.style.cursor = 'none'; + } + + } + + /** + * Enters the paused mode which fades everything on screen to + * black. + */ + function pause() { + + if( config.pause ) { + var wasPaused = dom.wrapper.classList.contains( 'paused' ); + + cancelAutoSlide(); + dom.wrapper.classList.add( 'paused' ); + + if( wasPaused === false ) { + dispatchEvent( 'paused' ); + } + } + + } + + /** + * Exits from the paused mode. + */ + function resume() { + + var wasPaused = dom.wrapper.classList.contains( 'paused' ); + dom.wrapper.classList.remove( 'paused' ); + + cueAutoSlide(); + + if( wasPaused ) { + dispatchEvent( 'resumed' ); + } + + } + + /** + * Toggles the paused mode on and off. + */ + function togglePause( override ) { + + if( typeof override === 'boolean' ) { + override ? pause() : resume(); + } + else { + isPaused() ? resume() : pause(); + } + + } + + /** + * Checks if we are currently in the paused mode. + * + * @return {Boolean} + */ + function isPaused() { + + return dom.wrapper.classList.contains( 'paused' ); + + } + + /** + * Toggles the auto slide mode on and off. + * + * @param {Boolean} [override] Flag which sets the desired state. + * True means autoplay starts, false means it stops. + */ + + function toggleAutoSlide( override ) { + + if( typeof override === 'boolean' ) { + override ? resumeAutoSlide() : pauseAutoSlide(); + } + + else { + autoSlidePaused ? resumeAutoSlide() : pauseAutoSlide(); + } + + } + + /** + * Checks if the auto slide mode is currently on. + * + * @return {Boolean} + */ + function isAutoSliding() { + + return !!( autoSlide && !autoSlidePaused ); + + } + + /** + * Steps from the current point in the presentation to the + * slide which matches the specified horizontal and vertical + * indices. + * + * @param {number} [h=indexh] Horizontal index of the target slide + * @param {number} [v=indexv] Vertical index of the target slide + * @param {number} [f] Index of a fragment within the + * target slide to activate + * @param {number} [o] Origin for use in multimaster environments + */ + function slide( h, v, f, o ) { + + // Remember where we were at before + previousSlide = currentSlide; + + // Query all horizontal slides in the deck + var horizontalSlides = dom.wrapper.querySelectorAll( HORIZONTAL_SLIDES_SELECTOR ); + + // Abort if there are no slides + if( horizontalSlides.length === 0 ) return; + + // If no vertical index is specified and the upcoming slide is a + // stack, resume at its previous vertical index + if( v === undefined && !isOverview() ) { + v = getPreviousVerticalIndex( horizontalSlides[ h ] ); + } + + // If we were on a vertical stack, remember what vertical index + // it was on so we can resume at the same position when returning + if( previousSlide && previousSlide.parentNode && previousSlide.parentNode.classList.contains( 'stack' ) ) { + setPreviousVerticalIndex( previousSlide.parentNode, indexv ); + } + + // Remember the state before this slide + var stateBefore = state.concat(); + + // Reset the state array + state.length = 0; + + var indexhBefore = indexh || 0, + indexvBefore = indexv || 0; + + // Activate and transition to the new slide + indexh = updateSlides( HORIZONTAL_SLIDES_SELECTOR, h === undefined ? indexh : h ); + indexv = updateSlides( VERTICAL_SLIDES_SELECTOR, v === undefined ? indexv : v ); + + // Update the visibility of slides now that the indices have changed + updateSlidesVisibility(); + + layout(); + + // Update the overview if it's currently active + if( isOverview() ) { + updateOverview(); + } + + // Find the current horizontal slide and any possible vertical slides + // within it + var currentHorizontalSlide = horizontalSlides[ indexh ], + currentVerticalSlides = currentHorizontalSlide.querySelectorAll( 'section' ); + + // Store references to the previous and current slides + currentSlide = currentVerticalSlides[ indexv ] || currentHorizontalSlide; + + // Show fragment, if specified + if( typeof f !== 'undefined' ) { + navigateFragment( f ); + } + + // Dispatch an event if the slide changed + var slideChanged = ( indexh !== indexhBefore || indexv !== indexvBefore ); + if (!slideChanged) { + // Ensure that the previous slide is never the same as the current + previousSlide = null; + } + + // Solves an edge case where the previous slide maintains the + // 'present' class when navigating between adjacent vertical + // stacks + if( previousSlide && previousSlide !== currentSlide ) { + previousSlide.classList.remove( 'present' ); + previousSlide.setAttribute( 'aria-hidden', 'true' ); + + // Reset all slides upon navigate to home + // Issue: #285 + if ( dom.wrapper.querySelector( HOME_SLIDE_SELECTOR ).classList.contains( 'present' ) ) { + // Launch async task + setTimeout( function () { + var slides = toArray( dom.wrapper.querySelectorAll( HORIZONTAL_SLIDES_SELECTOR + '.stack') ), i; + for( i in slides ) { + if( slides[i] ) { + // Reset stack + setPreviousVerticalIndex( slides[i], 0 ); + } + } + }, 0 ); + } + } + + // Apply the new state + stateLoop: for( var i = 0, len = state.length; i < len; i++ ) { + // Check if this state existed on the previous slide. If it + // did, we will avoid adding it repeatedly + for( var j = 0; j < stateBefore.length; j++ ) { + if( stateBefore[j] === state[i] ) { + stateBefore.splice( j, 1 ); + continue stateLoop; + } + } + + document.documentElement.classList.add( state[i] ); + + // Dispatch custom event matching the state's name + dispatchEvent( state[i] ); + } + + // Clean up the remains of the previous state + while( stateBefore.length ) { + document.documentElement.classList.remove( stateBefore.pop() ); + } + + if( slideChanged ) { + dispatchEvent( 'slidechanged', { + 'indexh': indexh, + 'indexv': indexv, + 'previousSlide': previousSlide, + 'currentSlide': currentSlide, + 'origin': o + } ); + } + + // Handle embedded content + if( slideChanged || !previousSlide ) { + stopEmbeddedContent( previousSlide ); + startEmbeddedContent( currentSlide ); + } + + // Announce the current slide contents, for screen readers + dom.statusDiv.textContent = getStatusText( currentSlide ); + + updateControls(); + updateProgress(); + updateBackground(); + updateParallax(); + updateSlideNumber(); + updateNotes(); + updateFragments(); + + // Update the URL hash + writeURL(); + + cueAutoSlide(); + + } + + /** + * Syncs the presentation with the current DOM. Useful + * when new slides or control elements are added or when + * the configuration has changed. + */ + function sync() { + + // Subscribe to input + removeEventListeners(); + addEventListeners(); + + // Force a layout to make sure the current config is accounted for + layout(); + + // Reflect the current autoSlide value + autoSlide = config.autoSlide; + + // Start auto-sliding if it's enabled + cueAutoSlide(); + + // Re-create the slide backgrounds + createBackgrounds(); + + // Write the current hash to the URL + writeURL(); + + sortAllFragments(); + + updateControls(); + updateProgress(); + updateSlideNumber(); + updateSlidesVisibility(); + updateBackground( true ); + updateNotesVisibility(); + updateNotes(); + + formatEmbeddedContent(); + + // Start or stop embedded content depending on global config + if( config.autoPlayMedia === false ) { + stopEmbeddedContent( currentSlide, { unloadIframes: false } ); + } + else { + startEmbeddedContent( currentSlide ); + } + + if( isOverview() ) { + layoutOverview(); + } + + } + + /** + * Updates reveal.js to keep in sync with new slide attributes. For + * example, if you add a new `data-background-image` you can call + * this to have reveal.js render the new background image. + * + * Similar to #sync() but more efficient when you only need to + * refresh a specific slide. + * + * @param {HTMLElement} slide + */ + function syncSlide( slide ) { + + // Default to the current slide + slide = slide || currentSlide; + + syncBackground( slide ); + syncFragments( slide ); + + loadSlide( slide ); + + updateBackground(); + updateNotes(); + + } + + /** + * Formats the fragments on the given slide so that they have + * valid indices. Call this if fragments are changed in the DOM + * after reveal.js has already initialized. + * + * @param {HTMLElement} slide + * @return {Array} a list of the HTML fragments that were synced + */ + function syncFragments( slide ) { + + // Default to the current slide + slide = slide || currentSlide; + + return sortFragments( slide.querySelectorAll( '.fragment' ) ); + + } + + /** + * Resets all vertical slides so that only the first + * is visible. + */ + function resetVerticalSlides() { + + var horizontalSlides = toArray( dom.wrapper.querySelectorAll( HORIZONTAL_SLIDES_SELECTOR ) ); + horizontalSlides.forEach( function( horizontalSlide ) { + + var verticalSlides = toArray( horizontalSlide.querySelectorAll( 'section' ) ); + verticalSlides.forEach( function( verticalSlide, y ) { + + if( y > 0 ) { + verticalSlide.classList.remove( 'present' ); + verticalSlide.classList.remove( 'past' ); + verticalSlide.classList.add( 'future' ); + verticalSlide.setAttribute( 'aria-hidden', 'true' ); + } + + } ); + + } ); + + } + + /** + * Sorts and formats all of fragments in the + * presentation. + */ + function sortAllFragments() { + + var horizontalSlides = toArray( dom.wrapper.querySelectorAll( HORIZONTAL_SLIDES_SELECTOR ) ); + horizontalSlides.forEach( function( horizontalSlide ) { + + var verticalSlides = toArray( horizontalSlide.querySelectorAll( 'section' ) ); + verticalSlides.forEach( function( verticalSlide, y ) { + + sortFragments( verticalSlide.querySelectorAll( '.fragment' ) ); + + } ); + + if( verticalSlides.length === 0 ) sortFragments( horizontalSlide.querySelectorAll( '.fragment' ) ); + + } ); + + } + + /** + * Randomly shuffles all slides in the deck. + */ + function shuffle() { + + var slides = toArray( dom.wrapper.querySelectorAll( HORIZONTAL_SLIDES_SELECTOR ) ); + + slides.forEach( function( slide ) { + + // Insert this slide next to another random slide. This may + // cause the slide to insert before itself but that's fine. + dom.slides.insertBefore( slide, slides[ Math.floor( Math.random() * slides.length ) ] ); + + } ); + + } + + /** + * Updates one dimension of slides by showing the slide + * with the specified index. + * + * @param {string} selector A CSS selector that will fetch + * the group of slides we are working with + * @param {number} index The index of the slide that should be + * shown + * + * @return {number} The index of the slide that is now shown, + * might differ from the passed in index if it was out of + * bounds. + */ + function updateSlides( selector, index ) { + + // Select all slides and convert the NodeList result to + // an array + var slides = toArray( dom.wrapper.querySelectorAll( selector ) ), + slidesLength = slides.length; + + var printMode = isPrintingPDF(); + + if( slidesLength ) { + + // Should the index loop? + if( config.loop ) { + index %= slidesLength; + + if( index < 0 ) { + index = slidesLength + index; + } + } + + // Enforce max and minimum index bounds + index = Math.max( Math.min( index, slidesLength - 1 ), 0 ); + + for( var i = 0; i < slidesLength; i++ ) { + var element = slides[i]; + + var reverse = config.rtl && !isVerticalSlide( element ); + + element.classList.remove( 'past' ); + element.classList.remove( 'present' ); + element.classList.remove( 'future' ); + + // http://www.w3.org/html/wg/drafts/html/master/editing.html#the-hidden-attribute + element.setAttribute( 'hidden', '' ); + element.setAttribute( 'aria-hidden', 'true' ); + + // If this element contains vertical slides + if( element.querySelector( 'section' ) ) { + element.classList.add( 'stack' ); + } + + // If we're printing static slides, all slides are "present" + if( printMode ) { + element.classList.add( 'present' ); + continue; + } + + if( i < index ) { + // Any element previous to index is given the 'past' class + element.classList.add( reverse ? 'future' : 'past' ); + + if( config.fragments ) { + // Show all fragments in prior slides + toArray( element.querySelectorAll( '.fragment' ) ).forEach( function( fragment ) { + fragment.classList.add( 'visible' ); + fragment.classList.remove( 'current-fragment' ); + } ); + } + } + else if( i > index ) { + // Any element subsequent to index is given the 'future' class + element.classList.add( reverse ? 'past' : 'future' ); + + if( config.fragments ) { + // Hide all fragments in future slides + toArray( element.querySelectorAll( '.fragment.visible' ) ).forEach( function( fragment ) { + fragment.classList.remove( 'visible' ); + fragment.classList.remove( 'current-fragment' ); + } ); + } + } + } + + // Mark the current slide as present + slides[index].classList.add( 'present' ); + slides[index].removeAttribute( 'hidden' ); + slides[index].removeAttribute( 'aria-hidden' ); + + // If this slide has a state associated with it, add it + // onto the current state of the deck + var slideState = slides[index].getAttribute( 'data-state' ); + if( slideState ) { + state = state.concat( slideState.split( ' ' ) ); + } + + } + else { + // Since there are no slides we can't be anywhere beyond the + // zeroth index + index = 0; + } + + return index; + + } + + /** + * Optimization method; hide all slides that are far away + * from the present slide. + */ + function updateSlidesVisibility() { + + // Select all slides and convert the NodeList result to + // an array + var horizontalSlides = toArray( dom.wrapper.querySelectorAll( HORIZONTAL_SLIDES_SELECTOR ) ), + horizontalSlidesLength = horizontalSlides.length, + distanceX, + distanceY; + + if( horizontalSlidesLength && typeof indexh !== 'undefined' ) { + + // The number of steps away from the present slide that will + // be visible + var viewDistance = isOverview() ? 10 : config.viewDistance; + + // Shorten the view distance on devices that typically have + // less resources + if( isMobileDevice ) { + viewDistance = isOverview() ? 6 : config.mobileViewDistance; + } + + // All slides need to be visible when exporting to PDF + if( isPrintingPDF() ) { + viewDistance = Number.MAX_VALUE; + } + + for( var x = 0; x < horizontalSlidesLength; x++ ) { + var horizontalSlide = horizontalSlides[x]; + + var verticalSlides = toArray( horizontalSlide.querySelectorAll( 'section' ) ), + verticalSlidesLength = verticalSlides.length; + + // Determine how far away this slide is from the present + distanceX = Math.abs( ( indexh || 0 ) - x ) || 0; + + // If the presentation is looped, distance should measure + // 1 between the first and last slides + if( config.loop ) { + distanceX = Math.abs( ( ( indexh || 0 ) - x ) % ( horizontalSlidesLength - viewDistance ) ) || 0; + } + + // Show the horizontal slide if it's within the view distance + if( distanceX < viewDistance ) { + loadSlide( horizontalSlide ); + } + else { + unloadSlide( horizontalSlide ); + } + + if( verticalSlidesLength ) { + + var oy = getPreviousVerticalIndex( horizontalSlide ); + + for( var y = 0; y < verticalSlidesLength; y++ ) { + var verticalSlide = verticalSlides[y]; + + distanceY = x === ( indexh || 0 ) ? Math.abs( ( indexv || 0 ) - y ) : Math.abs( y - oy ); + + if( distanceX + distanceY < viewDistance ) { + loadSlide( verticalSlide ); + } + else { + unloadSlide( verticalSlide ); + } + } + + } + } + + // Flag if there are ANY vertical slides, anywhere in the deck + if( hasVerticalSlides() ) { + dom.wrapper.classList.add( 'has-vertical-slides' ); + } + else { + dom.wrapper.classList.remove( 'has-vertical-slides' ); + } + + // Flag if there are ANY horizontal slides, anywhere in the deck + if( hasHorizontalSlides() ) { + dom.wrapper.classList.add( 'has-horizontal-slides' ); + } + else { + dom.wrapper.classList.remove( 'has-horizontal-slides' ); + } + + } + + } + + /** + * Pick up notes from the current slide and display them + * to the viewer. + * + * @see {@link config.showNotes} + */ + function updateNotes() { + + if( config.showNotes && dom.speakerNotes && currentSlide && !isPrintingPDF() ) { + + dom.speakerNotes.innerHTML = getSlideNotes() || 'No notes on this slide.'; + + } + + } + + /** + * Updates the visibility of the speaker notes sidebar that + * is used to share annotated slides. The notes sidebar is + * only visible if showNotes is true and there are notes on + * one or more slides in the deck. + */ + function updateNotesVisibility() { + + if( config.showNotes && hasNotes() ) { + dom.wrapper.classList.add( 'show-notes' ); + } + else { + dom.wrapper.classList.remove( 'show-notes' ); + } + + } + + /** + * Checks if there are speaker notes for ANY slide in the + * presentation. + */ + function hasNotes() { + + return dom.slides.querySelectorAll( '[data-notes], aside.notes' ).length > 0; + + } + + /** + * Updates the progress bar to reflect the current slide. + */ + function updateProgress() { + + // Update progress if enabled + if( config.progress && dom.progressbar ) { + + dom.progressbar.style.width = getProgress() * dom.wrapper.offsetWidth + 'px'; + + } + + } + + + /** + * Updates the slide number to match the current slide. + */ + function updateSlideNumber() { + + // Update slide number if enabled + if( config.slideNumber && dom.slideNumber ) { + dom.slideNumber.innerHTML = getSlideNumber(); + } + + } + + /** + * Returns the HTML string corresponding to the current slide number, + * including formatting. + */ + function getSlideNumber( slide ) { + + var value; + var format = 'h.v'; + if( slide === undefined ) { + slide = currentSlide; + } + + if ( typeof config.slideNumber === 'function' ) { + value = config.slideNumber( slide ); + } else { + // Check if a custom number format is available + if( typeof config.slideNumber === 'string' ) { + format = config.slideNumber; + } + + // If there are ONLY vertical slides in this deck, always use + // a flattened slide number + if( !/c/.test( format ) && dom.wrapper.querySelectorAll( HORIZONTAL_SLIDES_SELECTOR ).length === 1 ) { + format = 'c'; + } + + value = []; + switch( format ) { + case 'c': + value.push( getSlidePastCount( slide ) + 1 ); + break; + case 'c/t': + value.push( getSlidePastCount( slide ) + 1, '/', getTotalSlides() ); + break; + default: + var indices = getIndices( slide ); + value.push( indices.h + 1 ); + var sep = format === 'h/v' ? '/' : '.'; + if( isVerticalSlide( slide ) ) value.push( sep, indices.v + 1 ); + } + } + + var url = '#' + locationHash( slide ); + return formatSlideNumber( value[0], value[1], value[2], url ); + + } + + /** + * Applies HTML formatting to a slide number before it's + * written to the DOM. + * + * @param {number} a Current slide + * @param {string} delimiter Character to separate slide numbers + * @param {(number|*)} b Total slides + * @param {HTMLElement} [url='#'+locationHash()] The url to link to + * @return {string} HTML string fragment + */ + function formatSlideNumber( a, delimiter, b, url ) { + + if( url === undefined ) { + url = '#' + locationHash(); + } + if( typeof b === 'number' && !isNaN( b ) ) { + return '' + + ''+ a +'' + + ''+ delimiter +'' + + ''+ b +'' + + ''; + } + else { + return '' + + ''+ a +'' + + ''; + } + + } + + /** + * Updates the state of all control/navigation arrows. + */ + function updateControls() { + + var routes = availableRoutes(); + var fragments = availableFragments(); + + // Remove the 'enabled' class from all directions + dom.controlsLeft.concat( dom.controlsRight ) + .concat( dom.controlsUp ) + .concat( dom.controlsDown ) + .concat( dom.controlsPrev ) + .concat( dom.controlsNext ).forEach( function( node ) { + node.classList.remove( 'enabled' ); + node.classList.remove( 'fragmented' ); + + // Set 'disabled' attribute on all directions + node.setAttribute( 'disabled', 'disabled' ); + } ); + + // Add the 'enabled' class to the available routes; remove 'disabled' attribute to enable buttons + if( routes.left ) dom.controlsLeft.forEach( function( el ) { el.classList.add( 'enabled' ); el.removeAttribute( 'disabled' ); } ); + if( routes.right ) dom.controlsRight.forEach( function( el ) { el.classList.add( 'enabled' ); el.removeAttribute( 'disabled' ); } ); + if( routes.up ) dom.controlsUp.forEach( function( el ) { el.classList.add( 'enabled' ); el.removeAttribute( 'disabled' ); } ); + if( routes.down ) dom.controlsDown.forEach( function( el ) { el.classList.add( 'enabled' ); el.removeAttribute( 'disabled' ); } ); + + // Prev/next buttons + if( routes.left || routes.up ) dom.controlsPrev.forEach( function( el ) { el.classList.add( 'enabled' ); el.removeAttribute( 'disabled' ); } ); + if( routes.right || routes.down ) dom.controlsNext.forEach( function( el ) { el.classList.add( 'enabled' ); el.removeAttribute( 'disabled' ); } ); + + // Highlight fragment directions + if( currentSlide ) { + + // Always apply fragment decorator to prev/next buttons + if( fragments.prev ) dom.controlsPrev.forEach( function( el ) { el.classList.add( 'fragmented', 'enabled' ); el.removeAttribute( 'disabled' ); } ); + if( fragments.next ) dom.controlsNext.forEach( function( el ) { el.classList.add( 'fragmented', 'enabled' ); el.removeAttribute( 'disabled' ); } ); + + // Apply fragment decorators to directional buttons based on + // what slide axis they are in + if( isVerticalSlide( currentSlide ) ) { + if( fragments.prev ) dom.controlsUp.forEach( function( el ) { el.classList.add( 'fragmented', 'enabled' ); el.removeAttribute( 'disabled' ); } ); + if( fragments.next ) dom.controlsDown.forEach( function( el ) { el.classList.add( 'fragmented', 'enabled' ); el.removeAttribute( 'disabled' ); } ); + } + else { + if( fragments.prev ) dom.controlsLeft.forEach( function( el ) { el.classList.add( 'fragmented', 'enabled' ); el.removeAttribute( 'disabled' ); } ); + if( fragments.next ) dom.controlsRight.forEach( function( el ) { el.classList.add( 'fragmented', 'enabled' ); el.removeAttribute( 'disabled' ); } ); + } + + } + + if( config.controlsTutorial ) { + + // Highlight control arrows with an animation to ensure + // that the viewer knows how to navigate + if( !hasNavigatedDown && routes.down ) { + dom.controlsDownArrow.classList.add( 'highlight' ); + } + else { + dom.controlsDownArrow.classList.remove( 'highlight' ); + + if( !hasNavigatedRight && routes.right && indexv === 0 ) { + dom.controlsRightArrow.classList.add( 'highlight' ); + } + else { + dom.controlsRightArrow.classList.remove( 'highlight' ); + } + } + + } + + } + + /** + * Updates the background elements to reflect the current + * slide. + * + * @param {boolean} includeAll If true, the backgrounds of + * all vertical slides (not just the present) will be updated. + */ + function updateBackground( includeAll ) { + + var currentBackground = null; + + // Reverse past/future classes when in RTL mode + var horizontalPast = config.rtl ? 'future' : 'past', + horizontalFuture = config.rtl ? 'past' : 'future'; + + // Update the classes of all backgrounds to match the + // states of their slides (past/present/future) + toArray( dom.background.childNodes ).forEach( function( backgroundh, h ) { + + backgroundh.classList.remove( 'past' ); + backgroundh.classList.remove( 'present' ); + backgroundh.classList.remove( 'future' ); + + if( h < indexh ) { + backgroundh.classList.add( horizontalPast ); + } + else if ( h > indexh ) { + backgroundh.classList.add( horizontalFuture ); + } + else { + backgroundh.classList.add( 'present' ); + + // Store a reference to the current background element + currentBackground = backgroundh; + } + + if( includeAll || h === indexh ) { + toArray( backgroundh.querySelectorAll( '.slide-background' ) ).forEach( function( backgroundv, v ) { + + backgroundv.classList.remove( 'past' ); + backgroundv.classList.remove( 'present' ); + backgroundv.classList.remove( 'future' ); + + if( v < indexv ) { + backgroundv.classList.add( 'past' ); + } + else if ( v > indexv ) { + backgroundv.classList.add( 'future' ); + } + else { + backgroundv.classList.add( 'present' ); + + // Only if this is the present horizontal and vertical slide + if( h === indexh ) currentBackground = backgroundv; + } + + } ); + } + + } ); + + // Stop content inside of previous backgrounds + if( previousBackground ) { + + stopEmbeddedContent( previousBackground, { unloadIframes: !shouldPreload( previousBackground ) } ); + + } + + // Start content in the current background + if( currentBackground ) { + + startEmbeddedContent( currentBackground ); + + var currentBackgroundContent = currentBackground.querySelector( '.slide-background-content' ); + if( currentBackgroundContent ) { + + var backgroundImageURL = currentBackgroundContent.style.backgroundImage || ''; + + // Restart GIFs (doesn't work in Firefox) + if( /\.gif/i.test( backgroundImageURL ) ) { + currentBackgroundContent.style.backgroundImage = ''; + window.getComputedStyle( currentBackgroundContent ).opacity; + currentBackgroundContent.style.backgroundImage = backgroundImageURL; + } + + } + + // Don't transition between identical backgrounds. This + // prevents unwanted flicker. + var previousBackgroundHash = previousBackground ? previousBackground.getAttribute( 'data-background-hash' ) : null; + var currentBackgroundHash = currentBackground.getAttribute( 'data-background-hash' ); + if( currentBackgroundHash && currentBackgroundHash === previousBackgroundHash && currentBackground !== previousBackground ) { + dom.background.classList.add( 'no-transition' ); + } + + previousBackground = currentBackground; + + } + + // If there's a background brightness flag for this slide, + // bubble it to the .reveal container + if( currentSlide ) { + [ 'has-light-background', 'has-dark-background' ].forEach( function( classToBubble ) { + if( currentSlide.classList.contains( classToBubble ) ) { + dom.wrapper.classList.add( classToBubble ); + } + else { + dom.wrapper.classList.remove( classToBubble ); + } + } ); + } + + // Allow the first background to apply without transition + setTimeout( function() { + dom.background.classList.remove( 'no-transition' ); + }, 1 ); + + } + + /** + * Updates the position of the parallax background based + * on the current slide index. + */ + function updateParallax() { + + if( config.parallaxBackgroundImage ) { + + var horizontalSlides = dom.wrapper.querySelectorAll( HORIZONTAL_SLIDES_SELECTOR ), + verticalSlides = dom.wrapper.querySelectorAll( VERTICAL_SLIDES_SELECTOR ); + + var backgroundSize = dom.background.style.backgroundSize.split( ' ' ), + backgroundWidth, backgroundHeight; + + if( backgroundSize.length === 1 ) { + backgroundWidth = backgroundHeight = parseInt( backgroundSize[0], 10 ); + } + else { + backgroundWidth = parseInt( backgroundSize[0], 10 ); + backgroundHeight = parseInt( backgroundSize[1], 10 ); + } + + var slideWidth = dom.background.offsetWidth, + horizontalSlideCount = horizontalSlides.length, + horizontalOffsetMultiplier, + horizontalOffset; + + if( typeof config.parallaxBackgroundHorizontal === 'number' ) { + horizontalOffsetMultiplier = config.parallaxBackgroundHorizontal; + } + else { + horizontalOffsetMultiplier = horizontalSlideCount > 1 ? ( backgroundWidth - slideWidth ) / ( horizontalSlideCount-1 ) : 0; + } + + horizontalOffset = horizontalOffsetMultiplier * indexh * -1; + + var slideHeight = dom.background.offsetHeight, + verticalSlideCount = verticalSlides.length, + verticalOffsetMultiplier, + verticalOffset; + + if( typeof config.parallaxBackgroundVertical === 'number' ) { + verticalOffsetMultiplier = config.parallaxBackgroundVertical; + } + else { + verticalOffsetMultiplier = ( backgroundHeight - slideHeight ) / ( verticalSlideCount-1 ); + } + + verticalOffset = verticalSlideCount > 0 ? verticalOffsetMultiplier * indexv : 0; + + dom.background.style.backgroundPosition = horizontalOffset + 'px ' + -verticalOffset + 'px'; + + } + + } + + /** + * Should the given element be preloaded? + * Decides based on local element attributes and global config. + * + * @param {HTMLElement} element + */ + function shouldPreload( element ) { + + // Prefer an explicit global preload setting + var preload = config.preloadIframes; + + // If no global setting is available, fall back on the element's + // own preload setting + if( typeof preload !== 'boolean' ) { + preload = element.hasAttribute( 'data-preload' ); + } + + return preload; + } + + /** + * Called when the given slide is within the configured view + * distance. Shows the slide element and loads any content + * that is set to load lazily (data-src). + * + * @param {HTMLElement} slide Slide to show + */ + function loadSlide( slide, options ) { + + options = options || {}; + + // Show the slide element + slide.style.display = config.display; + + // Media elements with data-src attributes + toArray( slide.querySelectorAll( 'img[data-src], video[data-src], audio[data-src], iframe[data-src]' ) ).forEach( function( element ) { + if( element.tagName !== 'IFRAME' || shouldPreload( element ) ) { + element.setAttribute( 'src', element.getAttribute( 'data-src' ) ); + element.setAttribute( 'data-lazy-loaded', '' ); + element.removeAttribute( 'data-src' ); + } + } ); + + // Media elements with children + toArray( slide.querySelectorAll( 'video, audio' ) ).forEach( function( media ) { + var sources = 0; + + toArray( media.querySelectorAll( 'source[data-src]' ) ).forEach( function( source ) { + source.setAttribute( 'src', source.getAttribute( 'data-src' ) ); + source.removeAttribute( 'data-src' ); + source.setAttribute( 'data-lazy-loaded', '' ); + sources += 1; + } ); + + // If we rewrote sources for this video/audio element, we need + // to manually tell it to load from its new origin + if( sources > 0 ) { + media.load(); + } + } ); + + + // Show the corresponding background element + var background = slide.slideBackgroundElement; + if( background ) { + background.style.display = 'block'; + + var backgroundContent = slide.slideBackgroundContentElement; + var backgroundIframe = slide.getAttribute( 'data-background-iframe' ); + + // If the background contains media, load it + if( background.hasAttribute( 'data-loaded' ) === false ) { + background.setAttribute( 'data-loaded', 'true' ); + + var backgroundImage = slide.getAttribute( 'data-background-image' ), + backgroundVideo = slide.getAttribute( 'data-background-video' ), + backgroundVideoLoop = slide.hasAttribute( 'data-background-video-loop' ), + backgroundVideoMuted = slide.hasAttribute( 'data-background-video-muted' ); + + // Images + if( backgroundImage ) { + backgroundContent.style.backgroundImage = 'url('+ encodeURI( backgroundImage ) +')'; + } + // Videos + else if ( backgroundVideo && !isSpeakerNotes() ) { + var video = document.createElement( 'video' ); + + if( backgroundVideoLoop ) { + video.setAttribute( 'loop', '' ); + } + + if( backgroundVideoMuted ) { + video.muted = true; + } + + // Inline video playback works (at least in Mobile Safari) as + // long as the video is muted and the `playsinline` attribute is + // present + if( isMobileDevice ) { + video.muted = true; + video.autoplay = true; + video.setAttribute( 'playsinline', '' ); + } + + // Support comma separated lists of video sources + backgroundVideo.split( ',' ).forEach( function( source ) { + video.innerHTML += ''; + } ); + + backgroundContent.appendChild( video ); + } + // Iframes + else if( backgroundIframe && options.excludeIframes !== true ) { + var iframe = document.createElement( 'iframe' ); + iframe.setAttribute( 'allowfullscreen', '' ); + iframe.setAttribute( 'mozallowfullscreen', '' ); + iframe.setAttribute( 'webkitallowfullscreen', '' ); + iframe.setAttribute( 'allow', 'autoplay' ); + + iframe.setAttribute( 'data-src', backgroundIframe ); + + iframe.style.width = '100%'; + iframe.style.height = '100%'; + iframe.style.maxHeight = '100%'; + iframe.style.maxWidth = '100%'; + + backgroundContent.appendChild( iframe ); + } + } + + // Start loading preloadable iframes + var backgroundIframeElement = backgroundContent.querySelector( 'iframe[data-src]' ); + if( backgroundIframeElement ) { + + // Check if this iframe is eligible to be preloaded + if( shouldPreload( background ) && !/autoplay=(1|true|yes)/gi.test( backgroundIframe ) ) { + if( backgroundIframeElement.getAttribute( 'src' ) !== backgroundIframe ) { + backgroundIframeElement.setAttribute( 'src', backgroundIframe ); + } + } + + } + + } + + } + + /** + * Unloads and hides the given slide. This is called when the + * slide is moved outside of the configured view distance. + * + * @param {HTMLElement} slide + */ + function unloadSlide( slide ) { + + // Hide the slide element + slide.style.display = 'none'; + + // Hide the corresponding background element + var background = getSlideBackground( slide ); + if( background ) { + background.style.display = 'none'; + + // Unload any background iframes + toArray( background.querySelectorAll( 'iframe[src]' ) ).forEach( function( element ) { + element.removeAttribute( 'src' ); + } ); + } + + // Reset lazy-loaded media elements with src attributes + toArray( slide.querySelectorAll( 'video[data-lazy-loaded][src], audio[data-lazy-loaded][src], iframe[data-lazy-loaded][src]' ) ).forEach( function( element ) { + element.setAttribute( 'data-src', element.getAttribute( 'src' ) ); + element.removeAttribute( 'src' ); + } ); + + // Reset lazy-loaded media elements with children + toArray( slide.querySelectorAll( 'video[data-lazy-loaded] source[src], audio source[src]' ) ).forEach( function( source ) { + source.setAttribute( 'data-src', source.getAttribute( 'src' ) ); + source.removeAttribute( 'src' ); + } ); + + } + + /** + * Determine what available routes there are for navigation. + * + * @return {{left: boolean, right: boolean, up: boolean, down: boolean}} + */ + function availableRoutes() { + + var horizontalSlides = dom.wrapper.querySelectorAll( HORIZONTAL_SLIDES_SELECTOR ), + verticalSlides = dom.wrapper.querySelectorAll( VERTICAL_SLIDES_SELECTOR ); + + var routes = { + left: indexh > 0, + right: indexh < horizontalSlides.length - 1, + up: indexv > 0, + down: indexv < verticalSlides.length - 1 + }; + + // Looped presentations can always be navigated as long as + // there are slides available + if( config.loop ) { + if( horizontalSlides.length > 1 ) { + routes.left = true; + routes.right = true; + } + + if( verticalSlides.length > 1 ) { + routes.up = true; + routes.down = true; + } + } + + // Reverse horizontal controls for rtl + if( config.rtl ) { + var left = routes.left; + routes.left = routes.right; + routes.right = left; + } + + return routes; + + } + + /** + * Returns an object describing the available fragment + * directions. + * + * @return {{prev: boolean, next: boolean}} + */ + function availableFragments() { + + if( currentSlide && config.fragments ) { + var fragments = currentSlide.querySelectorAll( '.fragment' ); + var hiddenFragments = currentSlide.querySelectorAll( '.fragment:not(.visible)' ); + + return { + prev: fragments.length - hiddenFragments.length > 0, + next: !!hiddenFragments.length + }; + } + else { + return { prev: false, next: false }; + } + + } + + /** + * Enforces origin-specific format rules for embedded media. + */ + function formatEmbeddedContent() { + + var _appendParamToIframeSource = function( sourceAttribute, sourceURL, param ) { + toArray( dom.slides.querySelectorAll( 'iframe['+ sourceAttribute +'*="'+ sourceURL +'"]' ) ).forEach( function( el ) { + var src = el.getAttribute( sourceAttribute ); + if( src && src.indexOf( param ) === -1 ) { + el.setAttribute( sourceAttribute, src + ( !/\?/.test( src ) ? '?' : '&' ) + param ); + } + }); + }; + + // YouTube frames must include "?enablejsapi=1" + _appendParamToIframeSource( 'src', 'youtube.com/embed/', 'enablejsapi=1' ); + _appendParamToIframeSource( 'data-src', 'youtube.com/embed/', 'enablejsapi=1' ); + + // Vimeo frames must include "?api=1" + _appendParamToIframeSource( 'src', 'player.vimeo.com/', 'api=1' ); + _appendParamToIframeSource( 'data-src', 'player.vimeo.com/', 'api=1' ); + + } + + /** + * Start playback of any embedded content inside of + * the given element. + * + * @param {HTMLElement} element + */ + function startEmbeddedContent( element ) { + + if( element && !isSpeakerNotes() ) { + + // Restart GIFs + toArray( element.querySelectorAll( 'img[src$=".gif"]' ) ).forEach( function( el ) { + // Setting the same unchanged source like this was confirmed + // to work in Chrome, FF & Safari + el.setAttribute( 'src', el.getAttribute( 'src' ) ); + } ); + + // HTML5 media elements + toArray( element.querySelectorAll( 'video, audio' ) ).forEach( function( el ) { + if( closestParent( el, '.fragment' ) && !closestParent( el, '.fragment.visible' ) ) { + return; + } + + // Prefer an explicit global autoplay setting + var autoplay = config.autoPlayMedia; + + // If no global setting is available, fall back on the element's + // own autoplay setting + if( typeof autoplay !== 'boolean' ) { + autoplay = el.hasAttribute( 'data-autoplay' ) || !!closestParent( el, '.slide-background' ); + } + + if( autoplay && typeof el.play === 'function' ) { + + // If the media is ready, start playback + if( el.readyState > 1 ) { + startEmbeddedMedia( { target: el } ); + } + // Mobile devices never fire a loaded event so instead + // of waiting, we initiate playback + else if( isMobileDevice ) { + var promise = el.play(); + + // If autoplay does not work, ensure that the controls are visible so + // that the viewer can start the media on their own + if( promise && typeof promise.catch === 'function' && el.controls === false ) { + promise.catch( function() { + el.controls = true; + + // Once the video does start playing, hide the controls again + el.addEventListener( 'play', function() { + el.controls = false; + } ); + } ); + } + } + // If the media isn't loaded, wait before playing + else { + el.removeEventListener( 'loadeddata', startEmbeddedMedia ); // remove first to avoid dupes + el.addEventListener( 'loadeddata', startEmbeddedMedia ); + } + + } + } ); + + // Normal iframes + toArray( element.querySelectorAll( 'iframe[src]' ) ).forEach( function( el ) { + if( closestParent( el, '.fragment' ) && !closestParent( el, '.fragment.visible' ) ) { + return; + } + + startEmbeddedIframe( { target: el } ); + } ); + + // Lazy loading iframes + toArray( element.querySelectorAll( 'iframe[data-src]' ) ).forEach( function( el ) { + if( closestParent( el, '.fragment' ) && !closestParent( el, '.fragment.visible' ) ) { + return; + } + + if( el.getAttribute( 'src' ) !== el.getAttribute( 'data-src' ) ) { + el.removeEventListener( 'load', startEmbeddedIframe ); // remove first to avoid dupes + el.addEventListener( 'load', startEmbeddedIframe ); + el.setAttribute( 'src', el.getAttribute( 'data-src' ) ); + } + } ); + + } + + } + + /** + * Starts playing an embedded video/audio element after + * it has finished loading. + * + * @param {object} event + */ + function startEmbeddedMedia( event ) { + + var isAttachedToDOM = !!closestParent( event.target, 'html' ), + isVisible = !!closestParent( event.target, '.present' ); + + if( isAttachedToDOM && isVisible ) { + event.target.currentTime = 0; + event.target.play(); + } + + event.target.removeEventListener( 'loadeddata', startEmbeddedMedia ); + + } + + /** + * "Starts" the content of an embedded iframe using the + * postMessage API. + * + * @param {object} event + */ + function startEmbeddedIframe( event ) { + + var iframe = event.target; + + if( iframe && iframe.contentWindow ) { + + var isAttachedToDOM = !!closestParent( event.target, 'html' ), + isVisible = !!closestParent( event.target, '.present' ); + + if( isAttachedToDOM && isVisible ) { + + // Prefer an explicit global autoplay setting + var autoplay = config.autoPlayMedia; + + // If no global setting is available, fall back on the element's + // own autoplay setting + if( typeof autoplay !== 'boolean' ) { + autoplay = iframe.hasAttribute( 'data-autoplay' ) || !!closestParent( iframe, '.slide-background' ); + } + + // YouTube postMessage API + if( /youtube\.com\/embed\//.test( iframe.getAttribute( 'src' ) ) && autoplay ) { + iframe.contentWindow.postMessage( '{"event":"command","func":"playVideo","args":""}', '*' ); + } + // Vimeo postMessage API + else if( /player\.vimeo\.com\//.test( iframe.getAttribute( 'src' ) ) && autoplay ) { + iframe.contentWindow.postMessage( '{"method":"play"}', '*' ); + } + // Generic postMessage API + else { + iframe.contentWindow.postMessage( 'slide:start', '*' ); + } + + } + + } + + } + + /** + * Stop playback of any embedded content inside of + * the targeted slide. + * + * @param {HTMLElement} element + */ + function stopEmbeddedContent( element, options ) { + + options = extend( { + // Defaults + unloadIframes: true + }, options || {} ); + + if( element && element.parentNode ) { + // HTML5 media elements + toArray( element.querySelectorAll( 'video, audio' ) ).forEach( function( el ) { + if( !el.hasAttribute( 'data-ignore' ) && typeof el.pause === 'function' ) { + el.setAttribute('data-paused-by-reveal', ''); + el.pause(); + } + } ); + + // Generic postMessage API for non-lazy loaded iframes + toArray( element.querySelectorAll( 'iframe' ) ).forEach( function( el ) { + if( el.contentWindow ) el.contentWindow.postMessage( 'slide:stop', '*' ); + el.removeEventListener( 'load', startEmbeddedIframe ); + }); + + // YouTube postMessage API + toArray( element.querySelectorAll( 'iframe[src*="youtube.com/embed/"]' ) ).forEach( function( el ) { + if( !el.hasAttribute( 'data-ignore' ) && el.contentWindow && typeof el.contentWindow.postMessage === 'function' ) { + el.contentWindow.postMessage( '{"event":"command","func":"pauseVideo","args":""}', '*' ); + } + }); + + // Vimeo postMessage API + toArray( element.querySelectorAll( 'iframe[src*="player.vimeo.com/"]' ) ).forEach( function( el ) { + if( !el.hasAttribute( 'data-ignore' ) && el.contentWindow && typeof el.contentWindow.postMessage === 'function' ) { + el.contentWindow.postMessage( '{"method":"pause"}', '*' ); + } + }); + + if( options.unloadIframes === true ) { + // Unload lazy-loaded iframes + toArray( element.querySelectorAll( 'iframe[data-src]' ) ).forEach( function( el ) { + // Only removing the src doesn't actually unload the frame + // in all browsers (Firefox) so we set it to blank first + el.setAttribute( 'src', 'about:blank' ); + el.removeAttribute( 'src' ); + } ); + } + } + + } + + /** + * Returns the number of past slides. This can be used as a global + * flattened index for slides. + * + * @param {HTMLElement} [slide=currentSlide] The slide we're counting before + * + * @return {number} Past slide count + */ + function getSlidePastCount( slide ) { + + if( slide === undefined ) { + slide = currentSlide; + } + + var horizontalSlides = toArray( dom.wrapper.querySelectorAll( HORIZONTAL_SLIDES_SELECTOR ) ); + + // The number of past slides + var pastCount = 0; + + // Step through all slides and count the past ones + mainLoop: for( var i = 0; i < horizontalSlides.length; i++ ) { + + var horizontalSlide = horizontalSlides[i]; + var verticalSlides = toArray( horizontalSlide.querySelectorAll( 'section' ) ); + + for( var j = 0; j < verticalSlides.length; j++ ) { + + // Stop as soon as we arrive at the present + if( verticalSlides[j] === slide ) { + break mainLoop; + } + + pastCount++; + + } + + // Stop as soon as we arrive at the present + if( horizontalSlide === slide ) { + break; + } + + // Don't count the wrapping section for vertical slides + if( horizontalSlide.classList.contains( 'stack' ) === false ) { + pastCount++; + } + + } + + return pastCount; + + } + + /** + * Returns a value ranging from 0-1 that represents + * how far into the presentation we have navigated. + * + * @return {number} + */ + function getProgress() { + + // The number of past and total slides + var totalCount = getTotalSlides(); + var pastCount = getSlidePastCount(); + + if( currentSlide ) { + + var allFragments = currentSlide.querySelectorAll( '.fragment' ); + + // If there are fragments in the current slide those should be + // accounted for in the progress. + if( allFragments.length > 0 ) { + var visibleFragments = currentSlide.querySelectorAll( '.fragment.visible' ); + + // This value represents how big a portion of the slide progress + // that is made up by its fragments (0-1) + var fragmentWeight = 0.9; + + // Add fragment progress to the past slide count + pastCount += ( visibleFragments.length / allFragments.length ) * fragmentWeight; + } + + } + + return Math.min( pastCount / ( totalCount - 1 ), 1 ); + + } + + /** + * Checks if this presentation is running inside of the + * speaker notes window. + * + * @return {boolean} + */ + function isSpeakerNotes() { + + return !!window.location.search.match( /receiver/gi ); + + } + + /** + * Reads the current URL (hash) and navigates accordingly. + */ + function readURL() { + + var hash = window.location.hash; + + // Attempt to parse the hash as either an index or name + var bits = hash.slice( 2 ).split( '/' ), + name = hash.replace( /#|\//gi, '' ); + + // If the first bit is not fully numeric and there is a name we + // can assume that this is a named link + if( !/^[0-9]*$/.test( bits[0] ) && name.length ) { + var element; + + // Ensure the named link is a valid HTML ID attribute + try { + element = document.getElementById( decodeURIComponent( name ) ); + } + catch ( error ) { } + + // Ensure that we're not already on a slide with the same name + var isSameNameAsCurrentSlide = currentSlide ? currentSlide.getAttribute( 'id' ) === name : false; + + if( element ) { + // If the slide exists and is not the current slide... + if ( !isSameNameAsCurrentSlide ) { + // ...find the position of the named slide and navigate to it + var indices = Reveal.getIndices(element); + slide(indices.h, indices.v); + } + } + // If the slide doesn't exist, navigate to the current slide + else { + slide( indexh || 0, indexv || 0 ); + } + } + else { + var hashIndexBase = config.hashOneBasedIndex ? 1 : 0; + + // Read the index components of the hash + var h = ( parseInt( bits[0], 10 ) - hashIndexBase ) || 0, + v = ( parseInt( bits[1], 10 ) - hashIndexBase ) || 0, + f; + + if( config.fragmentInURL ) { + f = parseInt( bits[2], 10 ); + if( isNaN( f ) ) { + f = undefined; + } + } + + if( h !== indexh || v !== indexv || f !== undefined ) { + slide( h, v, f ); + } + } + + } + + /** + * Updates the page URL (hash) to reflect the current + * state. + * + * @param {number} delay The time in ms to wait before + * writing the hash + */ + function writeURL( delay ) { + + // Make sure there's never more than one timeout running + clearTimeout( writeURLTimeout ); + + // If a delay is specified, timeout this call + if( typeof delay === 'number' ) { + writeURLTimeout = setTimeout( writeURL, delay ); + } + else if( currentSlide ) { + // If we're configured to push to history OR the history + // API is not avaialble. + if( config.history || !window.history ) { + window.location.hash = locationHash(); + } + // If we're configured to reflect the current slide in the + // URL without pushing to history. + else if( config.hash ) { + window.history.replaceState( null, null, '#' + locationHash() ); + } + // If history and hash are both disabled, a hash may still + // be added to the URL by clicking on a href with a hash + // target. Counter this by always removing the hash. + else { + window.history.replaceState( null, null, window.location.pathname + window.location.search ); + } + } + + } + /** + * Retrieves the h/v location and fragment of the current, + * or specified, slide. + * + * @param {HTMLElement} [slide] If specified, the returned + * index will be for this slide rather than the currently + * active one + * + * @return {{h: number, v: number, f: number}} + */ + function getIndices( slide ) { + + // By default, return the current indices + var h = indexh, + v = indexv, + f; + + // If a slide is specified, return the indices of that slide + if( slide ) { + var isVertical = isVerticalSlide( slide ); + var slideh = isVertical ? slide.parentNode : slide; + + // Select all horizontal slides + var horizontalSlides = toArray( dom.wrapper.querySelectorAll( HORIZONTAL_SLIDES_SELECTOR ) ); + + // Now that we know which the horizontal slide is, get its index + h = Math.max( horizontalSlides.indexOf( slideh ), 0 ); + + // Assume we're not vertical + v = undefined; + + // If this is a vertical slide, grab the vertical index + if( isVertical ) { + v = Math.max( toArray( slide.parentNode.querySelectorAll( 'section' ) ).indexOf( slide ), 0 ); + } + } + + if( !slide && currentSlide ) { + var hasFragments = currentSlide.querySelectorAll( '.fragment' ).length > 0; + if( hasFragments ) { + var currentFragment = currentSlide.querySelector( '.current-fragment' ); + if( currentFragment && currentFragment.hasAttribute( 'data-fragment-index' ) ) { + f = parseInt( currentFragment.getAttribute( 'data-fragment-index' ), 10 ); + } + else { + f = currentSlide.querySelectorAll( '.fragment.visible' ).length - 1; + } + } + } + + return { h: h, v: v, f: f }; + + } + + /** + * Retrieves all slides in this presentation. + */ + function getSlides() { + + return toArray( dom.wrapper.querySelectorAll( SLIDES_SELECTOR + ':not(.stack)' ) ); + + } + + /** + * Returns a list of all horizontal slides in the deck. Each + * vertical stack is included as one horizontal slide in the + * resulting array. + */ + function getHorizontalSlides() { + + return toArray( dom.wrapper.querySelectorAll( HORIZONTAL_SLIDES_SELECTOR ) ); + + } + + /** + * Returns all vertical slides that exist within this deck. + */ + function getVerticalSlides() { + + return toArray( dom.wrapper.querySelectorAll( '.slides>section>section' ) ); + + } + + /** + * Returns true if there are at least two horizontal slides. + */ + function hasHorizontalSlides() { + + return getHorizontalSlides().length > 1; + } + + /** + * Returns true if there are at least two vertical slides. + */ + function hasVerticalSlides() { + + return getVerticalSlides().length > 1; + + } + + /** + * Returns an array of objects where each object represents the + * attributes on its respective slide. + */ + function getSlidesAttributes() { + + return getSlides().map( function( slide ) { + + var attributes = {}; + for( var i = 0; i < slide.attributes.length; i++ ) { + var attribute = slide.attributes[ i ]; + attributes[ attribute.name ] = attribute.value; + } + return attributes; + + } ); + + } + + /** + * Retrieves the total number of slides in this presentation. + * + * @return {number} + */ + function getTotalSlides() { + + return getSlides().length; + + } + + /** + * Returns the slide element matching the specified index. + * + * @return {HTMLElement} + */ + function getSlide( x, y ) { + + var horizontalSlide = dom.wrapper.querySelectorAll( HORIZONTAL_SLIDES_SELECTOR )[ x ]; + var verticalSlides = horizontalSlide && horizontalSlide.querySelectorAll( 'section' ); + + if( verticalSlides && verticalSlides.length && typeof y === 'number' ) { + return verticalSlides ? verticalSlides[ y ] : undefined; + } + + return horizontalSlide; + + } + + /** + * Returns the background element for the given slide. + * All slides, even the ones with no background properties + * defined, have a background element so as long as the + * index is valid an element will be returned. + * + * @param {mixed} x Horizontal background index OR a slide + * HTML element + * @param {number} y Vertical background index + * @return {(HTMLElement[]|*)} + */ + function getSlideBackground( x, y ) { + + var slide = typeof x === 'number' ? getSlide( x, y ) : x; + if( slide ) { + return slide.slideBackgroundElement; + } + + return undefined; + + } + + /** + * Retrieves the speaker notes from a slide. Notes can be + * defined in two ways: + * 1. As a data-notes attribute on the slide
+ * 2. As an